ELF文件中section header的Addr的解释着实让我知识盲区了

sh_addr如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应该在进程映像中的位置。否则,此字段为 0。

Linux下的内存映像布局一般有如下几个段(从低地址到高地址):

  1. 代码段: 即二进制机器代码,代码段是只读的,可以被多个进程共享;
  2. 数据段: 存储已初始化的变量,包括全局变量和初始化了的静态变量;
  3. 未初始化数据段: 存储未被初始化的静态变量,也就是BSS段;
  4. 堆: 用于存放动态分配的变量;
  5. 栈: 用于函数调用,保存函数返回值,参数等等;

注意这里的“从低地址到高地址”,这和nm命令不同

源代码

int c = 1;

void func(int a) {
int b = a;
c = b;
}

int main() {
int a = 1;
func(a);
return 0;
}
nm -C -a te.o

0000000000000000 b .bss
0000000000000000 D c
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 r .eh_frame
0000000000000000 T func
000000000000001d T main
0000000000000000 r .note.gnu.property
0000000000000000 n .note.GNU-stack
0000000000000000 a te.c
0000000000000000 t .text

看到,他这个是进行分区分配的,根据标识符的不同从0000000000000000进行分配,当标识符相同的时候,就进行叠加分配,依次按段递增。

因此,nm命令下的地址是一个相对地址!