Qcloud1223 / COMP461905

Course project for Operating Systems at XJTU: A basic x86-64 dynamic linker.
13 stars 4 forks source link

Segmentation fault in fill_info #10

Closed xxyy-0204 closed 2 years ago

xxyy-0204 commented 2 years ago

2021-12-17 15-32-21屏幕截图 请问此行报错的原因是什么,是map library写错了吗,问题出在哪里?

Qcloud1223 commented 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:

You could provide a more detailed context(e.g. value of critical variables) if the problem persists.

xxyy-0204 commented 2 years ago

Sorry to bother you. But there is still something wrong.

2021-12-18 14-19-24屏幕截图

2021-12-18 14-23-30屏幕截图 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.

2021-12-18 14-27-22屏幕截图 which is nearly an unrolling of the place where it stuck.(rebase symtab) And I also added outputs for analysis.

2021-12-18 14-29-59屏幕截图 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.

Qcloud1223 commented 2 years ago

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.

xxyy-0204 commented 2 years ago

很抱歉再次打扰您,但我想我可能又遇到了一些问题。

以下是更改后的基地址和动态元素地址 2021-12-20 13-47-03屏幕截图 我想他是正确的,考虑了虚拟内存映射和页对齐后。

通过以上地址映射逻辑,得到了以下的错误

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难道不是如您上篇所说加上内存对齐后的值吗。

Qcloud1223 commented 2 years ago

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的offset0xe90,VirtAddr为0x200e90. 如果你的基地址(第一个LOAD segment的开始地址)为0x7ffff7ff5000,那么把lib->dyn指向0x7ffff7ff5000 + 0x200e90 = 0x7ffff81f5e90就应当是正确的。


另在此处附上gdb调试时,你应当看到的各个segment的起止地址(注:各OS编译结果可能不同,此处只对截图中的文件适用):

第一个LOAD segment的起止:0x7ffff7ff5000 ~ 0x7ffff7ff6000

第二个LOAD segment的起止:0x7ffff81f5000 ~ 0x7ffff81f7000