│0x565554fd <main> lea 0x4(%esp),%ecx │
│0x56555501 <main+4> and $0xfffffff0,%esp │
│0x56555504 <main+7> pushl -0x4(%ecx) │
│0x56555507 <main+10> push %ebp │
│0x56555508 <main+11> mov %esp,%ebp │
│0x5655550a <main+13> push %ebx │
│0x5655550b <main+14> push %ecx │
│0x5655550c <main+15> call 0x56555529 <__x86.get_pc_thunk.ax> │
│0x56555511 <main+20> add $0x1acb,%eax │
B+>│0x56555516 <main+25> mov %eax,%ebx │
│0x56555518 <main+27> call 0x5655552d <swap> │
│0x5655551d <main+32> mov $0x0,%eax │
│0x56555522 <main+37> pop %ecx │
│0x56555523 <main+38> pop %ebx │
│0x56555524 <main+39> pop %ebp │
│0x56555525 <main+40> lea -0x4(%ecx),%esp │
│0x56555528 <main+43> ret │
│0x56555529 <__x86.get_pc_thunk.ax> mov (%esp),%eax │
│0x5655552c <__x86.get_pc_thunk.ax+3> ret │
│0x5655552d <swap> push %ebp │
│0x5655552e <swap+1> mov %esp,%ebp │
│0x56555530 <swap+3> sub $0x10,%esp │
│0x56555533 <swap+6> call 0x56555529 <__x86.get_pc_thunk.ax> │
│0x56555538 <swap+11> add $0x1aa4,%eax │
│0x5655553d <swap+16> lea 0x3c(%eax),%edx │
│0x56555543 <swap+22> lea 0x2c(%eax),%ecx │
│0x56555549 <swap+28> lea 0x4(%ecx),%ecx
这是东西。请给我任何线索,如何从一开始就使用GDB遍历程序集?每次我启动程序时,它都来自main()函数,而不是__libc_start_main()的开头。
如果有人可以帮我这个忙,我将不胜感激。
最佳答案
使用GDB的starti
命令来run
,但是要在第一条用户空间指令之前停止(即使该指令位于动态链接器内部)。这就像在run
之前的入口点上设置一个临时断点。对于不支持starti
的旧版GDB版本,存在诸如b *0
之类的黑客来创建无效的断点,然后在使用run
后将其删除。 (Stopping at the first machine code instruction in GDB)
或者,如果您只想从__libc_start_main
而不是您的_start
或动态链接程序的_start
开始,请在此处设置一个断点。
从那里,您可以使用si
(又名stepi
)按照说明进行单步操作。
您可能需要layout reg
或layout asm
。
尽管动态链接器会在跳转到可执行文件的gcc -no-pie -fno-pie
之前执行一些代码,但是您可能希望构建非PIE可执行文件(_start
)。
如何从我的代码段中的0x565554fd开始?
这是一个完全不同的问题。
那只是main
的顶部
GDB的一部分是为C调试而设计的,有时喜欢为您省去处理函数序言的麻烦。在这种情况下,32位main
的序言对齐堆栈并使用PC相对方法(因为它是PIE可执行文件)获取GOT指针。
您可以再次b *0x565554fd
和run
您的程序。
或使用非PIE,您可以在首次运行之前轻松获得main
的真实地址。