gpt4 book ai didi

c++ - 为什么动态链接器“减去”虚拟地址以找出已加载的共享库可执行文件在内存中的位置?

转载 作者:行者123 更新时间:2023-12-02 10:03:07 28 4
gpt4 key购买 nike

根据ldt_code中的ld源代码here。没有将dl_main传递给phdr的上下文,我对为什么通过减去虚拟地址来推断main_map的加载地址有些困惑。

我跟踪过的代码:

1124 static void
1125 dl_main (const ElfW(Phdr) *phdr,
1126 ElfW(Word) phnum,
1127 ElfW(Addr) *user_entry,
1128 ElfW(auxv_t) *auxv)
1129 {
1130 const ElfW(Phdr) *ph;
1131 enum mode mode;
1132 struct link_map *main_map;
1133 size_t file_size;
1134 char *file;
1135 bool has_interp = false;
1136 unsigned int i;
1137 bool prelinked = false;
1138 bool rtld_is_main = false;
1139 void *tcbp = NULL;
... // Before this else, it thinks you're calling `ld.so.<version>` directly. This is not usually the case.
1366 else
1367 {
1368 /* Create a link_map for the executable itself.
1369 This will be what dlopen on "" returns. */
1370 main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
1371 __RTLD_OPENEXEC, LM_ID_BASE);
1372 assert (main_map != NULL);
1373 main_map->l_phdr = phdr;
1374 main_map->l_phnum = phnum;
1375 main_map->l_entry = *user_entry;
1376
1377 /* Even though the link map is not yet fully initialized we can add
1378 it to the map list since there are no possible users running yet. */
1379 _dl_add_to_namespace_list (main_map, LM_ID_BASE);
1380 assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded);
1399 }
... // Loops through program headers loaded in sequence from the ELF header.
1409 for (ph = phdr; ph < &phdr[phnum]; ++ph)
1410 switch (ph->p_type)
1411 {
1412 case PT_PHDR:
1413 /* Find out the load address. */
1414 main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;
1415 break;

那么为什么在这里减去加载地址呢?

最佳答案

特别是在第1414行,我们看到了main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;。从文件link.h定义了link_map的类型main_map,我看到link_map是一个struct,它描述了一个已加载的共享库。 l_addr字段用于描述在运行VirtAddr时将.so加载到内存中的位置与将其表示在readelf字段中加载的位置之间的区别:

❯ readelf -l main

Elf file type is EXEC (Executable file)
Entry point 0x401020
There are 11 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x0000000000000268 0x0000000000000268 R 0x8
INTERP 0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000004c0 0x00000000000004c0 R 0x1000
...

这意味着 l_addr不是 加载地址。实际上,它是 偏移量,您需要从当前内存中为其添加该值以访问共享库的内容。

关于c++ - 为什么动态链接器“减去”虚拟地址以找出已加载的共享库可执行文件在内存中的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61569543/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com