CSAPP - Chapter7 链接

7.2 静态链接 为了构造可执行文件,链接器必须完成两个主要任务: 符号解析。将每个符号引用和一个符号定义连接起来。 重定位。编译器和汇编器生成从 0 地址开始的代码和数据节。连接器通过把每个符号定义与一个内存位置关联起来,从而重定位这些节。然后修改所有对这些符号的引用,使得他们指向这个内存位置。 7.3 目标文件 可重定位目标文件 .o, .a(.a 就是一堆打包的.o) 可执行目标文件 elf 共享目标文件 .so 7.4 可重定位目标文件 .text 代码段 .rodata 只读数据段,保存字符串,const 数据等。 .data 数据段。全局和静态变量。 .bss 未初始化和初始化为 0 的全局和静态变量。不占空间。 .symtab 符号表,存放程序中定义和引用的函数和全局变量信息。 .rel.text .text 节中需要重定位的代码段。 .rel.data .data 节中需要重定位的数据段,被模块引用或定义的所有全局变量。 .debug 调试符号表。包含程序中定义的局部变量和类型定义,定义和引用的全局变量,原始的 C 源文件。 .line 原始 C 文件中的行号和.text 节中机器指令的映射。 .strtab 字符串表。 7.5 符号和符号表 由当前模块定义并能被其他模块引用的全局符号 其他模块定义并被当前模块引用的全局符号,称为外部符号 只被当前模块定义和引用的的局部符号 下面两个局部静态变量: int f() { static int x = 1; return x; } int g() { static int x = 2; return x; } 两个 x 分别在各自的函数中可见,这两个 x 都会保存到....

2024-08-07 · 5 min

CSAPP - Cache Lab

实验说明 在 cache lab 实验中,包含两个部分: 第一部分要求我们写一个 C program 来模拟 cache memory。 第二部分要求我们通过减少 cache miss 来优化一个矩阵转置函数。 对应的文件分别为csim.c, trans.c 可通过make和make clean来编译和删除编译文件。 PartA Writing a Cache Simulator 准备工作 我们利用valgrind生成的 trace files 作为我们 cache simulator 的 input。 格式为[space]operation address, size: I 0400d7d4,8 M 0421c7f0,4 L 04f6b868,8 S 7ff0005c8,8 I 加载指令 L 加载数据 S 存储数据 M 内存数据修改(先加载数据,再存储数据) I 前面不跟空格,L/S/M 前面需要加一个空格。 csim-ref是一个参考的 cache simulator 实现。使用LRU替换算法。 用法: Usage: ./csim-ref [-hv] -s <s> -E <E> -b <b> -t <tracefile>...

2024-08-05 · 3 min

CSAPP - Chapter6 存储器层次结构

6.1 存储技术 6.1.1 随机访问存储器 RAM SRAM DRAM ROM 6.1.2 磁盘存储 6.1.3 固态硬盘 大约十万次写会导致块损坏。 6.2 局部性 6.4 高速缓冲存储器 // todo: 添加截图 高速缓存确定一个请求是否命中,然后抽出被请求字的过程分为三步: 组选择 行匹配 字抽取 6.4.2 直接映射高速缓存 每组只有一行(E=1)。 // todo: 添加截图 6.4.3 组相连高速缓存 1<E<C/B 组选择 和直接映射高速缓存相同。 行匹配和字选择 每组的任何一行都可以包含任何映射到这个组的内存块。 所以高速缓存必须搜索组中的每一行,寻找一个有效行,其标记与地址中的标记相匹配。 行替换 行替换算法: LFU: Least frequently used. 替换过去某个时间窗口引用次数最少的一行。 LRU: Least recently used. 替换最后一次访问时间最久远的一行。 6.4.4 全相连高速缓存 //todo: 插图 E=CB,一个组包含所有行。 组选择 只有一个组,没有组索引。 行匹配和字选择 构建一个又大又快的相连高速缓存很困难,而且很昂贵。因此全相连高速缓存只适合做小的高速缓存,例如虚拟内存中的 TLB。 6.4.5 有关写的问题 写命中 假设我们要写一个已经缓存了的字 w(写命中)。 首先都会先更新高速缓存中的字 w,接着更新低一级的内存中的数据,有两种方式: write-through 直写。立即将 w 的高速缓存块写回到低一层中。 wirte-back 写回。尽可能地推迟更新,只有当替换算法要驱逐这个更新过的块时,才写到低一层去。 写回可以显著减少总线流量,但增加了复杂性,需要额外维护一个 dirty bit,表示这个高速缓存快块是否修改过。...

