这些已经足够支撑我们在调试寡居下来的部分轻松地处理存放器,所以我们如今可以把这些添加到我们的用户界面。
显示我们的存放器
如今根据要请求的存放器,我们要攫取 regs。我们可以写一个很大年夜的 switch 语句,但因为我们 g_register_descriptors 表的构冒昧序和 user_regs_struct 雷同,我们只须要搜刮存放器描述符的索引,然后作为 uint64_t 数组拜访 user_regs_struct 久煨。(你也可以从新排序 reg 列举变量,然后应用索引把它们转换为底层类型,但第一次我就应用这种方法编写,它能正常工作,我也就懒得改它了。)
- uint64_t debugger::get_pc() {
- return get_register_value(m_pid, reg::rip);
- }
- void debugger::set_pc(uint64_t pc) {
- set_register_value(m_pid, reg::rip, pc);
- }
这里我们要做的就是给 handle_command 函数添加一个敕令。经由过程下面的代码,用户可以输入 register read rax、 register write rax 0x42 以及类似的语句。
- else if (is_prefix(command, "register")) {
- if (is_prefix(args[1], "dump")) {
- dump_registers();
- }
- else if (is_prefix(args[1], "read")) {
- std::cout << get_register_value(m_pid, get_register_from_name(args[2])) << std::endl;
- }
- else if (is_prefix(args[1], "write")) {
- std::string val {args[3], 2}; //assume 0xVAL
- set_register_value(m_pid, get_register_from_name(args[2]), std::stol(val, 0, 16));
- }
- }
如今我们可以编写一堆函数来和存放器交互。我们欲望可以攫取存放器、写入数据、根据 DWARF 存放器编号获取值,以及经由过程名称查找存放器,反之类似。让我们先大年夜实现 get_register_value 开端:
接下来做什么?
设置断点的时刻我们已经攫取和写入内存,是以我们只须要添加一些函数用于隐蔽 ptrace 调用。
- uint64_t debugger::read_memory(uint64_t address) {
- return ptrace(PTRACE_PEEKDATA, m_pid, address, nullptr);
- }
- void debugger::write_memory(uint64_t address, uint64_t value) {
- ptrace(PTRACE_POKEDATA, m_pid, address, value);
- }
你可能想要添加支撑一次攫取或者写入多个字节,你可以在每次欲望攫取另一个字节时经由过程递增地址来实现。如不雅你须要的话,你也可以应用 process_vm_readv 和 process_vm_writev 或 /proc/<pid>/mem 代替 ptrace。
- else if(is_prefix(command, "memory")) {
- std::string addr {args[2], 2}; //assume 0xADDRESS
- if (is_prefix(args[1], "read")) {
- std::cout << std::hex << read_memory(std::stol(addr, 0, 16)) << std::endl;
- }
- if (is_prefix(args[1],
推荐阅读
在当局改革范畴,淄博市大年夜力履行“互联网+”政务办事,开通网上干事大年夜厅、微信"大众,"办事平台、移动办公APP等网上申报功能,干事企业和群众足不出户就可解决审批,市级网上解决事项零次劈叉和一次>>>详细阅读
地址:http://www.17bianji.com/lsqh/36047.html
1/2 1