Of course, all programs compiled without '-pg' work fine for me.
I found this issue when I profile my application with gprof(1).
For example, following example C source code fails to execute on OpenBSD 7.0.
```
$ cat helloworld.c
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello World!\n");
return 0;
}
$ cc helloworld.c
$ ./a.out
Hello World!
$ cc -pg helloworld.c
$ ./a.out
Segmentation fault (core dumped)
$ readelf -h -l -d -u ./a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x2045f0
Start of program headers: 64 (bytes into file)
Start of section headers: 419600 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 11
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 27
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000200040 0x0000000000200040
0x0000000000000268 0x0000000000000268 R 8
INTERP 0x00000000000002a8 0x00000000002002a8 0x00000000002002a8
0x0000000000000013 0x0000000000000013 R 1
[Requesting program interpreter: /usr/libexec/ld.so]
LOAD 0x0000000000000000 0x0000000000200000 0x0000000000200000
0x00000000000035ec 0x00000000000035ec R 1000
LOAD 0x00000000000035f0 0x00000000002045f0 0x00000000002045f0
0x000000000001563e 0x000000000001563e R E 1000
LOAD 0x0000000000018c30 0x000000000021ac30 0x000000000021ac30
0x0000000000000700 0x0000000000000700 RW 1000
LOAD 0x0000000000019330 0x000000000021c330 0x000000000021c330
0x0000000000001028 0x0000000000006a38 RW 1000
GNU_RELRO 0x0000000000018c30 0x000000000021ac30 0x000000000021ac30
0x0000000000000700 0x00000000000013d0 R 1
GNU_EH_FRAME 0x00000000000017a8 0x00000000002017a8 0x00000000002017a8
0x00000000000004bc 0x00000000000004bc R 4
OPENBSD_RANDOM 0x0000000000018c30 0x000000000021ac30 0x000000000021ac30
0x0000000000000068 0x0000000000000068 RW 8
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0
NOTE 0x00000000000002bc 0x00000000002002bc 0x00000000002002bc
0x0000000000000018 0x0000000000000018 R 4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.openbsd.ident .rodata .eh_frame_hdr .eh_frame
03 .text .init .fini
04 .openbsd.randomdata .jcr .ctors .dtors .preinit_array .data.rel.ro
.got
05 .data .bss
06 .openbsd.randomdata .jcr .ctors .dtors .preinit_array .data.rel.ro
.got
07 .eh_frame_hdr
08 .openbsd.randomdata
09
10 .note.openbsd.ident
There is no dynamic section in this file.
There are no unwind sections in this file.
```
I can see the compiled program is statically linked (Type: EXEC),
and has an INTERP section (/usr/libexec/ld.so), and no dynamic sections.
If a elf binary has an INTERP section, the kernel invokes dynamic linker
(ld.so).
Ld.so tries to link dynamic link libraries, but it fails because no dynamic
sections in the elf binary.
In 'src/libexec/ld.so/loader.c', `_dl_boot` function reads a dynamic section and
initialize `exe_obj` pointer. If there is no dynamic sections, `exe_obj` is
still `NULL`.
After reading header sections, `exe_obj` is referred to store parsed values,
and it fails by NULL pointer access.
```
501 exe_obj = NULL;
(snip)
511 for (loop = 0; loop < dl_data[AUX_phnum]; loop++) {
512 switch (phdp->p_type) {
513 case PT_PHDR:
514 exe_loff = (Elf_Addr)dl_data[AUX_phdr] -
phdp->p_vaddr;
515 us += exe_loff;
516 DL_DEB(("exe load offset: 0x%lx\n", exe_loff));
517 break;
518 case PT_DYNAMIC:
519 minva = TRUNC_PG(minva);
520 maxva = ROUND_PG(maxva);
521 exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "",
522 (Elf_Dyn *)(phdp->p_vaddr + exe_loff),
523 (Elf_Phdr *)dl_data[AUX_phdr],
524 dl_data[AUX_phnum], OBJTYPE_EXE, minva +
exe_loff,
525 exe_loff);
526 _dl_add_object(exe_obj);
527 break;
(snip)
562 exe_obj->load_list = load_list;
563 exe_obj->obj_flags |= DF_1_GLOBAL;
564 exe_obj->load_size = maxva - minva;
565 exe_obj->relro_addr = relro_addr;
566 exe_obj->relro_size = relro_size;
```
I wonder why statically linked binary has an INTERP section?
I tried checking which options are passed to 'ld'.
I replaced my '/usr/bin/ld' as following script.
```
#!/bin/sh
echo $*
exec /usr/bin/ld.lld $*
```
I ran `cc -pg` again.
```
$ cc -pg helloworld.c
__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/helloworld-59ced4.o
-lcompiler_rt -lc_p -lcompiler_rt /usr/lib/crtend.o
```
`-Bdynamic -dynamic-linker /usr/libexec/ld.so` is passed to the 'ld'.
I think 'ld' is not wrong, passing the dynamic linker option seems to be a bug.
I patched clang source code to pass `-Bstatic` option as follows.
I can confirm my programs compiled with -pg option run successfully.
```
diff --git a/gnu/llvm/clang/lib/Driver/ToolChains/OpenBSD.cpp
b/gnu/llvm/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 1577f70aad6..c3a2f9e005e 100644
--- a/gnu/llvm/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/gnu/llvm/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -108,25 +108,25 @@ void openbsd::Linker::ConstructJob(Compilation &C, const
JobAction &JA,
if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
else if (ToolChain.getArch() == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
CmdArgs.push_back("--eh-frame-hdr");
- if (Args.hasArg(options::OPT_static)) {
+ if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_pg)) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
CmdArgs.push_back("-Bdynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
} else {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld.so");
}
}
```
Is it OK?
--
Yuichiro NAITO ([email protected])