基于ptrace获取子进程系统调用参数与返回值的问题排查
问题分析与解决
你看到的18446744073709551578是**-6的64位无符号整数表示**(对应十六进制0xfffffffffffffffa),这说明系统调用返回了错误码EBADF(无效文件描述符),但你的代码错误地把带符号的返回值当作无符号数打印了。
核心问题
Linux系统调用的返回规则是:
- 调用成功时,
rax寄存器存储正数或0; - 调用失败时,
rax存储负数形式的错误码(比如-EBADF即-6)。
你用%llu(无符号长整型格式符)打印regs.rax,会把负数强制转换为超大无符号数,就出现了看到的异常值。
代码修正
修改返回值的打印逻辑,先判断返回值是否为负,再做对应处理:
// 替换原有的printf行 long long ret = regs.rax; if (ret < 0) { // 错误情况:取反得到错误码,并用strerror输出对应描述 printf(" -> -%d (%s)\n", (int)-ret, strerror((int)-ret)); } else { // 成功情况:正常打印返回值 printf(" -> %lld\n", ret); }
额外排查方向
- 验证系统调用参数合法性:比如输出里多次出现
close(3),可能是子进程重复关闭已释放的文件描述符,导致EBADF错误,可在系统调用进入时打印参数确认。 - 确认寄存器结构正确性:确保你使用的
user_regs_struct是对应架构(比如x86_64)的正确定义,rax和orig_rax的偏移没有错误。 - 检查waitpid逻辑:当前两次
waitpid的循环没有处理子进程退出的边界情况,可能导致无限循环,建议在WIFEXITED(status)或WIFSIGNALED(status)时跳出循环。
内容的提问来源于stack exchange,提问作者user2374991
相关产品推荐
相关产品推荐

