This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Function addresses on the AVR


Hey there.  I've been looking at uses of CONVERT_FROM_FUNC_PTR_ADDR
with an eye towards fixing up some related stuff, and I noticed two
things about avr-tdep.c:

- It provides a function for CONVERT_FROM_FUNC_PTR_ADDR that
  multiplies the address by two, and

- There's a comment saying:

     ...
     The problem manifests itself when trying to set a breakpoint in a
     function which resides in the upper half of the instruction space and
     thus requires a 17-bit address.
     ...

Both of these things caught my eye, and made me wonder if there
weren't a way to help the AVR port work better, and incidentally
remove your use of CONVERT_FROM_FUNC_PTR_ADDR altogether.

>From looking at the AVR manual, I gather that code addresses are 16
bits wide, and refer to 16-bit words in the program memory.  So the
architecture can address 64k words (128k bytes), of code.
Instructions are always 16 or 32 bits long, so the processor never
addresses them by byte at all.  So as far as the processor is
concerned, code addresses are 16 bit long.  Is that right?

But GDB and the rest of the GNU toolchain all want to use byte
addresses for everything, so in the unified address space you use for
linking, your program memory appears as 128k bytes at addresses 0x0
through 0x1ffff.  Whatever SRAM the system has appears at 0x800000 in
this unified address space; a pointer value of 0x0 refers to the byte
at 0x800000 in the unified space.  Is that right?

I'll bet C programs represent data pointers as byte addresses, but
pointers to a functions as word addresses --- 16-bit values you could
load directly into the PC.  And I'll bet return addresses on the stack
are also just 16-bit values.

So this means that the toolchain is using 17-bit byte addresses, while
the running program is using 16-bit word addresses.  Right?

If so, I think this is exactly the program that POINTER_TO_ADDRESS and
ADDRESS_TO_POINTER are supposed to solve.  They're described in more
detail in gdb/doc/gdbint.texinfo, in the section called "Pointers Are
Not Always Addresses"; that even uses a Harvard architecture as an
example.

You're using them to add and remove the upper "prefix" bits, which is
partly what they're for, but they're also supposed to handle
converting between the word addresses that appear in the running
program, and the byte addresses that GDB uses to actually read and
write instruction memory.

The general idea is that CORE_ADDR values should always be byte
addresses, and if the processor's natural form for function pointers
and return addresses on the stack is not a byte address, then
POINTER_TO_ADDRESS converts the natural form to byte addresses, and
ADDRESS_TO_POINTER converts byte addresses to the natural form.

In other words, POINTER_TO_ADDRESS should shift the value left one bit
when the type is a pointer to function or method --- turning the word
address into a byte address --- and ADDRESS_TO_POINTER should shift
the value right one bit when the type is right --- turning the byte
address back into a word address.

If you change your methods to do this, and dedicate the full range 0x0
-- 0x1ffff for byte-addressed program memory (which I'll bet is what
gas, ld, and the binutils are doing already), and then get rid of the
definition of CONVERT_FROM_FUNC_PTR_ADDR, then I think a bunch of
stuff should start to work better.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]