On Sat, Nov 06, 2021 at 03:20:03PM +0100, Sebastien Marie wrote:
> 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 ?
You made me happy :-)
--
Antoine