首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >谁执行运行时重定位?

谁执行运行时重定位?
EN

Stack Overflow用户
提问于 2021-10-07 13:10:35
回答 1查看 170关注 0票数 5

我试图更好地理解Linux中的运行时重定位,特别是在不同的情况下由谁来执行它们。下面是我目前的理解,准确吗?

  • Position-dependent静态链接可执行程序没有运行时重定位needed
  • Dynamically-linked可执行文件动态链接器(ld.so)加载库,然后执行relocations
  • Statically链接饼libc启动代码执行relocations
  • The动态链接器本身- ld.so是一个自重新定位的二进制

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-08 04:19:22

你的答案(大部分)都是正确的。

您可以使用调试器观察重新定位的发生位置,并确认您的理解。

示例:

代码语言:javascript
运行
复制
#include <stdio.h>

int main()
{
  printf("%d\n", 123);
  return 0;
}

让我们从位置相关的动态链接二进制开始。

代码语言:javascript
运行
复制
gcc -g -fno-pie -no-pie t.c
gdb -q ./a.out
Reading symbols from ./a.out...
(gdb) starti
Starting program: /tmp/a.out

Program stopped.
0x00007ffff7fd2090 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) disas main
Dump of assembler code for function main:
   0x0000000000401126 <+0>:     push   %rbp
   0x0000000000401127 <+1>:     mov    %rsp,%rbp
   0x000000000040112a <+4>:     mov    $0x7b,%esi
   0x000000000040112f <+9>:     mov    $0x402010,%edi
   0x0000000000401134 <+14>:    mov    $0x0,%eax
   0x0000000000401139 <+19>:    call   0x401030 <printf@plt>
   0x000000000040113e <+24>:    mov    $0x0,%eax
   0x0000000000401143 <+29>:    pop    %rbp
   0x0000000000401144 <+30>:    ret
End of assembler dump.

(gdb) disas 0x401030
Dump of assembler code for function printf@plt:
   0x0000000000401030 <+0>:     jmp    *0x2fe2(%rip)        # 0x404018 <printf@got.plt>
   0x0000000000401036 <+6>:     push   $0x0
   0x000000000040103b <+11>:    jmp    0x401020
End of assembler dump.

在这里我们可以看到要重新定位的地址是0x404018。让我们看看地址是在哪里更新的:

代码语言:javascript
运行
复制
(gdb) watch *(void**)0x404018
Hardware watchpoint 1: *(void**)0x404018
(gdb) c
Continuing.

Hardware watchpoint 1: *(void**)0x404018

Old value = (void *) 0x401036 <printf@plt+6>
New value = (void *) 0x7ffff7e54270 <printf>
0x00007ffff7fe0f10 in _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at dl-runtime.c:146
146     dl-runtime.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7fe0f10 in _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at dl-runtime.c:146
#1  0x00007ffff7fe84fe in _dl_runtime_resolve_xsavec () at ../sysdeps/x86_64/dl-trampoline.h:126
#2  0x000000000040113e in main () at t.c:5

(gdb) info symbol $pc
_dl_fixup + 288 in section .text of /lib64/ld-linux-x86-64.so.2

因此,在动态链接的非饼的情况下,它确实是动态加载器执行重定位。

注意:这是一个懒惰的迁移,并且正在按需进行,在main已经运行之后。

如果我们使它不懒惰,那么它将在调用main之前由ld.so执行:

代码语言:javascript
运行
复制
gcc -g -fno-pie -no-pie t.c -Wl,-z,now

重复上面的步骤,并观察在main之前发生的重定位

代码语言:javascript
运行
复制
(gdb) run
Starting program: /tmp/a.out

Hardware watchpoint 1: *(void**)0x403fe8

Old value = (void *) 0x401036 <printf@plt+6>
New value = (void *) 0x7ffff7e54270
elf_machine_rela (skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>, version=<optimized out>, sym=<optimized out>, reloc=<optimized out>, map=<optimized out>)
    at ../sysdeps/x86_64/dl-machine.h:464
464     ../sysdeps/x86_64/dl-machine.h: No such file or directory.
(gdb) bt
#0  elf_machine_rela (skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>, version=<optimized out>, sym=<optimized out>, reloc=<optimized out>, map=<optimized out>)
    at ../sysdeps/x86_64/dl-machine.h:464
#1  elf_dynamic_do_Rela (skip_ifunc=<optimized out>, lazy=<optimized out>, nrelative=<optimized out>, relsize=<optimized out>, reladdr=<optimized out>, map=0x7ffff7ffe1a0)
    at do-rel.h:137
#2  _dl_relocate_object (l=l@entry=0x7ffff7ffe1a0, scope=<optimized out>, reloc_mode=<optimized out>, consider_profiling=<optimized out>, consider_profiling@entry=0)
    at dl-reloc.c:274
#3  0x00007ffff7fd555b in dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:2341
#4  0x00007ffff7fec1a2 in _dl_sysdep_start (start_argptr=start_argptr@entry=0x7fffffffe380, dl_main=dl_main@entry=0x7ffff7fd34c0 <dl_main>) at ../elf/dl-sysdep.c:252
#5  0x00007ffff7fd3021 in _dl_start_final (arg=0x7fffffffe380) at rtld.c:504
#6  _dl_start (arg=0x7fffffffe380) at rtld.c:597
#7  0x00007ffff7fd2098 in _start () from /lib64/ld-linux-x86-64.so.2

重复其他构建组合。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69481807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档