breakpoint at address on Atmel AVR - parsing
Petr Hluzín
petr.hluzin@gmail.com
Thu Aug 16 22:57:00 GMT 2012
Hello
It seems GDB-7.4.91 badly parses program-space addresses given to
`break' and `disassemble' at Atmel AVR architecture: an "0x4d2"
becomes 0x8004d2.
(gdb) disassemble 0x4d2,0x4dc
Dump of assembler code from 0x8004d2 to 0x8004dc:
0x008004d2 <Fatfs+682>: rjmp .-1126 ; 0x80006e
0x008004d4 <Fatfs+684>: rjmp .-1126 ; 0x800070
0x008004d6 <Fatfs+686>: rjmp .-1126 ; 0x800072
0x008004d8 <Fatfs+688>: rjmp .-1126 ; 0x800074
0x008004da <Fatfs+690>: rjmp .-1126 ; 0x800076
(gdb) p & Fatfs
$4 = (FATFS (*)[2]) 0x800228 <Fatfs>
On Atmel AVR chips 0x8004d2 is an address in data RAM, not in a
program memory (harward arch). Program space addresses are in range 0
to 0x007fffff.
The disassembly command incorectly parses the input range and decodes
random data as instructions. In this example the `Fatfs' hapens to be
a static variable at that address (static FATFS* Fatfs[2]).
Using a function name instead of an address (e.g. `break main' and
`disassemble main') works correctly.
This also affects `break' command:
(gdb) break *0x20
Breakpoint 1 at 0x8000020
(Note: this will be rejected by a remote target when user attempts to
continue because only data breakpoints are accepted in RAM range.)
GDB understands that program counter (PC) points to a code
(__trampolines_start is a C runtime initialization), however it
incorrectly thinks that stack pointer (SP) points to code (__vectors
is interrupt vector table):
(gdb) info registers
...
r30 0xcd 205
r31 0xcd 205
SREG 0x0 0
SP 0x0 0x0 <__vectors>
PC2 0x4e6 1254
pc 0x4e6 0x4e6 <__trampolines_start>
I debugged GDB and the 0x4d2 -> 0x008004d2 transformation happens at
avr_make_saddr(), at this place:
#0 avr_make_saddr (x=0) at avr-tdep.c:256
#1 avr_integer_to_address () at avr-tdep.c:338
#2 gdbarch_integer_to_address () at gdbarch.c:2531
#3 value_as_address () at value.c:2392
#4 disassemble_command (arg=0x47331b7 ", 0x4", from_tty=1)
#5 do_cfunc (c=0x5e9d130, args=0x47331b4 "0x0, 0x4", from_tty=1)
#6 cmd_func (cmd=..., args="0x0, 0x4", from_tty=1) at ./cli/cli-decode.c:1758
#7 execute_command (p= "4", from_tty=1) at top.c:484
#8 command_handler (command= "disassemble 0x0, 0x4")
The value_as_address () contains a lot of comments explaining the
desired behavior [1]:
/* Some architectures (e.g. Harvard), map instruction and data
addresses onto a single large unified address space. For
instance: An architecture may consider a large integer in the
range 0x10000000 .. 0x1000ffff to already represent a data
addresses (hence not need a pointer to address conversion) while
a small integer would still need to be converted integer to
pointer to address. Just assume such architectures handle all
integer conversions in a single function. */
/* JimB writes:
...
AndrewC pointed out that users aren't complaining about how GDB
casts integers to pointers; they are complaining that they can't
take an address from a disassembly listing and give it to `x/i'.
This is certainly important.
Adding an architecture method like integer_to_address() certainly
makes it possible for GDB to "get it right" in all circumstances
--- the target has complete control over how things get done, so
people can Do The Right Thing for their target without breaking
anyone else. The standard doesn't specify how integers get
converted to pointers; usually, the ABI doesn't either, but
ABI-specific code is a more reasonable place to handle it. */
On this harward architrecture this is what GCC does:
void * p = 0x42; // compiles to 0x8000042
void (*func)() = 0x42; // compiles to 0x42
In case of `break' and `disassemble' commands an argument 0x42 should
be recognized as a code address. This is how GDB show register values
and what is a system ABI custom. (Personally I would prefer different
address space layout.)
How should avr_integer_to_address() handle integers?
The current behavior makes breakpoint-at-address impossible and breaks
IDEs (at least Qt Creator). There are many callers of value_as_address
(), I failed to deduce its contract.
[1] http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.c?cvsroot=src
--
Petr Hluzin
More information about the Gdb
mailing list