c - elf .rel.text 部分 R_386_32/R_386_PC32 的含义

标签 c linux assembly x86

为了理解重定位的概念,我编写了一个简单的 chk.c 程序如下:

  1 #include<stdio.h>
  2 main(){
  3         int x,y,sum;
  4         x = 3;
  5         y = 4;
  6         sum = x + y;
  7         printf("sum = %d\n",sum);
  8 }

它的等效汇编代码,使用“objdump -d chk.o”是:

00000000 <main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 20                sub    $0x20,%esp
   9:   c7 44 24 1c 03 00 00    movl   $0x3,0x1c(%esp)
  10:   00 
  11:   c7 44 24 18 04 00 00    movl   $0x4,0x18(%esp)
  18:   00 
  19:   8b 44 24 18             mov    0x18(%esp),%eax
  1d:   8b 54 24 1c             mov    0x1c(%esp),%edx
  21:   8d 04 02                lea    (%edx,%eax,1),%eax
  24:   89 44 24 14             mov    %eax,0x14(%esp)
  28:   b8 00 00 00 00          mov    $0x0,%eax
  2d:   8b 54 24 14             mov    0x14(%esp),%edx
  31:   89 54 24 04             mov    %edx,0x4(%esp)
  35:   89 04 24                mov    %eax,(%esp)
  38:   e8 fc ff ff ff          call   39 <main+0x39>
  3d:   c9                      leave  
  3e:   c3                      ret    

和使用readelf看到的.rel.text部分如下:

Relocation section '.rel.text' at offset 0x360 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000029  00000501 R_386_32          00000000   .rodata
00000039  00000902 R_386_PC32        00000000   printf

基于此我有以下问题:

1) 从 .rel.text 部分的第二个条目,我能够理解 .text 部分中偏移量 0x39 处的值(此处为 0xfcffffff)必须替换为与符号的索引 9 关联的符号的地址表(& 结果是 printf)。但是我在这里无法清楚地理解0x02(ELF32_R_TYPE)的含义。 R_386_PC32 在这里指定了什么?谁能解释清楚它的意思。

2) 我也无法理解第一个条目。在 .text 部分的 0x29 偏移处需要替换什么,为什么这里不清楚。我再次想知道 R_386_32 在这里的含义。我找到了一个 pdf elf_format.pdf,但我无法从中清楚地理解 .rel.text 部分中“类型”的含义。

3) 另外我想知道 assembly inst "lea (%edx,%eax,1),%eax"的含义。虽然我找到了一个很好的链接(What's the purpose of the LEA instruction?)来描述 lea 的含义,但是 lea 的格式(括号内的 3 个参数是什么)并不清楚。

如果有人能清楚地解释上述问题的答案,将不胜感激。尽管我已经用谷歌尝试了很多,但我仍在努力寻找这些问题的答案。

还有一个问题。我在下面显示了偏移量 5 和 9 的符号表条目。

 Num: Value Size Type Bind Vis Ndx Name 
 5: 00000000 0 SECTION LOCAL DEFAULT 5 
 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf' 

.rel.text 表中第一个条目的信息字段是0x05,表示符号表的索引。我已经在上面显示了索引 5 的符号表条目,但无法理解它如何告诉我们它是用于 .rodata 的。

最佳答案

1), 2): R_386_32 是将符号的绝对 32 位地址 放入指定内存位置的重定位。 R_386_PC32 是一个重定位,它将符号的PC 相对 32 位地址 放入指定的内存位置。 R_386_32 对于静态数据很有用,如此处所示,因为编译器只是将重定位的符号地址加载到某个寄存器中,然后将其视为指针。 R_386_PC32 对于函数引用很有用,因为它可以用作 call 的直接参数。参见 elf_machdep.c有关如何处理重定位的示例。

3) 如果用 C 语法表示,lea (%edx,%eax,1),%eax 表示简单的 %eax = %edx + 1*%eax。在这里,它基本上被用作 add 操作码的替代品。

编辑:这是一个例子。

假设您的代码从 0x401000 开始加载到内存中,字符串 "sum = %d\n" 结束于 0x401800(在 .rodata 的开头) > 部分),并且 printf 在 libc 中位于 0x1400ab80。

然后,位于 0x29 的 R_386_32 重定位会将字节 00 18 40 00 放置在 0x401029(简单地复制符号的绝对地址),使指令位于 0x401028

  401028:   b8 00 18 40 00          mov    $0x401800,%eax

在 0x39 处的 R_386_PC32 重定位将字节 43 9b c0 13 放在 0x401039 处(值 0x1400ab80 - 0x40103d = 0x13c09b43,十六进制),使该指令

  401038:   e8 43 9b c0 13          call   $0x1400ab80 <printf>

我们减去 0x40103d 以计算 %pc 的值(这是 call 之后指令的地址)。

关于c - elf .rel.text 部分 R_386_32/R_386_PC32 的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12412064/

相关文章:

c - 将 header 中的结构声明为 typedef

c++ - Shogun 无法编译。这些是幕府将军的 bug 吗?

c - 关于从 C 语言转换为汇编语言的字长按 4 缩放的问题

c - 如何在 gcc asm 中添加一个计数器?

c++ - IOServiceAddMatchingNotification 问题

在 C 中创建一个函数

c - 如何用 C 语言打印哈希表?

linux - 显示 tcp http 请求端口 80 Linux

c++ - Linux getrusage() maxrss 最大驻留集大小不随分配增加 (C++)

c++ - 为什么 g++ 将计算拉入热循环?