Hi, I started to look at profiling using utrace(2), so I played a bit with cc -pg. But the whole mail will be about -current without any patches.
While trying a very simple C file to play with, I found several problems when building with cc -pg (to enable profil instrumentation). $ cat test.c #include <stdio.h> int main() { printf("hello world\n"); return 0; } $ cc test.c && ./a.out hello world $ cc -pg test.c && ./a.out Segmentation fault (core dumped) This particular segfault comes from ld.so. $ egdb ./a.out (gdb) r Starting program: /tmp/a/a.out Program received signal SIGSEGV, Segmentation fault. _dl_boot (argv=<optimized out>, envp=<optimized out>, dyn_loff=11309662208, dl_data=0x720905e97fd0) at /usr/src/libexec/ld.so/loader.c:586 586 exe_obj->load_list = load_list; (gdb) bt #0 _dl_boot (argv=<optimized out>, envp=<optimized out>, dyn_loff=11309662208, dl_data=0x720905e97fd0) at /usr/src/libexec/ld.so/loader.c:586 #1 0x00000002a21c07f6 in _dl_start () at /usr/src/libexec/ld.so/amd64/ldasm.S:61 #2 0x0000000000000000 in ?? () If I correctly understood the problem, it is because a.out is a dynamic program (no -static on command line), but compiled only with static libraries, so it is without .dynamic section. $ cc -v -pg test.c OpenBSD clang version 13.0.0 Target: amd64-unknown-openbsd7.3 Thread model: posix InstalledDir: /usr/bin "/usr/bin/cc" -cc1 -triple amd64-unknown-openbsd7.3 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name test.c -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -v -fcoverage-compilation-dir=/tmp/a -resource-dir /usr/lib/clang/13.0.0 -internal-isystem /usr/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/tmp/a -ferror-limit 19 -pg -fwrapv -stack-protector 2 -fgnuc-version=4.2.1 -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/test-1efcc1.o -x c test.c clang -cc1 version 13.0.0 based upon LLVM 13.0.0 default target amd64-unknown-openbsd7.3 #include "..." search starts here: #include <...> search starts here: /usr/lib/clang/13.0.0/include /usr/include End of search list. "/usr/bin/ld" -e __start --eh-frame-hdr -Bdynamic -dynamic-linker /usr/libexec/ld.so -nopie -o a.out /usr/lib/gcrt0.o /usr/lib/crtbegin.o -L/usr/lib /tmp/test-1efcc1.o -lcompiler_rt -lc_p -lcompiler_rt /usr/lib/crtend.o When using -pg, instead of linking to -lc, it is using -lc_p which only exists as libc_p.a. The linker has no dynamic library to register and seems to no include any .dynamic section. $ readelf -d a.out There is no dynamic section in this file. But ld.so seems to assumes that .dynamic will exists. exe_obj is initialized when .dynamic is found (PT_DYNAMIC), and used unconditionnally later. src/libexec/ld.so/loader.c 542 case PT_DYNAMIC: 543 minva = TRUNC_PG(minva); 544 maxva = ROUND_PG(maxva); 545 exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "", 546 (Elf_Dyn *)(phdp->p_vaddr + exe_loff), 547 (Elf_Phdr *)dl_data[AUX_phdr], 548 dl_data[AUX_phnum], OBJTYPE_EXE, minva + exe_loff, 549 exe_loff); 550 _dl_add_object(exe_obj); 551 break; ... 586 exe_obj->load_list = load_list; 587 exe_obj->obj_flags |= DF_1_GLOBAL; 588 exe_obj->nodelete = 1; 589 exe_obj->load_size = maxva - minva; 590 exe_obj->relro_addr = relro_addr; 591 exe_obj->relro_size = relro_size; The segfault is at line 586 (at first exe_obj deferences). If the program is built with a (unused) dynamic library, it is (somehow) fine: exe_obj is properly initialized and _dl_boot is fine. $ cc -pg -lm test.c $ readelf -d a.out Dynamic section at offset 0x1acb8 contains 18 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libm.so.10.1] 0x0000000000000015 (DEBUG) 0x0 0x0000000000000007 (RELA) 0x2007b8 0x0000000000000008 (RELASZ) 48 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x0000000000000017 (JMPREL) 0x2007e8 0x0000000000000002 (PLTRELSZ) 24 (bytes) 0x0000000000000003 (PLTGOT) 0x21ce50 0x0000000000000014 (PLTREL) RELA 0x0000000000000006 (SYMTAB) 0x200348 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000005 (STRTAB) 0x2006c4 0x000000000000000a (STRSZ) 244 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x200570 0x0000000000000004 (HASH) 0x200604 0x0000000000000020 (PREINIT_ARRAY) 0x21c6b8 0x0000000000000021 (PREINIT_ARRAYSZ) 0x8 0x0000000000000000 (NULL) 0x0 Now, at runtime, it segfaults later but for another reason. $ a.out Segmentation fault (core dumped) $ dmesg | tail -1 [a.out]34943/523783 pc=218a32 inside 2c72e0000-2c72ebfff: bogus syscall $ egdb ./a.out Program received signal SIGSEGV, Segmentation fault. issetugid () at /tmp/-:3 3 /tmp/-: No such file or directory. (gdb) bt #0 issetugid () at /tmp/-:3 #1 0x00000000002056ac in _libc_preinit (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>, cb=<error reading variable: Cannot access memory at address 0x87c52af645eebfa7>) at /usr/src/lib/libc/dlfcn/init.c:128 Backtrace stopped: Cannot access memory at address 0x87c52af645eebfdf (gdb) disassemble Dump of assembler code for function issetugid: 0x0000000000218a10 <+0>: push rbp 0x0000000000218a11 <+1>: lea rbp,[rsp] 0x0000000000218a15 <+5>: call 0x205eb0 <__mcount> 0x0000000000218a1a <+10>: pop rbp 0x0000000000218a1b <+11>: mov r11,QWORD PTR [rip+0x3c06] # 0x21c628 <__retguard__thread_sys_issetugid> 0x0000000000218a22 <+18>: xor r11,QWORD PTR [rsp] 0x0000000000218a26 <+22>: push r11 0x0000000000218a28 <+24>: mov eax,0xfd 0x0000000000218a2d <+29>: mov r10,rcx 0x0000000000218a30 <+32>: syscall => 0x0000000000218a32 <+34>: pop r11 0x0000000000218a34 <+36>: xor r11,QWORD PTR [rsp] 0x0000000000218a38 <+40>: cmp r11,QWORD PTR [rip+0x3be9] # 0x21c628 <__retguard__thread_sys_issetugid> 0x0000000000218a3f <+47>: je 0x218a4c <issetugid+60> 0x0000000000218a41 <+49>: int3 0x0000000000218a42 <+50>: int3 0x0000000000218a43 <+51>: int3 0x0000000000218a44 <+52>: int3 0x0000000000218a45 <+53>: int3 0x0000000000218a46 <+54>: int3 0x0000000000218a47 <+55>: int3 0x0000000000218a48 <+56>: int3 0x0000000000218a49 <+57>: int3 0x0000000000218a4a <+58>: int3 0x0000000000218a4b <+59>: int3 0x0000000000218a4c <+60>: ret End of assembler dump. >From my understanding, the `syscall` isn't permitted because it comes from the static library libc_p.a inside the dynamic program a.out. Thanks. -- Sebastien Marie