yhdang
@yhdang
yhdang
@yhdang
-
今晚。
Post #3 -
插入任意长度的 nop 还能过就算正确
Post #2 ❤️ 1 like -
test 4 5 能正常过说明你的合并逻辑没问题,而是判断强弱符号的部分有问题。你可以结合具体源文件里的情况分析预期输出是什么:比如 test 4 是一个强符号和一个弱符号,这个时候只有一个强定义,所以是对的;test 5 有多个弱符号,也是符合定义的,所以也是对的。
但 test 2 中对
foo的没有任何一个强定义或弱定义,所以它应当报 undefined reference。你是否是对弱定义的判断有误?Post #2 ❤️ 2 likes -
这里是文档写得不清楚。
在多个 object file 被合成为一个
mergedObject之后,每个 object 的符号表中的符号被修改与mergedObject相同,详见util.cc: rebaseSymbols。不过在完成实验时无需考虑这个细节。要看到修改前的符号表,在这个函数被调用前打印即可。
Post #2 -
在返回这个错误时,同时要设置没得到定义的符号的名字,详见指导书。
Post #2 ❤️ 1 like -
感谢你的反馈!你的意见对这个新实验很宝贵。
对你提出的问题我稍微做一点澄清:
感觉这次实验难度某种意义上很简单,因为实验流程很简单,代码量也很小
它在设计上的本意如此。想象一下,如果把
util.cc去掉呢?如果在此过程中我们不调用ld,全部事情都自己做呢?具体实验中还有 bug,比如 test1 的重定位类型没有 R-X86-64-PC32,与文档描述不符
test1 似乎本就不该有
R_X86_64_PC32?之前的版本里确实会生成它,不过这个 bug 已经修复了。如果你在本地还能看到,请 pull 后重新编译。还有有关多个目标文件合并顺序的问题,文档里也没有细讲
你说得对,这里应该在文档里进行补充。
比如重定位类型,util.h 文件定义为 int 型,文档中虽然说了 relocation type 的类型,却并没有讲代码头文件中有相关定义
大家在代码里只需要做类似
re.type == R_X86_64_PC32的判断即可,似乎并没有必要知道R_X86_64_PC32是在哪里定义的。test0 中就说明了多个目标文件的合并问题
实际上,直到 test 4,大家才真的需要考虑将多个.o 合并在一起的情况。我们确实可以把“多个目标文件合并后需要调整 offset”放在这里再讲,但考虑到前边一直在讲知识,从连贯性的角度出发,最终还是决定放弃这种“娓娓道来”的讲法,在一开始就把所有需要完成的任务先讲出来,让大家有一个基础的认识。这样的坏处就如你所体验到的,在解题时没有环环相扣的感觉。
test4 和 test5 我实验要求都没看,系统就判定我过了
这个问题我在群里和论坛里也都说了,属于时间仓促下的一个 bug,今年就当是送给大家了。不过就算是这两个测试点有正确的实现,部分同学仍然会觉得简单,因为这个过程确实不太复杂。
最后重复一下我们的初心:纸上得来终觉浅,这个实验的出发点就是为了让大家获得一个上手实践静态链接的机会,从而加深理解。不是为了为难大家。
Post #2 ❤️ 1 like -
把所有的源文件都改成.c 就能正确链接了。
问题的根源是 C++ 编译器一般不会生成 common symbol(就算使用
-fcommon)。但是 C 会,因为它要支持从 Fortran port 来的程序,而 common symbol 是 Fortran 的首创。对这个问题可以详见:https://stackoverflow.com/q/10411052
你也可以使用
readelf -s观察符号的 index 是否为COM,从而确定编译器是否生成了一个 common symbol。Post #2 -
你说得对,只有 1 个弱定义时也是合法的。test 2 里这样写是因为在文件里没有弱定义,但显然不太严谨。
Post #2 -
请仔细阅读指导书。test 0 与 test 1 只需填写
relocation.cc,test 2 与 test 3 只涉及resolve.cc,但实现上的错误可能影响前两个 test 的结果。test 4 和 test 5 要求两个文件之间的协作。Post #2 -
可以使用
readelf -r检查两个目标文件的重定位条目:

发现在
weakdef里没有对foo的重定位,但strongdef里有。但二者的符号表里都有
foo,一个是有定义而另一个没有:

所以我猜你应该参考的是
relocTable而不是symbolTable?Post #2 -
你无需对 value 赋值,而是应当把
RelocEntry中的sym指向正确的Symbol。如果出现了预期输出中的错误输出,请检查是否正确地修改了 offset,建议将重定位时的输出打印出来。
Post #2 ❤️ 1 like -
off总是指当前这个对象在文件里的偏移量是多少。在你的例子中,符号
a的offset为 304,这代表的意思是这个符号所在符号表上中的表项在文件中的偏移量为 304。而序号为 3 的节(也就是.data)的off是 92,且a的 value 为 0,此时说明变量a的存储空间在这个文件内从 92+0 开始。因为符号a对应的 size 为 4,因此第 92~95 字节是用来存储 a 的初值也就是 1 的。因此可以这样总结:符号表中的表项(也就是大家看到的
Symbol)指示的是这个符号的具体信息,而这个符号的存储空间在它的index指示的节中。Post #3 -
从
114d处连续的 4 个字节都为 0 来看,foo中引用变量a没有在它应该在的地方被重定位。我的建议是在处理每一个RelocEntry时都将对应的地址打印出来,看看到底是往内存的哪个地方写了。Post #2 -
你说得对,这是一个 typo,这张图的上一个版本没有完全改过来。感谢反馈!
Post #2 -
test 4 和 test 5 准确来说没有 bug,只是在现有框架下大家没法绑定到错误的符号上,导致这两个点被削弱了。
鉴于解决这个问题需要对框架进行较大的修改,今年我们决定保持原状,大家能通过 autograder(以及加入
nop之后也能过)即可。Post #2 -
c3 之后这个函数就返回了,之后的 nop 可能是为了让下一个函数的代码对其。在这一点上不同版本的 gcc 可能有不同的行为(指导书里的输出使用 gcc 9 而大家的平台是 gcc 11)。虽然输出的二进制文件不一样,但只要把重定位做对了,最后的输出就是对的。
Post #2 -
这是先前框架里的一个 bug。pull 新的变化之后 make clean 再 make 即可。
Post #3 -
test1 中并不存在
R_X86_64_32这是实验框架的一个疏忽,感谢你的反馈。
请
make clean后git pull origin master,再make就可以了。语义不清
感谢反馈,应为“与
R_X86_64_PC32完全一样”,已修改。Post #2 -
zip 已安装,思源学习平台上的提交通道已开放
Post #4 -
igw 上安装了 cmake 而 ics-arm 上没有。这个实验我们在 igw 上进行,现在环境配置应该没有问题了。
Post #3 -
现在 g++ 已经安装了
Post #2