Why Is Gdb Breakpoint Set at the Wrong Address for an X86 Assembly Function

Why is GDB breakpoint set at the wrong address for an x86 assembly function?


How come

By default, GDB tries to skip past function prolog, when you set a breakpoint on a function, or a line on which the function starts.

This tends to be what C developers want, since they usually aren't interested in parameter setup.

If you want something else, use b *address or b &print to prevent GDB from doing its usual thing.

gdb shows wrong addresses while zeroing a buffer

As the comments indicated, there is another variable called buffer in another source file of glibc. Changing the variable name to puffer gives the expected results.
Furthermore, the following line should have made me skeptical:

$1 = (char **) 0x7ffff7fa0250 <buffer>

gdb did not interfered types in my assembler code, but it knew that I put char **s in my buffer.

How to set breakpoint using GDB for x86 assembly when no symbol information is present?

Use something like objdump -f to show you the numeric value of the entry point address. Or inside gdb, info files will show you the entry point.

Copy/paste that value into a gdb command: b *0x... to break at the entry point. You can then single-step from there.


See also the bottom of the x86 tag wiki for some asm-debugging tips, like layout reg.


Sample output from objdump -f:

/bin/ls:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000404870 <<---- copy this address

Instead of finding the entry-point address

b *0 will cause an error when gdb tries to set the breakpoint. This results in stopping before any instructions execute, at the entry point. Delete the bogus breakpoint (or it will keep erroring when you try to single-step or continue).
Stopping at the first machine code instruction in GDB

GDB - Address of breakpoint

It's a virtual address in RAM. You have a position-dependent executable, so the absolute address it will be loaded to is right there in the ELF metadata. (you can use readelf my_program, or the GDB command info files.)

If you had a PIE executable and set a breakpoint before starting it, GDB will give you a breakpoint address that isn't relocated yet, so the first byte of the file is treated as address 0. e.g.

(gdb) b main
Breakpoint 1 at 0x64e: file hello.c, line 3.
(gdb) run
Starting program: /tmp/hello

Breakpoint 1, main () at hello.c:3
(gdb) info br
Num Type Disp Enb Address What
1 breakpoint keep y 0x000055555555464e in main at hello.c:3
breakpoint already hit 1 time

Note that 0x64e and 0x000055555555464e have the same offset within a 4k page, because the file gets mapped to a page-aligned address.

Why doesn't reading back from the address of an int give me back the correct value of the int (C & gdb)

The value 2 you see is after the designated 4 bytes for the integer. You have your input 4 right there occupying the first nibble.

I think comments explain it even better.

How does GDB determine the address to break at when you do break function-name ?

gdb uses a few methods to decide this information.

First, the very best way is if your compiler emits DWARF describing the function. Then gdb can decode the DWARF to find the end of the prologue.

However, this isn't always available. GCC emits it, but IIRC only when optimization is used.

I believe there's also a convention that if the first line number of a function is repeated in the line table, then the address of the second instance is used as the end of the prologue. That is if the lines look like:

< function f >
line 23 0xffff0000
line 23 0xffff0010

Then gdb will assume that the function f's prologue is complete at 0xfff0010.

I think this is the mode used by gcc when not optimizing.

Finally gdb has some prologue decoders that know how common prologues are written on many platforms. These are used when debuginfo isn't available, though offhand I don't recall what the purpose of that is.

How to set exact instruction `gdb` puts a breakpoint on?


How do I

You can set a breakpoint on any instruction you want with b *0x1234 syntax. Example:

(gdb) disas $pc
Dump of assembler code for function main:
=> 0x0000555555555040 <+0>: xor %eax,%eax
0x0000555555555042 <+2>: cmp $0x1,%edi
0x0000555555555045 <+5>: setg %al
0x0000555555555048 <+8>: retq
End of assembler dump.
(gdb) b *0x0000555555555045
Breakpoint 2 at 0x555555555045
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555045 in main ()
(gdb) x/i $pc
=> 0x555555555045 <main+5>: setg %al


Related Topics



Leave a reply



Submit