Harvard architecture and gdb

duane@duaneellis.com duane@duaneellis.com
Wed Jan 13 18:06:00 GMT 2016

> FT32 has two address spaces, flash and RAM. They both occupy addresses starting at address 0. This is similar to AVR. We use a __flash__ modifier to specify address space 1.
> But I am struggling to understand how to describe the architecture to gdb. In particular FT32 uses address spaces to distinguish between pointers to RAM and flash.

Hmm - interesting problem, there are other examples of this when  you
are working in the bare metal world ( a place that GDB does not work
very well )

This subject came upon the OpenOCD mailing list {OpenOCD = Open source
JTAG debugger} here: (see item #2 and #3 in that email)


for example -
     Debugging the Linux kernel, you have:  
     (A) Physical vrs Virtual.
     (B) User vrs Kernel
     (C) Secure vrs Non-Secure [ie: Think ARM TrustZone]
     (D) Hypervisor vrs non-Hypervisor space

If you are dealing with an SOC - such as an ARM based one with a DAP,
there are also multiple address spaces (one for each memory-type DAP

There are also systems that allow you to access target memory *WHILE*
the CPU is running, without halting the CPU - this is a wonderful tool
for debugging!

ARM also has the COPROCESSOR interfaces, which is sort of a memory

Other debuggers, specifically Lauterbach have a prefix that acts as an
attribute. that you can place on the front of an address, in fact you
can also define a SYMBOL that contains both an address *AND* an

Lauterbach's terms are: "Access Class" - an example can be found here:


Specifically page 37, Table: "Access Class"

here's the solution that I think would solve it, but it means some
*MASSIVE* changes internal to GDB, and the GDB protocol

What would be very helpful is this:

Define a Memory address as the combination of 
(A) a Nbit number - this needs to be at least 64bit for all targets,
even if the debug target is 32bit 
    Example: An SOC with a 64bit cpu and a 32bit power management cpu
(B) A route ID {see below}
(C) Route specific flags

There is always 'a default route' ie: RouteID = 0 means do this the
normal way, via the CPU, in the current mode... etc.


there are actually 2 structures needed:

(1) A memory attribute structure
     And a means to create arbitrary target specific attributes.
(2) a memory address structure.

Today GDB passes a address around as a "generic 64bit number" - that
needs to change to become a small structure, the "memory address"

In my mind the structs would look like this:

struct mem_address {
/* RouteID 
 *  0 = default, normal what ever that might be.
 *     then a list of well known semi standardized names
 *  1 = Virtual
 *  2 = Physical
 *  3 = Kernel
 *  4 = IO space
 *  5 = Code
 *  6 = Data
 * ... perhaps other standard names ...
 *  100 ... 200 = Technology specific 
 *  200 ... 300 = another technology 
 *         ie: ARM or MIPs, or AVR specific.
 *  1000 - a range for hardware specific.
    int  route_id;   

/* Modifiers for the route
 * bits[0:15] = might be standard flags.
 * bits[16:32] = defined by the specific route
 *     Example:  bit 0 = virtual vrs phys
 *               bit 1 = clean the cache after the operation
 *               bit [3:2] = user, kernel, Hypervisor, spare
    uint64_t route_flags;

// Of course the address.
    uint64_t address;

And the separately a memory attribute, defined like this:

struct mem_attr {
    const char *name;
    // used to initialize a mem_address:route_id
    uintt4_t route_id;
    // used to initialize a mem_addresss:route_flags
    uint64_t route_flags;

The user should be able to specify, like the Lauterbach solution:

      dump memory at:   SA:0x1234     [ meaning: kernel mode, absolute
address ]

Or create their own
      create attribute:  name = foo,  route = 0x1234,  attribute =

Then use the attribute like this:

      dump memory at:   foo:0x1234

The existing code that parses an address would change - instead of
returning an address (64bit number) would need use a structure.

That code would:
     Recognize the list of prefix names (see: mem_attr:name)
     And initialize a "mem_address" route_id and route_attribute based
on the named attribute.

     If no prefix is found, then the  "route_id = 0, and route_flags = 0
[which is the default]


This sort of stuff needs to be transmitted "over the wire[socket]" to
the target control device [ie: The JTAG-GDB-SERVER] so that it can
access memory correctly.

Oh my this is super invasive.


More information about the Gdb mailing list