2024-07-28 · 1 min

CSAPP - Chapter5 优化程序性能

5.1 优化编译器的能力和局限性 gcc 优化等级: -O0:这是默认的优化等级,基本上不进行任何优化,以便于调试。源代码会被尽可能地转化为目标代码,而不会对程序的执行速度进行优化。 -O1:这是一个适度的优化等级,它会在编译时执行一些简单的优化,如常量折叠、死代码删除、循环展开等,但不会影响编译时间太多。这个等级的优化通常不会显著改变程序的行为。 -O2:这是最常见的优化等级,它会执行更多的优化,包括函数内联、循环优化、寄存器分配等,可能会稍微增加编译时间,但是通常可以产生更快的可执行文件。 -O3:这是最高级别的优化,它包含了-O2 中的所有优化,并且会执行更激进的优化策略,如更多的内联、循环展开等。这可能会显著增加编译时间,但同时也可能产生执行效率最高的代码。 -Os:这个优化等级专注于减少输出文件的大小,同时仍然保持一定的运行时性能。它会使用一些特定的技巧来减小代码和数据的大小,适合用于嵌入式系统或资源有限的环境。 -Og:这个优化等级主要用于调试,它会生成更多的调试信息,同时尽量保持源代码和目标代码的一致性,以便于调试。 -Ofast:这是为了追求极致性能的优化等级,它会启用所有可用的优化,并且可能会违反 C/C++语言标准的一些规则,比如浮点运算的精度可能会有所损失。 两种指针可能指向同一个内存位置的情况称为内存别名使用。 比如 void twiddle1(long *xp, long *yp) { *xp += *yp; *xp += *yp; } void twiddle2(long *xp, long *yp) { *xp = 2* *yp; } 在xp和yp指针不指向同一地址时,twiddle1可以被优化成twiddle2,但如果xp == yp,那结果就不一样了,twiddle1该地址的值会变成 4 倍,而twiddle2只是两倍。所以编译器对这种情况不能进行优化。 提供一个 combine1 函数,看看我们能如何来优化它。 // for add #define IDENT 0 #define OP + // for multiply #define INENT 1 #define OP * void combine1(vec_ptr v, data_t *dest) { long i; *dest = IDENT; for (i = 0; i < vec_length(v); i++) { data_t val; get_vec_element(v, i, &val); *dest = *dest OP val; } } int get_vec_element(vec_ptr v, long index, data_t *dest) { if (index < 0 || index >= v->Len) return 0; *dest = v->data[index]; return 1; } long vec_length(vec_ptr v) { return v->len; } 5....

2024-07-21 · 2 min

CSAPP - Attack Lab

文件说明 ctarget: An executable program vulnerable to code-injection(CI) attacks. rtarget: An executable program vulnerable to return-oriented-programming(ROP) attacks. cookie.txt: An 8-digit hex code that you will use as a unique identifier in your attack farm.c: 用来生成 ROP 攻击的代码。 hex2raw: 生成攻击字符串的工具。 输入ctarget -h查看帮助信息: Usage: [-hq] ./ctarget -i <infile> -h Print help information -q Don't submit result to server -i <infile> Input file 我们在本地跑的话必须加上-q选项,否则会提示Running on an illegal host错误。 工具使用 hex2raw hex2raw 可以将文本中保存的 ascii 码值转化成字符串。注意每个 ascii 需要以空格分开,可以加注释(注释/* */前后需要空格)。...

2024-07-05 · 10 min

CSAPP - Data Lab

Build ./dlc bits.c: 用来检查是否符合coding guidelines. ./dlc -e bits.c: 显示每个函数用了多少个操作符。 make btest: 编译btest。 make clean Rules Each "Expr" is an expression using ONLY the following: 1. Integer constants 0 through 255 (0xFF), inclusive. You are not allowed to use big constants such as 0xffffffff. 2. Function arguments and local variables (no global variables). 3. Unary integer operations ! ~ 4. Binary integer operations & ^ | + << >> You are expressly forbidden to: 1....

