0324ICSHW答案
ICS作业-链接2参考
7.10
A.
1 |
|
B.
1 |
|
C.
1 |
|
7.11
因为有.BSS区域,该区域在可执行文件中并不分配空间;而在加载入内存时进行分配,因此要预留出0x230字节。
7.12
A.
$*refptr = ADDR(r.symbol)+r.addend-refaddr$
$=0x4004f8-4-(0x4004e0+0xa)=0xa$
B.
$*refptr = ADDR(r.symbol)+r.addend-refaddr$
$=0x400500-4-(0x4004d0+0xa)=0x22$
7.13
A.
寻找libc.a和libm.a
使用如下的命令,找到库的位置
1 |
|
得出这两个文件均在/usr/lib/aarch64-linux-gnu
目录下
查找有多少个Object Files
1 |
|
得出结论,在libc.a下有1616个Object file,在libm.a下有576个Object file
B.
他们产生的二进制文件是不同的,-g会携带更多的debug和符号信息。
使用如下命令即可看出他们之间的差别
1 |
|
事实上,添加的部分为debug section,可以用readelf读出来
1 |
|
1
2
i
=infoDisplays the contents of the ‘.debug_info’ section. Note: the output from this option can also be restricted by the use of the –dwarf-depth and –dwarf-start options.
C.
使用ldd分析任意一个可执行文件,可看出在我的电脑上(Ubuntu20.04 aarch64),动态链接库如下
1 |
|
- linux-vdso.so.1
- libselinux.so.1 => /lib/aarch64-linux-gnu/libselinux.so.1
- libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6
- /lib/ld-linux-aarch64.so.1
- libpcre2-8.so.0 => /lib/aarch64-linux-gnu/libpcre2-8.so.0
- libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2
- libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0
补充习题
1.补充源码
源码和Makefile见附带的文件
编译成功后的截图如下
2. 手动编译
使用了两种方法,第一种直接使用gcc -v
的编译参数,第二种使用更简单的手动链接
gcc -v式的
能正常编译并运行
手动链接式的
在我们进行链接之前,需要先解释各个系统库有什么用,才能进行选择性的简化链接
- libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3496d10000) - C标准库动态共享对象
- /lib64/ld-linux-x86-64.so.2 (0x00007f3497303000) - 动态链接器/加载器
- crt1.o:包含入口函数_start(该函数执行了上一节所描述的整个程序执行过程),以及未定义的符号__libc_start_main、main
- crti.o: 提供.init节和.fini节的序言(function prologs)
- crtn.o: 提供.init节和.fini节的尾言(function epilogs)
- crtbegin.o: 提供构造函数的首地址(但在本题中,因为没有构造函数,因此不需要链接)
- crtend.o: 提供析构函数的首地址(同上)
具体到本题中,使用如下命令即可
1 |
|
3.OBJDUMP进行反汇编
使用objdump -S main.o > main.S
将反编译形成的汇编码写入main.S
文件中
4. 生成调试信息后,使用GDB进行调试
使用了list, break, start, run, continue, info等多种命令进行了调试,在此处限于截图篇幅,仅截取部分
5. 相关问题
分析同一个源程序在不同机器上生成的可执行目标代码是否相同
- ISA: 在arm处理器和x86处理器上,显然有不同的可执行目标文件代码
- OS:在windows和linux上有不同的寄存器分配规则,在windows64上的函数调用采用
RCX
,RDX
,R8
,R9
的寄存器调用顺序,在Linux64上采用的函数调用寄存器为RDI
,RSI
,RDX
,RCX
,R8
,R9
- 编译器:不同编译器会采用不同的优化策略,生成的可执行目标代码可能不同
你能在可执行目标文件中找出函数printf ()对应的机器代码段吗?能的话,请标示出来。
不能,printf函数所对应的机器代码段在libc.so中,是在运行时调用的,因此无法找到。
事实上,的确有printf@plt(Procedure linkage table)这一函数,但这仅仅是一个找到真实printf代码的stub
1
2
3
40000000000000710 <printf@plt>:
710: ff 25 9a 18 20 00 jmpq *0x20189a(%rip) # 201fb0 <printf@GLIBC_2.2.5>
716: 68 03 00 00 00 pushq $0x3
71b: e9 b0 ff ff ff jmpq 6d0 <.plt>为什么源程序文件的内容和可执行目标文件的内容完全不同?
源程序文件的内容为文本文件,是编程语言代码;可执行目标文件为CPU可以运行的二进制代码,自然不同。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!