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

Reply via email to