c - .symtab 部分的 Ndx 列中的 "COM"是什么意思?

标签 c gcc elf

add2.c:

int counter=0;
int a=0;
int b;
int c;
int add(int a, int b) {
    return a+b;
}

编译: 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

Ndx 列中的“COM”是什么意思?我知道“counter”和“a”在第 3 节(即 .bss)中定义,“add”在第 1 节(即 .text)中定义,但我期待“b”和“c”也将在 .bss 部分中定义,因此在 Ndx 列中获得“3”。

谢谢

最佳答案

gcc 将未明确声明 extern 的未初始化全局变量视为“通用”符号(因此称为“COM”)。

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

总而言之,如果您有两个 int a 的定义:

    一个对象中的
  • int a; 和另一个对象中的 int a; 是可以的:两者都引用相同的 a,初始化为 0
  • 一个对象中的
  • int a; 和另一个对象中的 int a = 42; 是可以的:两者都引用相同的 a,已初始化到 42
  • 一个对象中的
  • int a = 23; 和另一个对象中的 int a= 42; 将给出链接错误。

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

关于c - .symtab 部分的 Ndx 列中的 "COM"是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4137522/

相关文章:

c - 使用 ELF 文件

c++ - 宏字符串 : what does #define __T(x) x mean? 和 __T(#x)?

c++ - 打开 netlink 套接字将使用相同的 pid,然后绑定(bind)和创建失败

c++ - 在我的函数中使用简单类时出现 undefined reference 错误

linux - x86_32 Linux 上 ELF 的初始堆栈布局是什么?

linker - 预定义的 ELF 代码部分

c - 将矩阵作为参数传递给函数

c - 如何从头文件中获取未使用的变量警告?

gcc - 为什么默认定义 _GNU_SOURCE 以及如何关闭它?

c - 编译器决定放入寄存器的变量的运算符地址会发生什么?