Closed xxyy-0204 closed 2 years ago
The hints in MapLibrary.c
just mean to tell you how to use these helper functions. Providing wrong arguments can lead to failure of helper functions.
I would give the following hints:
lib->dyn
is set to an absolute address(i.e. a long one like 0x7fff...
(value is not exact) instead of a short one like 0x200000
).dyn
. There is a segment whose name is PT_DYNAMIC
, which tells you infomation about .dynamic
section.You could provide a more detailed context(e.g. value of critical variables) if the problem persists.
Sorry to bother you. But there is still something wrong.
while the "start_address" means the base address as instruction mentions, and the "dyn_addr" means the real address of dyn. So, that's the nearly whole thing of my problem.
which is nearly an unrolling of the place where it stuck.(rebase symtab) And I also added outputs for analysis.
with the ptr means the offset of symtab and the addr means the base address.
So here is my question why the program stuck at this sentences as picture shows? Is there anything wrong with the base address or dyn address?
Thank you for reading the problem I met.
Though your problem is a bit long, but I appreciate how detailedly you provide information. Keep it up! :)
Plus, you absolutely can ask question or provide infomation in Chinese, if you feel more comfortable.
Let's get to your question. Your direct problem comes from here:
Although I really think that the dyn address should be caculated by add the base address and the offset
It's wrong.
Offset
means that if you want to read something from a file, the number of bytes you need to jump over till you can see that.
While VirtAddr
means the address of this thing in virtual memory. You can see more about these two in #7 .
dyn_addr
in your program is wrong. It should be 0x7ffff7fff5000 + 0x200e90
, not 0xe90
. I hope you can understand why we use VirtAddr
, and its relationship with alignment
and offset
in the issue above.
Let me know if the problem persists after you correctly get the address of dynamic segment.
很抱歉再次打扰您,但我想我可能又遇到了一些问题。
以下是更改后的基地址和动态元素地址 我想他是正确的,考虑了虚拟内存映射和页对齐后。
通过以上地址映射逻辑,得到了以下的错误
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bcfd3f in setup_hash (l=0x555555756260) at src/MapLibrary.c:30
30 Elf32_Word *hash32 = (Elf32_Word *)l->dynInfo[DT_GNU_HASH_NEW]->d_un.d_ptr;
其中的setup_hash函数遇到了段错误问题。
显然我的问题就在这个错误的原因。
为了更深层分解这个问题,我修改了原fill_info的代码使其输出导入的dyn的d_tag值,但是他显示为0。(正如第一张图最后一行所示) 对于该显示,DT_NULL(即0)标记dynamic section的结尾,说明我的dyn找到dyn的末尾了。
基于以上分析,我将原计算的得到的dyn进行了简单粗暴的减法操作,
Elf64_Dyn *dyn = lib->dyn-0x100;
而为什么是减100,我想不明白。但是这样结果是0x7ffff7ff5e90
,而如果减去1000,则是0x7ffff7fe6e90
。
得到输出的d_tag为
12
c
d
19
1b
1a
1c
6ffffef5
5
6
a
b
3
7
8
9
6ffffff9
这与符号表中标记一致。 但是我不明白为什么原来的dyn会找到错误的位置导致无法运行 以及究竟应该如何更改dyn的address呢 dyn的address难道不是如您上篇所说加上内存对齐后的值吗。
Comment: The student has some problem accessing Github and sends me an email, so I update the question and post my reply here.
Original Answer:
而为什么是减100,我想不明白。但是这样结果是
0x7ffff7ff5e90
,而如果减去1000
,则是0x7ffff7fe6e90
。
说实话,你为什么要减100,我也不明白……我猜想,你可能在这里发现,0x7ffff7ff5e90
(而不是0x7ffff7fe6e90
)处,d_tag的值符合你从readelf中读出的tag顺序。
为什么能在0x7ffff7ff5e90
读出这些tag?很简单,因为dynamic section从文件中的0xe90
处开始。你从0x7ffff7ff5000
处建立了一个长度为0x1000
字节的映射,自然能从0x7ffff7ff5e90
处读出部分信息。
此外,我从你的截图里还发现一个严重的问题:第二个LOAD segment的开始地址是0x7ffff7ff6e80
既没有按照页大小对齐,也没有按照segment的offset对齐,这明显是不对的。
但是我不明白为什么原来的dyn会找到错误的位置导致无法运行
你两次找到的dyn的地址应该都不对。
以及究竟应该如何更改dyn的address呢
从你的截图中看,DYNAMIC segment的offset
是0xe90
,VirtAddr为0x200e90
. 如果你的基地址(第一个LOAD segment的开始地址)为0x7ffff7ff5000
,那么把lib->dyn指向0x7ffff7ff5000 + 0x200e90 = 0x7ffff81f5e90
就应当是正确的。
另在此处附上gdb调试时,你应当看到的各个segment的起止地址(注:各OS编译结果可能不同,此处只对截图中的文件适用):
第一个LOAD segment的起止:0x7ffff7ff5000
~ 0x7ffff7ff6000
第二个LOAD segment的起止:0x7ffff81f5000
~ 0x7ffff81f7000
请问此行报错的原因是什么,是map library写错了吗,问题出在哪里?