2024-06-25 · 1 min

CSAPP - Bomb Lab

Setup 新建solution.txt保存答案, 运行./bomb solution.txt进行测试。 gdb bomb (gdb) r solution.txt 注意如果solution.txt 每行的结尾需要是LF结尾,否则无法正确解析。 objdump -t bomb > bomb_symbol_table.txt: 生成符号表。 objdump -d bomb > bomb.txt: 生成反汇编文件。 Answer Bomb1 首先根据bomb.txt找到bomb的执行入口main函数。 400e32: e8 67 06 00 00 call 40149e <read_line> # 读取输入的一行 400e37: 48 89 c7 mov %rax,%rdi # 把读取的字符串地址传入%rdi 400e3a: e8 a1 00 00 00 call 400ee0 <phase_1> # 调用phase_1,传入的第一个参数为%rdi 400e3f: e8 80 07 00 00 call 4015c4 <phase_defused> 400e44: bf a8 23 40 00 mov $0x4023a8,%edi 400e49: e8 c2 fc ff ff call 400b10 <puts@plt> 400e4e: e8 4b 06 00 00 call 40149e <read_line> 400e53: 48 89 c7 mov %rax,%rdi 400e56: e8 a1 00 00 00 call 400efc <phase_2> 400e5b: e8 64 07 00 00 call 4015c4 <phase_defused> 400e60: bf ed 22 40 00 mov $0x4022ed,%edi 400e65: e8 a6 fc ff ff call 400b10 <puts@plt> //....

2024-06-13 · 11 min

CSAPP - Chapter3 程序的机器级表示

3.3 数据格式 Intel用术语字来表示16位数据类型。 32位:双字。 64位:四字。 3.4 访问信息 %rbp是帧指针。 生成1字节和2字节数字的指令会保持剩下的字节不变; 生成4字节数字的指令会把高位的4个字节置为0。 3.4.1 操作数指示符 3.4.2 数据传送指令 MOV S, D: S->D 传送指令和的两个操作数不能都指向内存地址。 movabsq: 常规的movq指令只能以表示为32位补码数字的立即数作为源操作数。然后把这个值符号扩展得到64位的值,放到目的位置。 movabsq指令能够以任意64位立即数作为源操作数,并且只能以寄存器作为目的。 MOVZ S, R: 零扩展(S)->R MOVS S, R: 符号扩展(S)->R 这两个指令目的只能是寄存器。 cltq: 符号扩展(%eax)->%rax, 把%eax符号扩展到%rax。 3.4.4 压入和弹出栈数据 练习题 3.2 内存引用总是以4字节寄存器给出,比如%rax。 练习题 3.3 movl %eax, %rdx: 目的寄存器%rdx长度不匹配,应该为%edx。 3.5算术和逻辑操作 图3-10: 3.5.1 加载有效地址 如果%rdx保存的值为x leaq 7(%rdx, %rdx, 4), %rax: 将%rax寄存器的值设为5x+7。 指令形式是从内存读数据到寄存器,但实际上根本没有引用内存。 3.5.3 移位操作 移位量可以是一个立即数,或者放在单字节寄存器%cl中。(只允许以这个特定的寄存器) 3.5.5 特殊的算术操作 //TODO: 3.6 控制 3.6.1 条件码 CF: 进位标志。 ZF: 零标志。...

2024-06-07 · 3 min

CSAPP - Chapter2 信息的表示和处理

2.1.1 十六进制表示法 2的整数幂转化为16进制: 多少次方就有多少个零。 \(2048 = 2^{11}\) \(n = 11 = 3 +4*2\) 因此十六进制表示为0x800。 2.1.2 字数据大小 计算机字长等于指针数据的长度,32/64。 2.1.3 寻址和字节顺序 typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (int i = 0; i < len; i++) printf("%.2x\n", start[i]); } int val = 0x87654321 byte_pointer valp = (byte_pointer)&val; show_bytes(valp, 1); // 结果是0x21, 小端法低地址保存的是数据低有效位 const char *s = "12345"; show_bytes((byte_pointer)s, strlen(s)); // 结果是31 32 33 34 35。没有字符串结尾的00,因为strlen不统计结束符。 // 注意字符串会以顺序排列,和字节序无关。 2....

2024-05-25 · 1 min