Lab2 bomb
GDB手册
1.单步执行和跟踪函数调用
#include <stdio.h>
int add_range(int low, int high)
{
int i, sum;
for (i = low; i <= high; i++)
sum = sum + i;
return sum;
}
int main(void)
{
int result[100];
result[0] = add_range(1, 10);
result[1] = add_range(1, 100);
printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);
return 0;
}
result[0]=55
result[1]=5105
第二个有问题,因为sum未初始化,用的是第一次调用的寄存器
gcc -g main.c -o main
gdb main
-g
选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb
能找到源文件。gdb
提供一个类似Shell的命令行环境,上面的(gdb)
就是提示符,在这个提示符下输入help
可以查看命令的类别
看bomb.pdf
chapter Ⅲ
3.2 程序编码
gcc -Og -o p p1.c p2.c
-Og,告诉编译器产生符合原始C代码整体结构的机器代码的优化等级。使用较高级别优化产生的代码会严重变形,以至于产生的机器代码和初始源代码之间的关系非常难以理解。因此我们会使用-Og优化作为学习工具。
首先C预处理器扩展源代码,插入所以用#include 命令指定的文件,并扩展所有用#define声明指定的宏。
其次,编译器 ()产生两个源代码的汇编文件,p1.s,p2.s.
接下来,汇编器()产生两个汇编代码转化成二进制目标代码文件p1.o,p2.o.
目标代码是机器代码的一种,它包含机器指令的所有形式,但是还没有填入全局值的地址。
最后,链接器将两个目标代码文件与实现库函数的代码合并,并产生最终的可执行代码文件 p,(由命令行指示符-o p指定的)
3.2.1 机器代码
- 程序计数器(PC),%rip
- 整数寄存器
- 条件码寄存器
3.2.2 代码示例
gcc -Og -S mstore.c
gcc -Og -c mstore.c
3.7 过程
//前面的控制看看就行,记不下来,得查表
3.7.1 运行时栈
当函数过程需要的存储空间超过了寄存器能够存放的大小,就会在栈上分配空间,这个部分被称为frame(栈帧)
bomb lab
some tips
gdb bomb
在gdb中运行bomb程序
gdb bomb -tui
可以一遍看汇编代码一遍运行bomb程序
objdump -d bomb > bomb.txt
在shell中可以先反汇编bomb程序,并且重定向到bomb.txt中,便于查看结果。
利用
Ctrl+F
,搜索bomb相关字眼,可以看到explode_bomb
,约莫是会导致炸弹的函数,你再通过gdb bomb -tui
,运行程序时候,看着汇编一行行变换,发现还真是。gdb : disas
在gdb状态下如果你想要看一下当前的运行的汇编语句,如上。
break explode_bomb
break phase_1 break phase_2 ...
嗯,看看代码文件,这些是我们需要打的断点。
run ./sol.txt ## 就是拿txt里的东西来作为程序参数
phase_4
phase3 phase4
,都是把要输入的值放在了栈上面
对于phase4
扫一眼,
000000000040100c <phase_4>:
40100c: 48 83 ec 18 sub $0x18,%rsp
401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
40101a: be cf 25 40 00 mov $0x4025cf,%esi
40101f: b8 00 00 00 00 mov $0x0,%eax
401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@plt>
401029: 83 f8 02 cmp $0x2,%eax
40102c: 75 07 jne 401035 <phase_4+0x29>
40102e: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)
401033: 76 05 jbe 40103a <phase_4+0x2e>
401035: e8 00 04 00 00 callq 40143a <explode_bomb>
40103a: ba 0e 00 00 00 mov $0xe,%edx
40103f: be 00 00 00 00 mov $0x0,%esi
401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
401048: e8 81 ff ff ff callq 400fce <func4>
40104d: 85 c0 test %eax,%eax
40104f: 75 07 jne 401058 <phase_4+0x4c>
401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)
401056: 74 05 je 40105d <phase_4+0x51>
401058: e8 dd 03 00 00 callq 40143a <explode_bomb>
40105d: 48 83 c4 18 add $0x18,%rsp
401061: c3 retq
scanf输入函数需要字符类型作为参数,注意到 mov $0x4025cf, %esi
非常奇怪,因此
该操作可以从CMU的gdb手册中看到.
可以发现输入函数接受了两个整数
.
401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@plt>
401029: 83 f8 02 cmp $0x2,%eax
同时这两行可以佐证该观点.
另外还得搞清楚
0000000000400fce <func4>:
400fce: 48 83 ec 08 sub $0x8,%rsp
400fd2: 89 d0 mov %edx,%eax
400fd4: 29 f0 sub %esi,%eax
400fd6: 89 c1 mov %eax,%ecx
400fd8: c1 e9 1f shr $0x1f,%ecx
400fdb: 01 c8 add %ecx,%eax
400fdd: d1 f8 sar %eax
400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx
400fe2: 39 f9 cmp %edi,%ecx
400fe4: 7e 0c jle 400ff2 <func4+0x24>
400fe6: 8d 51 ff lea -0x1(%rcx),%edx
400fe9: e8 e0 ff ff ff callq 400fce <func4>
400fee: 01 c0 add %eax,%eax
400ff0: eb 15 jmp 401007 <func4+0x39>
400ff2: b8 00 00 00 00 mov $0x0,%eax
400ff7: 39 f9 cmp %edi,%ecx
400ff9: 7d 0c jge 401007 <func4+0x39>
400ffb: 8d 71 01 lea 0x1(%rcx),%esi
400ffe: e8 cb ff ff ff callq 400fce <func4>
401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
401007: 48 83 c4 08 add $0x8,%rsp
40100b: c3 retq
说实话,在gdb-tui里看的更清楚,那个是十进制的编号。
/*复制的吴迪学长的代码,是将fun4人脑翻译成c,从前面可知x<=0xe,所以穷举一下就可以了*/
#include<stdio.h>
int fun(int a1, int a2, int x);
int fun(int a1, int a2, int x){
int b = (a1 - a2) >> 31;
int result = ((a1-a2) + b) >> 1;
b = result + a2;
if(b == x) return 0;
if(b < x) {
result = fun(a1, b + 1, x);
return result * 2 + 1;
}else{
result = fun(b - 1, a2, x);
return result * 2;
}
}
int main(void){
for(int i = 0; i <= 0xe; i++){
if(fun(0xe,0,i) == 0){
printf("%d\n",i) ;
}
}
return 0;
}
得出前一个值是0 1 3 7;从401051可以看出后一个值应该是0.
phase_5
lab4 Cache Lab
实现一个缓存系统
This lab will help you understand the impact that cache memories can have on the performance of your Cprograms
The lab consists of two parts. In the first part you will write asmall C program (about 200-300 lines) thatsimulates the behavior of a cache memory. In the second part,you will optimize a small matrix transposefunction, with the goal of minimizing the number of cache misses.
Part A: Writing a Cache Simulator
做bomb lab的时候可以看这个PDF来用gdb ↩︎