On Sat, 6 Nov 2021 15:20:03 +0100 Sebastien Marie <sema...@online.fr> wrote:
> When an object is compiled using -ffunction-sections... > The following diff makes nm(1) to properly mark the function 'T', by > recognize ".text.*" sections: ok gkoehler@ nm(1) has more problems. If one compiles with -fdata-sections, then the mark on read-only symbols (like "const int var;") changes from 'R' to 'D', because nm knows ".rodata" but not ".rodata.*". If an object has >= 65280 sections, then nm fails. Example is from clang 11.1.0 on my macppc, $ perl -E 'say "void f$_(void) {}" for 1..30000'>exam.c $ time cc -O2 -ffunction-sections -c exam.c 7m40.20s real 7m33.96s user 0m03.29s system $ nm exam.o nm: exam.o: no section header table This is because nm(1) can't read a section count >= 65280. https://stackoverflow.com/a/30428833/3614563 quotes the ELF spec, | If the number of sections is greater than or equal to SHN_LORESERVE | (0xff00), e_shnum has the value SHN_UNDEF (0) and the actual number | of section header table entries is contained in the sh_size field of | the section header at index 0 ... I found a large count in real C++ code, when I built llvm-project from git on amd64. Then nm(1) failed on some *.o file (and ar(1) made a wrongly indexed *.a, so I used llvm-ar to unbreak my build). I tried to fix nm(1), but then I got '?' and not 'T' on my function symbols, because I didn't have your diff. My sections were named ".text.*" and not ".text". I switched to llvm-nm or another tool. I didn't know that libtool(1) runs nm. We might have a problem if something will use libtool with -ffunction-sections or -fdata-sections and have >= 65280 sections. I don't know whether nm should check section names like ".text*", or it should ignore section names and check bits like SHF_EXECINSTR. Because nm now checks section names, your diff improves nm. --George > 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 > -- George Koehler <kern...@gmail.com>