Skip to content
Advertisement

Cannot insert breakpoints. Addresses with low values

I’m trying to debug this simple C program:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("Hellon");
}

But when I disassemble the main function I get this:

(gdb) disas main
Dump of assembler code for function main:
    0x000000000000063a <+0>:    push   rbp
    0x000000000000063b <+1>:    mov    rbp,rsp
    0x000000000000063e <+4>:    sub    rsp,0x10
    0x0000000000000642 <+8>:    mov    DWORD PTR [rbp-0x4],edi
    0x0000000000000645 <+11>:   mov    QWORD PTR [rbp-0x10],rsi
    0x0000000000000649 <+15>:   lea    rdi,[rip+0x94]        # 0x6e4
    0x0000000000000650 <+22>:   call   0x510 <puts@plt>
    0x0000000000000655 <+27>:   mov    eax,0x0
    0x000000000000065a <+32>:   leave  
    0x000000000000065b <+33>:   ret    
End of assembler dump.

And this is already pretty strange because addresses starts with a prefix of 4… for 32 bit executables and 8… for 64 bit executables I think.

But going on I then put a breakpoint:

(gdb) b *0x0000000000000650
Breakpoint 1 at 0x650

I run it and I get this error message:

Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x650

Advertisement

Answer

Your code was most probably compiled as Position-Independent Executable (PIE) to allow Address Space Layout Randomization (ASLR). On some systems, gcc is configured to create PIEs by default (that implies the options -pie -fPIE being passed to gcc).

When you start GDB to debug a PIE, it starts reading addresses from 0, since your executable was not started yet, and therefore not relocated (in PIEs, all addresses including the .text section are relocatable and they start at 0, similar to a dynamic shared object). This is a sample output:

$ gcc -o prog main.c -pie -fPIE
$ gdb -q prog
Reading symbols from prog...(no debugging symbols found)...done.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x000000000000071a <+0>:     push   rbp
   0x000000000000071b <+1>:     mov    rbp,rsp
   0x000000000000071e <+4>:     sub    rsp,0x10
   0x0000000000000722 <+8>:     mov    DWORD PTR [rbp-0x4],edi
   0x0000000000000725 <+11>:    mov    QWORD PTR [rbp-0x10],rsi
   0x0000000000000729 <+15>:    lea    rdi,[rip+0x94]        # 0x7c4
   0x0000000000000730 <+22>:    call   0x5d0 <puts@plt>
   0x0000000000000735 <+27>:    mov    eax,0x0
   0x000000000000073a <+32>:    leave
   0x000000000000073b <+33>:    ret
End of assembler dump.

As you can see, this shows a similar output to yours, with .text adresses starting at low values.

Relocation takes place once you start your executable, so after that, your code will be placed at some random address in your process memory:

gdb-peda$ start
...
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x00002b1c8f17271a <+0>:     push   rbp
   0x00002b1c8f17271b <+1>:     mov    rbp,rsp
=> 0x00002b1c8f17271e <+4>:     sub    rsp,0x10
   0x00002b1c8f172722 <+8>:     mov    DWORD PTR [rbp-0x4],edi
   0x00002b1c8f172725 <+11>:    mov    QWORD PTR [rbp-0x10],rsi
   0x00002b1c8f172729 <+15>:    lea    rdi,[rip+0x94]        # 0x2b1c8f1727c4
   0x00002b1c8f172730 <+22>:    call   0x2b1c8f1725d0 <puts@plt>
   0x00002b1c8f172735 <+27>:    mov    eax,0x0
   0x00002b1c8f17273a <+32>:    leave
   0x00002b1c8f17273b <+33>:    ret
End of assembler dump.

As you can see, the addresses now take “real” values that you can set breakpoints to. Note that usually you will still not see the effect of ASLR in GDB though, since it disables randomization by default (debugging a program with randomized location would be cumbersome). You can check this with show disable-randomization. If you really want to see the effects of ASLR in your PIE, set disable-randomization off. Then every run will relocate your code to random addresses.

So the bottom line is: When debugging PIE code, start your program in GDB first and then figure out the addresses.

Alternatively, you can explicitly disable the creation of PIE code and compile your application using gcc filename.c -o filename -no-pie -fno-PIE. My system does not enforce PIE creation by default, so unfortunately I don’t know about the implications of disabling PIE on such a system (would be glad to see comments on that).

For a more comprehensive explanation of position-independent code (PIC) in general (which is of utmost importance for shared libraries), have a look at Ulrich Drepper’s paper “How to Write Shared Libraries”.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement