This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
RE: Harvard architecture and gdb
- From: <duane at duaneellis dot com>
- To: "Luis Machado" <lgustavo at codesourcery dot com>, "James Bowman" <james dot bowman at ftdichip dot com>, "gdb at sourceware dot org" <gdb at sourceware dot org>
- Date: Wed, 13 Jan 2016 11:06:28 -0700
- Subject: RE: Harvard architecture and gdb
- Authentication-results: sourceware.org; auth=none
> 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)
http://sourceforge.net/p/openocd/mailman/openocd-devel/thread/20150428234557.8376.qmail@stuge.se/
====
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
interface)
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
interface.
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
attribute.
Lauterbach's terms are: "Access Class" - an example can be found here:
http://www2.lauterbach.com/pdf/debugger_arm.pdf
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"
structure.
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 =
0x3234
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.
-Duane.