"."在.symtab部分的Ndx列中的含义是什么?

use*_*507 6 c gcc elf

add2.c:

int counter=0;
int a=0;
int b;
int c;
int add(int a, int b) {
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

编译:gcc -c add2.c -o add2.o

阅读符号表:readelf --symbols add2.o

Symbol table '.symtab' contains 12 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS add2.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1 
     3: 00000000     0 SECTION LOCAL  DEFAULT    2 
     4: 00000000     0 SECTION LOCAL  DEFAULT    3 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 SECTION LOCAL  DEFAULT    4 
     7: 00000000     4 OBJECT  GLOBAL DEFAULT    3 counter
     8: 00000004     4 OBJECT  GLOBAL DEFAULT    3 a
     9: 00000004     4 OBJECT  GLOBAL DEFAULT  COM b
    10: 00000004     4 OBJECT  GLOBAL DEFAULT  COM c
    11: 00000000    14 FUNC    GLOBAL DEFAULT    1 add
Run Code Online (Sandbox Code Playgroud)

"COM"在Ndx列中的含义是什么?我理解"#"和"a"在#3部分(即.bss)中定义,"add"在#1部分(即.text)中定义,但我期待"b"和"c"也在.bss部分中定义,因此在Ndx列中得到"3".

谢谢

Mat*_*ery 5

gcc处理未初始化的全局变量,这些全局变量未明确声明extern为"常用"符号(因此为"COM").

在创建最终可执行文件时,链接器将相同公共符号的多个定义(跨多个目标文件)合并在一起,以便它们都引用相同的存储.其中一个目标文件可以将其初始化为特定值(在这种情况下,它将最终出现在数据部分中); 如果没有对象文件初始化它,将最终在BSS中; 如果多个对象初始化它,您将收到链接器错误.

总之,如果你有两个定义int a:

  • int a;在一个对象和int a;另一个对象中是OK:两者都引用相同a,初始化为0
  • int a;在一个对象和int a = 42;另一个对象中是OK:两者都指向相同的a,初始化为42
  • int a = 23;在一个对象和int a= 42;另一个对象中将给出链接错误.

请注意,标准C在技术上不允许在两个对象上使用相同符号的多个定义; 但许多编译器都支持它,包括gcc,作为扩展.(它被列在"共同扩展"下 - 在C99规范中没有双关语.)