如何确定程序跳转到无效地址

编程入门 行业动态 更新时间:2024-10-25 17:17:26
本文介绍了如何确定程序跳转到无效地址 - 没有单步执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我试图调试一个多线程程序,它以某种方式结束了 RIP = 0x0 和堆栈中的大量零。有没有什么办法可以找出程序之前只有一条指令?当我尝试单步执行时,结果会有所不同(可能是某种竞争条件),但是如果我只是启动程序并放手,它就会一直登录到这里。

I'm trying to debug a multithreaded program, which somehow ends up with RIP=0x0 and lots of zeros on the stack. Is there any way to find out where the program was just one instruction before? When I try single-stepping, the result appears different (likely some race condition), but if I just start the program and let it go, it consistently lands here.

那么是否有任何方法可以在实际采用之前将跳转/调用地址设置为零,而无需执行单步执行或仿真?是否有一些寄存器可以保存前面指令的地址?

So is there any way to trap on a jump/call to zero address before it is actually taken, without doing single-stepping or emulation? Is there maybe some register holding address of previous instruction?

推荐答案

以前的指令?

Is there maybe some register holding address of previous instruction?

没有这样的寄存器,但有 Branch Trace Store ,GDB通过记录btrace 命令来支持它。

There is no such register, but there is Branch Trace Store, and GDB supports it with record btrace command.

注意:从上面的维基百科文章:

Note: from above wikipedia article:

Intel处理器上的分支跟踪可能导致应用程序运行时间减少40倍。

Branch tracing on Intel processors can cause 40x application run-time slow down.

以下是如何使用记录btrace 来调试您的问题:

Here is how you could use record btrace to debug your problem:

cat t.c #include <string.h> int bar() { char buf[10]; memset(buf, 0, sizeof(buf)); memset(buf, 'A', 100); // overflow } int foo() { return bar(); } int main() { return foo(); } gcc -g t.c -fno-stack-protector gdb -q ./a.out (gdb) run Starting program: /tmp/a.out Program received signal SIGSEGV, Segmentation fault. 0x0000000000400562 in bar () at t.c:7 7 } (gdb) bt 5 #0 0x0000000000400562 in bar () at t.c:7 #1 0x4141414141414141 in ?? () #2 0x4141414141414141 in ?? () #3 0x4141414141414141 in ?? () #4 0x4141414141414141 in ?? () (More stack frames follow...)

难以调试:我们有

(gdb) start Temporary breakpoint 1 at 0x400577: file t.c, line 16. Starting program: /tmp/a.out Temporary breakpoint 1, main () at t.c:16 16 return foo(); (gdb) record btrace (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x0000000000400562 in bar () at t.c:7 7 } (gdb) record instruction-history 719 0x00007ffff7a9e531 <memset+113>: movdqu %xmm8,0x20(%rdi) 720 0x00007ffff7a9e537 <memset+119>: movdqu %xmm8,-0x30(%rdi,%rdx,1) 721 0x00007ffff7a9e53e <memset+126>: movdqu %xmm8,0x30(%rdi) 722 0x00007ffff7a9e544 <memset+132>: movdqu %xmm8,-0x40(%rdi,%rdx,1) 723 0x00007ffff7a9e54b <memset+139>: add %rdi,%rdx 724 0x00007ffff7a9e54e <memset+142>: and $0xffffffffffffffc0,%rdx 725 0x00007ffff7a9e552 <memset+146>: cmp %rdx,%rcx 726 0x00007ffff7a9e555 <memset+149>: je 0x7ffff7a9e4fa <memset+58> 727 0x00007ffff7a9e4fa <memset+58>: repz retq 728 0x0000000000400561 <bar+52>: leaveq

上面的指令跟踪告诉我们,在从 bar 返回时崩溃,并且 memset

Above instruction trace tells us that we crashed on return from bar, and that memset was executing just before the return.

(gdb) record instruction-history - 709 0x00007ffff7a9e4cd <memset+13>: punpcklwd %xmm8,%xmm8 710 0x00007ffff7a9e4d2 <memset+18>: pshufd $0x0,%xmm8,%xmm8 711 0x00007ffff7a9e4d8 <memset+24>: cmp $0x40,%rdx 712 0x00007ffff7a9e4dc <memset+28>: ja 0x7ffff7a9e510 <memset+80> 713 0x00007ffff7a9e510 <memset+80>: lea 0x40(%rdi),%rcx 714 0x00007ffff7a9e514 <memset+84>: movdqu %xmm8,(%rdi) 715 0x00007ffff7a9e519 <memset+89>: and $0xffffffffffffffc0,%rcx 716 0x00007ffff7a9e51d <memset+93>: movdqu %xmm8,-0x10(%rdi,%rdx,1) 717 0x00007ffff7a9e524 <memset+100>: movdqu %xmm8,0x10(%rdi) 718 0x00007ffff7a9e52a <memset+106>: movdqu %xmm8,-0x20(%rdi,%rdx,1) (gdb) 699 0x00007ffff7a9e5b6 <memset+246>: retq 700 0x000000000040054b <bar+30>: lea -0x10(%rbp),%rax 701 0x000000000040054f <bar+34>: mov $0x64,%edx 702 0x0000000000400554 <bar+39>: mov $0x41,%esi 703 0x0000000000400559 <bar+44>: mov %rax,%rdi 704 0x000000000040055c <bar+47>: callq 0x400410 <memset@plt>

...这就是 memset 被调用。

... And this is where the memset was called from.

705 0x0000000000400410 <memset@plt+0>: jmpq *0x200c02(%rip) # 0x601018 <memset@got.plt> 706 0x00007ffff7a9e4c0 <memset+0>: movd %esi,%xmm8 707 0x00007ffff7a9e4c5 <memset+5>: mov %rdi,%rax 708 0x00007ffff7a9e4c8 <memset+8>: punpcklbw %xmm8,%xmm8

更多推荐

如何确定程序跳转到无效地址

本文发布于:2023-08-07 10:26:38,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:跳转到   地址   程序

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!