Search code examples
clinkerelfsymbol-table

What is the use of local symbols in the symbol table of an object file?


From the question (Hiding symbol names in library), I thought static functions are removed from an object file's symbol table when compiled with optimization (maybe because compilers assume it is a release build). The below is a slighltly modified source code from (Hiding symbol names in library) and the symbol table of the compiled object file.

// compile with gcc -c -O2 -o file.o file.c

extern int a();
extern int b();

static int f_b1(){
return a();
}

static int f_b3(){
return b();
}
test.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .comment       0000000000000000 .comment

However, it seems such disappearance was caused just because both f_b1 and f_b3 are not used. Evidently, if they are called by a non-static function as below, their symbols re-appear in the symbol table (i.e. objdump -t file.o).

extern int a();
extern int b();

static int __attribute__ ((noinline)) f_b1(){
return a();
}

static int __attribute__ ((noinline)) f_b2(){
return b();
}

void f_b3(){
    f_b1();
    f_b2();
}
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l     F .text  0000000000000007 f_b1
0000000000000010 l     F .text  0000000000000007 f_b2
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000         *UND*  0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000         *UND*  0000000000000000 a
0000000000000000         *UND*  0000000000000000 b
0000000000000020 g     F .text  0000000000000013 f_b3

So, by default, it seems a compiler emits the symbols of static functions into the symbol table even with optimization. Then, what is the use of such local symbols? Are they really required during linking stage (I don't see why they are required since call and jump are performed in an eip-relative way, isn't it?)?


Solution

  • Are they really required during linking stage

    No. They are only there to help debugging.

    You can confirm this by using objcopy --strip-unneeded test.o test1.o -- the symbols will be removed, but you can still link test1.o into the final binary just as you could with test.o.