Hi, aja@ shows me some problems with x11/gnome/librsvg update (the port is Rust based), and I finally tracked the problem inside nm(1).
I will not speak of Rust anymore, and will use only C for the example. When an object is compiled using -ffunction-sections, the compiler/linker will use one section per function (if I correctly understood the usual purpose, it is to be able to easily discard unused sections/functions at linking time). $ cat test.c #include <stdio.h> void test_fn(void) { printf("test_fn()\n"); } $ cc -Wall -c test.c -ffunction-sections $ readelf --sections test.o | grep -A1 test_fn [ 3] .text.test_fn PROGBITS 0000000000000000 00000040 0000000000000040 0000000000000000 AX 0 0 16 $ readelf -s test.o Symbol table '.symtab' contains 8 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c 2: 0000000000000000 11 OBJECT LOCAL DEFAULT 7 .L.str 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 24 FUNC WEAK HIDDEN 6 __llvm_retpoline_r11 5: 0000000000000000 8 OBJECT WEAK HIDDEN 9 __retguard_759 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf 7: 0000000000000000 64 FUNC GLOBAL DEFAULT 3 test_fn The problem is nm(1) doesn't recognize the test_fn type as a TEXT function: $ nm test.o 00000000 d .L.str 00000000 W __llvm_retpoline_r11 00000000 W __retguard_759 U printf 00000000 F test.c 00000000 ? test_fn test_fn symbol should be 'T', but it is reported as '?'. llvm-nm(1) is working correctly (but we don't have it in base): $ llvm-nm test.o 0000000000000000 r .L.str 0000000000000000 W __llvm_retpoline_r11 0000000000000000 V __retguard_759 U printf 0000000000000000 T test_fn The following diff makes nm(1) to properly mark the function 'T', by recognize ".text.*" sections: diff cecccd4b3c548875286ca2b010c95cbce6c0e359 /home/semarie/repos/openbsd/src blob - 5aeef7a01a7cbff029299cfc5562cfcec085347f file + usr.bin/nm/elf.c --- usr.bin/nm/elf.c +++ usr.bin/nm/elf.c @@ -274,6 +274,8 @@ elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn) return (-1); else if (!strcmp(sn, ELF_TEXT)) return (N_TEXT); + else if (!strncmp(sn, ".text.", 6)) + return (N_TEXT); else if (!strcmp(sn, ELF_RODATA)) return (N_SIZE); else if (!strcmp(sn, ELF_OPENBSDRANDOMDATA)) @@ -355,6 +357,7 @@ elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, } else if (sn != NULL && *sn != 0 && strcmp(sn, ELF_INIT) && strcmp(sn, ELF_TEXT) && + strncmp(sn, ".text.", 6) && strcmp(sn, ELF_FINI)) /* XXX GNU compat */ np->nl.n_other = '?'; break; The change on elf_shn2type() isn't strictly necessary for my use-case, but it (should) makes .text.* support better (recognize N_TEXT for STT_NOTYPE, STT_OBJECT, STT_TLS). After, nm(1) properly recognize the symbol: $ /usr/obj/usr.bin/nm/nm test.o 00000000 d .L.str 00000000 W __llvm_retpoline_r11 00000000 W __retguard_759 U printf 00000000 F test.c 00000000 T test_fn and it makes libtool(1) happy (LT/Archive.pm: get_symbollist function), and it makes librsvg build happy (which is playing with symbols at build time), and it should makes aja@ happy too. Comments or OK ? -- Sebastien Marie