How to disassemble a memory range with GDB?

124,157

Solution 1

Do you only want to disassemble your actual main? If so try this:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS

Like so:

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.

I don't see your system interrupt call however. (its been a while since I last tried to make a system call in assembly. INT 21h though, last I recall

Solution 2

Yeah, disassemble is not the best command to use here. The command you want is "x/i" (examine as instructions):

(gdb) x/i 0xdeadbeef

Solution 3

This isn't the direct answer to your question, but since you seem to just want to disassemble the binary, perhaps you could just use objdump:

objdump -d program

This should give you its dissassembly. You can add -S if you want it source-annotated.

Solution 4

fopen() is a C library function and so you won't see any syscall instructions in your code, just a regular function call. At some point, it does call open(2), but it does that via a trampoline. There is simply a jump to the VDSO page, which is provided by the kernel to every process. The VDSO then provides code to make the system call. On modern processors, the SYSCALL or SYSENTER instructions will be used, but you can also use INT 80h on x86 processors.

Solution 5

If all that you want is to see the disassembly with the INTC call, use objdump -d as someone mentioned but use the -static option when compiling. Otherwise the fopen function is not compiled into the elf and is linked at runtime.

Share:
124,157
Patrick
Author by

Patrick

A Swiss-made software engineer who likes to play with as many technologies as possible. I'm fluent in Java, dabbled in C#, develop for Android in my spare time. In my job I develop software for businesses, mainly with Eclipse Scout and Java. Also I configure, engineer and maintain our build setup and continuous integration systems, deploy and support our software. #SOreadytohelp

Updated on October 09, 2021

Comments

  • Patrick
    Patrick over 2 years

    I'm trying to disassemble a program to see a syscall assembly instruction (the INT instruction, I believe) and the handler with GDB and have written a little program (see below) for it that opens and closes a file.

    I was able to follow the call to fopen with GDB until it executed a call.

    When I tried to tell GDB "disassemble 0x...." (address of call) it responded with 'No function contains specified address.'

    Is it possible to force GDB to disassemble (or display it in assembler as good as possible) that memory address? If so, how?

    #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;
    }
    
  • Patrick
    Patrick almost 15 years
    ok, then I'll try to look for INT 21h in the future. Thanks for that hint. But what I wanted to try is to follow the call sequence originating in fopen() (don't see it in your code...) 'down' until I can see the INT command.
  • Patrick
    Patrick almost 15 years
    Managed it - The way to go is to use both your answer and Falaina's. I had to compile it statically with gcc --static main.c and then use gdb/objdump to go deep down into the C library. Ultimaltively, it resulted in a call to __open_nocancel, which did an INT 0x80. Thanks to both of you
  • user188012
    user188012 over 13 years
    THANKS! Adding this text to help others find this hint: this is the instruction to be used to disassemble binary blob, disassemble ROM, examine instruction in a binary image file etc. Write a small C program to fread() the binary blob into a buffer. Then do 'x /i' on the buffer.
  • Barry Kelly
    Barry Kelly almost 13 years
    @user188012 if you want to disassemble a binary blob, an easier way to do it is to use a standalone disassembler like ndisasm or similar.
  • k3a
    k3a over 12 years
    You can use: x/i $pc to get the instruction for the pc which is the address of current instruction
  • Hi-Angel
    Hi-Angel almost 10 years
    Note: the disas 0x401050 0x401075 syntax at least in version gdb 7.7 won't work. You have rather write it like disas 0x401050,0x401075. Also probably you might want to add the prefix «/m» to show a source code around: disas \m 0x401050,0x401075
  • Hi-Angel
    Hi-Angel almost 10 years
    ⁺¹ for -S, I didn't knew it could include the source code.
  • GramThanos
    GramThanos almost 9 years
    You can use: "(gdb) x/<number>i 0xaddress" to print <number> of instructions e.x. "(gdb) x/10i 0xaddress" to print 10 instructions
  • shane
    shane almost 8 years
    Is the address 0xdeadbeef of any significance here? I mean to ask that is it any special address?
  • Aydin K.
    Aydin K. over 7 years
    @shane: find more info about it here en.wikipedia.org/wiki/Hexspeak
  • sherrellbc
    sherrellbc about 7 years
    @Patrick, Although this was quite some time ago, it's worth noting that INT 0x80 is just how Linux does it. That is to say, Linux's syscall handler is registered at interrupt 128. Other operating systems may vary -- which they do.
  • FeepingCreature
    FeepingCreature about 5 years
    Thanks! This is perfect for debugging JIT!
  • SasQ
    SasQ about 2 years
    From some reason, x/i SomeAddress shows "(bad)" in GDB. The instruction at this address should be a far jump. What might be the reason for GDB not recognizing it properly as this instruction?