这是关于 Philip Kaludercic 的网站及他编写的一个用 C 语言编写的小程序“Trip”的介绍。
- 网站信息:网站链接包括Start、Index、About、⚛ Feed、Contact,他正将此站点迁移到https://sdf.org/~pkal/,此链接会过期。
Trip 程序:
- 目的是自动拦截特定的 Libc 函数并模拟其失败,背景是作者在大学的系统编程课程中担任助教,强调代码的健壮性和可移植性,此工具有助于引发特定错误。
- 例如,当
fork(2)
系统调用失败时,通常很难遇到,因为只有系统上的进程数过高时才会失败,而此程序可模拟fork
失败,如trip fork:0.5 bash
,bash
可能会立即放弃(设置errno
为ENOMEM
),也可能尝试几次(设置errno
为EAGAIN
),最后还可能等待一段时间再尝试。 - 核心机制是使用
LD_PRELOAD
黑客技术,通过设置环境变量,让动态链接器/加载器在检查通常位置之前先查找某些符号的定义,而 Trip 编译了一个常规的位置独立可执行文件,通过编辑 GCC 生成的 ELF 文件来绕过限制,使其可被ld.so
预加载。 - 预加载自身时,
LD_PRELOAD
需要共享对象文件的绝对路径,可通过/proc/self
目录获取当前执行程序的文件路径,用execvpe(2)
执行新程序时传递环境变量。 - 为了保存 Trip“可执行文件”和 Trip“库”之间的状态,使用了
conf
环境变量,通过宏定义GS
和RS
来编码函数、失败概率和errno
值等信息。 - 在
____trip_should_fail
函数中,通过检查配置和掷骰子来决定是否模拟函数失败,为避免并发初始化内部状态,使用atomic_flag
进行非阻塞同步。 - 解析
errno
时,不使用关联数组,而是通过popen(3)
和cpp
将errno
的符号表示转换为十六进制数字,避免使用sprintf
两次,通过$sprintf
宏来动态分配内存。 - 确定函数可能设置的
errno
值是瓶颈,手动将这些信息写在自定义文件格式中,用 AWK 转换为 C 文件,通过#include
将数据注入到数组中。
- 作者感受:作者认为“polishing”这个词很适合描述他对这个程序的修改,与其他编程任务相比,他可以专注于代码的一小部分进行无意义的重写,尝试一些想法,从手册和标准中获取灵感,虽然不是每个人都觉得这是有趣的周末活动,但对他来说有一定意义。
- 更新与备注:在 Hacker News 上有人指出可用
strace
复制其功能;不同操作系统对LD_PRELOAD
的文件格式要求不同;GCC 接受$
但 ISO C 不要求;大多数编译器的--version
标志更详细,可用于COMPILER
宏定义。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。