public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Harvard architecture and gdb
@ 2016-01-13  3:32 James Bowman
  2016-01-13 13:34 ` Luis Machado
  0 siblings, 1 reply; 3+ messages in thread
From: James Bowman @ 2016-01-13  3:32 UTC (permalink / raw)
  To: gdb

I am maintainer for a Harvard architecture target, FT32.

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. But gdb only seems to actually care about address spaces for *pointers*. When gcc writes the debug info for a plain object, it does not emit the DW_AT_address_class field; nor does gdb handle DW_AT_address_class for non-pointer types.  So I am at a loss to understand how these two variables would be distinguished by gdb:

  int ram_var = 1234;
  __flash__ const int flash_var = 1234;

I suspect I have misunderstood something fundamental. Does anyone have any suggestions? Thanks.

--
James Bowman
FTDI Open Source Liaison

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Harvard architecture and gdb
  2016-01-13  3:32 Harvard architecture and gdb James Bowman
@ 2016-01-13 13:34 ` Luis Machado
  0 siblings, 0 replies; 3+ messages in thread
From: Luis Machado @ 2016-01-13 13:34 UTC (permalink / raw)
  To: James Bowman, gdb

On 01/13/2016 01:32 AM, James Bowman wrote:
> I am maintainer for a Harvard architecture target, FT32.
>
> 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. But gdb only seems to actually care about address spaces for *pointers*. When gcc writes the debug info for a plain object, it does not emit the DW_AT_address_class field; nor does gdb handle DW_AT_address_class for non-pointer types.  So I am at a loss to understand how these two variables would be distinguished by gdb:
>
>    int ram_var = 1234;
>    __flash__ const int flash_var = 1234;
>

Right now, they wouldn't be distinguished.

> I suspect I have misunderstood something fundamental. Does anyone have any suggestions? Thanks.

Though supported by DWARF by means of DW_AT_address_class and also 
DW_AT_segment, this is not readily available in GDB right now.

On the compiler's side, it needs to be adjusted to provide enough debug 
information about those address spaces for each object being used in the 
program.

On GDB's side, the DWARF machinery and other bits need to be expanded to 
not assume a single address space and new hooks need to be added to 
handle reading data properly from those address spaces.

One limitation of GDB in this regard is assuming there are only a couple 
basic pointer types: data and code. Some architectures may have two 
distinct code pointers of different sizes, for example. So GDB needs to 
be able to tell when/how to use each.

Assuming the compiler and GDB are augmented to understand those, then 
the DWARF machinery in GDB can call the correct hooks to either read or 
write from/to flash or RAM.

Does this bring some light to your problem?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: Harvard architecture and gdb
@ 2016-01-13 18:06 duane
  0 siblings, 0 replies; 3+ messages in thread
From: duane @ 2016-01-13 18:06 UTC (permalink / raw)
  To: Luis Machado, James Bowman, gdb

> 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.





^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-01-13 18:06 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-13  3:32 Harvard architecture and gdb James Bowman
2016-01-13 13:34 ` Luis Machado
2016-01-13 18:06 duane

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).