4个版本 (破坏性更新)
0.4.0 | 2024年1月17日 |
---|---|
0.3.0 | 2022年3月13日 |
0.2.0 | 2022年1月31日 |
0.1.0 | 2022年1月31日 |
在调试中排名84
每月下载2,301次
用于10个crate(直接使用3个)
65KB
1K SLoC
macho-unwind-info
一个用于mach-O二进制文件__unwind_info部分内容的零复制解析器。
快速查找地址的解包操作码。然后解析操作码以找出如何恢复返回地址和调用帧的寄存器值。
此crate的目的是足够快,可以在采样分析器中使用。从头开始重新解析成本低廉,并且可以在每个样本上执行。
为了获得完整的解包体验,可能需要参考__unwind_info和__eh_frame部分。这两个部分是互补的:__unwind_info处理简单情况,对于复杂情况,会引用__eh_frame FDE。相反,__eh_frame只包含无法在__unwind_info中表示的解包信息的函数的FDE。
在x86和x86_64上,__unwind_info可以表示大多数函数,无论它们是否与framepointers编译。
在arm64上,强烈建议不要使用framepointers进行编译,__unwind_info只能表示具有framepointers的函数或不需要恢复任何寄存器的函数。因此,如果您有一个没有framepointers的arm64二进制文件(很少见!),则__unwind_info基本上只充当__eh_frame的索引,类似于ELF中的__eh_frame_hdr。
在clang为arm64的默认配置中,非叶子函数具有framepointers,而叶子函数(没有在栈上存储寄存器)没有framepointers。对于叶子函数,返回地址在整个函数期间都保持在lr寄存器中。并且解包信息让您能够区分这两种类型的函数("基于frame"和"无frame")。
示例
use macho_unwind_info::UnwindInfo;
use macho_unwind_info::opcodes::OpcodeX86_64;
let unwind_info = UnwindInfo::parse(data)?;
if let Some(function) = unwind_info.lookup(0x1234)? {
println!("Found function entry covering the address 0x1234:");
let opcode = OpcodeX86_64::parse(function.opcode);
println!("0x{:08x}..0x{:08x}: {}", function.start_address, function.end_address, opcode);
}
命令行使用方法
此仓库还包含两个CLI可执行文件。您可以按如下方式安装它们
% cargo install --examples macho-unwind-info
致谢
非常感谢 @Gankra 在 https://gankra.github.io/blah/compact-unwinding/ 上记录了此格式。
许可证
根据以下任意一种许可证授权:
- Apache License, Version 2.0 (
LICENSE-APACHE
或 http://www.apache.org/licenses/LICENSE-2.0) - MIT license (
LICENSE-MIT
或 http://opensource.org/licenses/MIT)
任选其一。
除非您明确声明,否则根据 Apache-2.0 许可证定义,您有意提交以包含在作品中的任何贡献,都将按照上述方式双许可,不附加任何额外条款或条件。
依赖
~1–1.6MB
~29K SLoC