如何使用GDB分解内存范围?

如何使用GDB分解内存范围?,gdb,disassembly,Gdb,Disassembly,我试图反汇编一个程序来查看syscall汇编指令(我相信是INT指令)和带有GDB的处理程序,并为它编写了一个小程序(见下文)来打开和关闭一个文件 我能够通过GDB跟踪对fopen的调用,直到它执行了一个调用 当我试图告诉GDB“反汇编0x…”(调用地址)时,它的响应是“没有包含指定地址的函数” 是否有可能强制GDB反汇编(或尽可能在汇编程序中显示)该内存地址?如果是,怎么做 #include <stdio.h> #include <stdlib.h> int main

我试图反汇编一个程序来查看syscall汇编指令(我相信是INT指令)和带有GDB的处理程序,并为它编写了一个小程序(见下文)来打开和关闭一个文件

我能够通过GDB跟踪对fopen的调用,直到它执行了一个调用

当我试图告诉GDB“反汇编0x…”(调用地址)时,它的响应是“没有包含指定地址的函数”

是否有可能强制GDB反汇编(或尽可能在汇编程序中显示)该内存地址?如果是,怎么做

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE* f;
    f = fopen("main.c", "r");
    if (!f) { 
      perror("open");
      return -1;
    }
    fclose(f);
    return 0;
}
#包括
#包括
int main(){
文件*f;
f=fopen(“main.c”、“r”);
如果(!f){
佩罗(“公开”);
返回-1;
}
fclose(f);
返回0;
}

您是否只想拆解实际的主泵?如果是这样,请尝试以下方法:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS
像这样:

USER@MACHINE /cygdrive/c/prog/dsa
$ gcc-3.exe -g main.c

USER@MACHINE /cygdrive/c/prog/dsa
$ gdb a.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
...
(gdb) info line main
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+
(gdb) disas 0x401050 0x401075
Dump of assembler code from 0x401050 to 0x401075:
0x00401050 <main+0>:    push   %ebp
0x00401051 <main+1>:    mov    %esp,%ebp
0x00401053 <main+3>:    sub    $0x18,%esp
0x00401056 <main+6>:    and    $0xfffffff0,%esp
0x00401059 <main+9>:    mov    $0x0,%eax
0x0040105e <main+14>:   add    $0xf,%eax
0x00401061 <main+17>:   add    $0xf,%eax
0x00401064 <main+20>:   shr    $0x4,%eax
0x00401067 <main+23>:   shl    $0x4,%eax
0x0040106a <main+26>:   mov    %eax,-0xc(%ebp)
0x0040106d <main+29>:   mov    -0xc(%ebp),%eax
0x00401070 <main+32>:   call   0x4010c4 <_alloca>
End of assembler dump.
USER@MACHINE/cygdrive/c/prog/dsa
$gcc-3.exe-g main.c
USER@MACHINE/cygdrive/c/prog/dsa
$gdb a.exe
GNU gdb 6.8.0.20080328-cvs(cygwin专用)
...
(gdb)主信息线

“main.c”的第3行开始于地址0x401050,结束于0x401075这不是您问题的直接答案,但由于您似乎只是想反汇编二进制文件,也许您可以使用
objdump

objdump -d program

这应该给你它的组装。如果希望对其进行源代码注释,可以添加
-S

可以通过添加-S开关强制gcc直接输出到汇编代码

gcc -S hello.c

是的,在这里反汇编不是最好的命令。 您需要的命令是“x/i”(按说明检查):


如果您只想通过INTC调用查看反汇编,请使用前面提到的objdump-d,但在编译时使用-static选项。否则,fopen函数不会编译到elf中,而是在运行时链接。

fopen()是一个C库函数,因此您不会在代码中看到任何系统调用指令,只是一个常规函数调用。在某种程度上,它确实叫开放(2),但它是通过蹦床来实现的。只需跳转到VDSO页面,该页面由内核提供给每个进程。VDSO然后提供代码进行系统调用。在现代处理器上,将使用SYSCALL或SYSENTER指令,但您也可以在x86处理器上使用INT 80h。

您不必使用gdb。GCC会这样做

 gcc -S foo.c
这将创建foo.s,它是程序集

gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst

上述版本将创建一个清单文件,其中包含C及其生成的程序集

gdb反汇编有一个a/m,在指令旁边包含源代码。这相当于objdump-S,还有一个额外的好处,就是只限于一个感兴趣的函数(或地址范围)。

fopen()不是系统调用,而是对C标准库的调用。为什么你认为系统调用必须通过INT指令进行?我可能错了,但我们被告知fopen调用最终会导致系统调用内核来打开文件并返回文件描述符?Patrick:是的,但不需要直接这样做。通常它调用libc函数,然后该函数进入内核。但是调用内核不仅可以使用int(这很慢),还可以使用syscall/sysenter,具体取决于处理器体系结构…kexik-感谢您提供的信息。我看到维基百科在其系统调用文章()中提到了这一点。显然,Linux开始在2.5内核中使用特殊调用。关于我的操作系统架构,我学到了另一件事。好的,那么我将尝试在将来寻找INT21H。谢谢你的提示。但我想尝试的是遵循源自fopen()的调用序列(在代码中看不到它…“向下”,直到我可以看到INT命令。管理它-方法是同时使用您的答案和Falaina的答案。我必须使用gcc——static main.c静态编译它,然后使用gdb/objdump深入c库。最后,它导致对uuu open_nocancel的调用,该调用执行INT 0x80。感谢你们注意:
disas 0x401050 0x401075
语法至少在gdb7.7版本中是不起作用的。您应该像
disas 0x401050,0x401075那样编写它。您可能还想添加前缀«/m»来显示源代码:
disas\m 0x401050,0x401075
@Patrick,尽管这是很久以前的事了,但值得注意的是,
INT 0x80
正是Linux所做的。也就是说,Linux的系统调用处理程序在中断128处注册。其他操作系统可能会有所不同——它们确实如此。谢谢!添加此文本以帮助其他人找到此提示:这是用于反汇编二进制blob、反汇编ROM、检查二进制图像文件中的指令等的指令。编写一个小型C程序,将二进制blob放入缓冲区。然后在缓冲区上执行“x/i”。@user188012如果要反汇编二进制blob,更简单的方法是使用独立的反汇编程序,如NDISSM或类似程序。您可以使用:x/i$pc获取pc的指令,该指令是当前指令的地址。您可以使用:“(gdb)x/i 0xaddress”打印指令e.x.“(gdb)x/10i 0xaddress”打印10条指令地址0xaddress在这里有意义吗?我的意思是问有没有特别的地址?⁺对于
-S
,我不知道它可能包含源代码。
gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst