Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* GDB and ARM Frame Pointer strangeness
@ 2004-06-07  8:50 Steven Johnson
  2004-06-08  4:25 ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-07  8:50 UTC (permalink / raw)
  To: gdb

Hi all,

I have compiled GDB 6.1 for ARM Cross Debugging. Hosted on X86 Linux.  
Ive been doing this for a while with PowerPC, so im no stranger to it.  
Well, now I have an ARM target and I am writing an ARM remote interface 
to my target communicating using the Remote Protocol over TCP/IP.  The 
strange thing is, right after startup, if I try and write an absolute 
memory location GDB insists on dereferencing the Frame Pointer (R11) and 
reading the address stored there.  It then does something with the 
result and dereferences that.

The problem is, I havent got a program loaded yet. And the Registers are 
just in any old state, a program not having been loaded and run.  
Dereferencing the FP (R11) is causing the target to crash, becasue the 
memory it is trying to access is a random address (being the default 
garbage in the register) and this is causing the target to get a memory 
exception and die.

Not Good.

Why is GDB insisting on de-referencing the FP when all I asked it to do 
is write to an absolute memory location. I have not told it to do 
anything that is frame pointer relative.  The last thing I expect to see 
is 2 memory read packets when i execute:

set (unsigned int)0x0 0x12345

all i should see is the memory write packet.  The single memory write 
packet is all i ever saw with my PowerPC target, it never dereferenced 
the FP on a memory write operation????

Is there a way to turn this undesirable operation off?

Any help would be appreciated.

Also, as an aside, 2 other strange things ive noticed with the ARM GDB:

 it seems "set architecture" causes GDB to crash for ARM targets.  eg 
set architecture armv4t followed by the write indicated above crashes 
GDB.  Leaving it on Auto does not.

and, set osabi does not work with ARM for anything other than "none" or 
"auto" I was trying to set an ABI to an embedded ABI, that theoretically 
doesnt use an FP, but the command doesnt work. Eg,
(gdb) set osabi ARM EABI v1
Ambiguous item "ARM EABI v1 ".

same goes for "ARM EABI v2" and "ARM APCS"

only "none" "default" and "auto" works.

Also, this is a raw GDB, meaning I havent loaded any application.  Im 
just trying to get GDB to talk to my target, so am not interested in 
debugging an actual application yet.  Reading and writing 
registers/memory and disassembling are the big ticket items at the moment.

Steven Johnson


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-07  8:50 GDB and ARM Frame Pointer strangeness Steven Johnson
@ 2004-06-08  4:25 ` Steven Johnson
  2004-06-08  4:29   ` Daniel Jacobowitz
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-08  4:25 UTC (permalink / raw)
  To: Steven Johnson; +Cc: gdb

I have tracked the root cause of GDB reading invalid memory at its whim, 
but am at the moment confused as to the way to solve this problem.

The problem resides in the function: value_assign in valops.c

struct value *
value_assign (struct value *toval, struct value *fromval)
{

  [snip]

  /* Since modifying a register can trash the frame chain, and modifying 
memory
     can trash the frame cache, we save the old frame and then restore 
the new
     frame afterwards.  */
  old_frame = get_frame_id (deprecated_selected_frame);

This is all well and good, but at the beginning of the world, when the 
target is not yet properly initialised, the frame is corrupt.  
Dereferencing R11 (on an ARM) and then looking at that Memory is BAD.  
R11 at the beginning of the world doesnt contain anything valid.

This seems to be a worse problem (to me) than the one supposedly solved 
by the piece of code here.  I would have thought it would only need to 
do this if:
1.  The frame was valid. AND
2. You modify a frame register OR
3. You modify any memory within the current Frame.

Otherwise the operation is un needed. (As far as I can tell).  Is there 
any way to determine if the frame is valid, so that at least that check 
can be added to this code, to prevent GDB illegally accessing invalid 
memory?

Steven Johnson

Steven Johnson wrote:

> Hi all,
>
> I have compiled GDB 6.1 for ARM Cross Debugging. Hosted on X86 Linux.  
> Ive been doing this for a while with PowerPC, so im no stranger to 
> it.  Well, now I have an ARM target and I am writing an ARM remote 
> interface to my target communicating using the Remote Protocol over 
> TCP/IP.  The strange thing is, right after startup, if I try and write 
> an absolute memory location GDB insists on dereferencing the Frame 
> Pointer (R11) and reading the address stored there.  It then does 
> something with the result and dereferences that.
>
> The problem is, I havent got a program loaded yet. And the Registers 
> are just in any old state, a program not having been loaded and run.  
> Dereferencing the FP (R11) is causing the target to crash, becasue the 
> memory it is trying to access is a random address (being the default 
> garbage in the register) and this is causing the target to get a 
> memory exception and die.
>
> Not Good.
>
> Why is GDB insisting on de-referencing the FP when all I asked it to 
> do is write to an absolute memory location. I have not told it to do 
> anything that is frame pointer relative.  The last thing I expect to 
> see is 2 memory read packets when i execute:
>
> set (unsigned int)0x0 0x12345
>
> all i should see is the memory write packet.  The single memory write 
> packet is all i ever saw with my PowerPC target, it never dereferenced 
> the FP on a memory write operation????
>
> Is there a way to turn this undesirable operation off?
>
> Any help would be appreciated.
>
> Also, as an aside, 2 other strange things ive noticed with the ARM GDB:
>
> it seems "set architecture" causes GDB to crash for ARM targets.  eg 
> set architecture armv4t followed by the write indicated above crashes 
> GDB.  Leaving it on Auto does not.
>
> and, set osabi does not work with ARM for anything other than "none" 
> or "auto" I was trying to set an ABI to an embedded ABI, that 
> theoretically doesnt use an FP, but the command doesnt work. Eg,
> (gdb) set osabi ARM EABI v1
> Ambiguous item "ARM EABI v1 ".
>
> same goes for "ARM EABI v2" and "ARM APCS"
>
> only "none" "default" and "auto" works.
>
> Also, this is a raw GDB, meaning I havent loaded any application.  Im 
> just trying to get GDB to talk to my target, so am not interested in 
> debugging an actual application yet.  Reading and writing 
> registers/memory and disassembling are the big ticket items at the 
> moment.
>
> Steven Johnson
>
>


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-08  4:25 ` Steven Johnson
@ 2004-06-08  4:29   ` Daniel Jacobowitz
  2004-06-08  5:02     ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2004-06-08  4:29 UTC (permalink / raw)
  To: Steven Johnson; +Cc: gdb

On Tue, Jun 08, 2004 at 02:24:16PM +1000, Steven Johnson wrote:
> This is all well and good, but at the beginning of the world, when the 
> target is not yet properly initialised, the frame is corrupt.  
> Dereferencing R11 (on an ARM) and then looking at that Memory is BAD.  
> R11 at the beginning of the world doesnt contain anything valid.

It is the responsibility of the stub to be robust against bad reads, in
general.  Most stubs manage this without trouble.

> This seems to be a worse problem (to me) than the one supposedly solved 
> by the piece of code here.  I would have thought it would only need to 
> do this if:
> 1.  The frame was valid. AND
> 2. You modify a frame register OR
> 3. You modify any memory within the current Frame.

GDB has no concept of "valid" in the sense that you're using it. 
"There is always a frame" - if we're connected to a target that has
registers and memory, it has a frame.

If your stub is going to fall down like this I recommend having the
stub initialize registers to point to memory that won't trap when read.

-- 
Daniel Jacobowitz


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-08  4:29   ` Daniel Jacobowitz
@ 2004-06-08  5:02     ` Steven Johnson
  2004-06-08 12:26       ` Mark Salter
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-08  5:02 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb

I simply disagree,

The stub does not know what memory is validly accessable,  It does not 
seem unreasonable that if you do not access a memory location that GDB 
should not attempt to read it.

I can give a number of real worl examples:
1. CPU's that have programmable Chip Selects.  The stub does not have 
any information about how the Chip Selects might be set up, its told to 
read memory, so it does.  If the Chip selects are not set up, the memory 
will not be accessable and therefore not readable.
2. Assembler programs that do not conform to any high level language 
ABI.  I thought GDB could debug Assembler programs.  The way it stands, 
if you put strange (non FP) values in the Frame Pointer register, the 
debugger runs the risk of de-referencing it, and reading the wrong 
memory.  For example,  There could be a "valid" memory location, but 
assembly code puts the address of a memory mapped IO Register in R11 (in 
my case the FP of an ARM).  When debugging, the person debugging the 
code tries to write another address, and GDB conveniently reads the 
address held in R11, without being instructed to.  This Memory Mapped 
IO, could be the sort that is read once, and the contents are lost.  It 
looks like GDB is becoming to bound to someones arbitrary ABI and is 
becoming unsuitable for debugging Assembler.

I dont think this is the intetntion, if it is the case.

I have yet to come across a stub that validates memory addresses.  Stubs 
are usually Lean and Mean.  What criteria would a stub use to validate 
the memory addresses?

I accept that if a person debugging, instructs GDB to access an invalid 
memory location they deserve what they get if that puts their target 
"off the air".  But unless they specifically read a memory address, I 
dont see why GDB goes and does it by itself.  At the very least this 
sort of automatic operation should be able to be turned off.

Further, this is recently introduced, we have never experienced this 
"problem" in earlier versions of GDB.

I am talking about a "set" operation of memory, there is just no 
justification why that should trigger a read, especially when no 
specific ABI is being used, and when the target and stack frame are not 
initialised.

It is wrong to say "if we are connected to a target that has registers 
and memory, it has a frame"  it is only correct to say "if we are 
connected to a target, and it is using an ABI GDB knows about, and it 
has registers and memory, and it is initialised, it has a frame".  Looks 
like something is missing here.

To me, this problem is far worse than the potential of corrupting GDB's 
knowledge of the stack frame.  And it is obviously lately introduced 
(since version 5.1).

It would be ideal if the old behaviour could be retained while still 
retaining the advantages of this change.

Steven

Daniel Jacobowitz wrote:

>On Tue, Jun 08, 2004 at 02:24:16PM +1000, Steven Johnson wrote:
>  
>
>>This is all well and good, but at the beginning of the world, when the 
>>target is not yet properly initialised, the frame is corrupt.  
>>Dereferencing R11 (on an ARM) and then looking at that Memory is BAD.  
>>R11 at the beginning of the world doesnt contain anything valid.
>>    
>>
>
>It is the responsibility of the stub to be robust against bad reads, in
>general.  Most stubs manage this without trouble.
>
>  
>
>>This seems to be a worse problem (to me) than the one supposedly solved 
>>by the piece of code here.  I would have thought it would only need to 
>>do this if:
>>1.  The frame was valid. AND
>>2. You modify a frame register OR
>>3. You modify any memory within the current Frame.
>>    
>>
>
>GDB has no concept of "valid" in the sense that you're using it. 
>"There is always a frame" - if we're connected to a target that has
>registers and memory, it has a frame.
>
>If your stub is going to fall down like this I recommend having the
>stub initialize registers to point to memory that won't trap when read.
>
>  
>


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-08  5:02     ` Steven Johnson
@ 2004-06-08 12:26       ` Mark Salter
  2004-06-08 23:47         ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Mark Salter @ 2004-06-08 12:26 UTC (permalink / raw)
  To: sjohnson; +Cc: drow, gdb

>>>>> Steven Johnson writes:

> I have yet to come across a stub that validates memory addresses.  Stubs 
> are usually Lean and Mean.  What criteria would a stub use to validate 
> the memory addresses?

Pretty much all of the ones I have seen are protected against bad
memory accesses. For instance, RedBoot stubs use the most usual
mechanism whereby a fault handler is used to catch accesses which
throw a cpu exception. The stub is in a much better position to
determine if a memory space access is valid or not. GDB only knows
about memory occupied by the program being debugged. A user may
also want to access h/w registers at addresses not known by GDB.

--Mark


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-08 12:26       ` Mark Salter
@ 2004-06-08 23:47         ` Steven Johnson
  2004-06-09 15:14           ` Andrew Cagney
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-08 23:47 UTC (permalink / raw)
  To: Mark Salter; +Cc: gdb, drow

Whether some stubs can check memory ranges or not will depend on the 
stub, its complexity, its implementation and the hardware its running on.

We are using an ARM with a JTAG Interface for Debugging.  Our Stub does 
not run in the hardware, it runs on a PC and communicates to the 
hardware over the JTAG Interface.  Now what any particular 
implementation of the ARM Core is going to do when it accesses invalid 
memory is undefined.  In our case, the processor just dies, going into 
an infinite wait for the memory to respond.

At any rate, this is all beside the point, and does not address the problem.

The problem is, that GDB will try and de-reference a register, assuming 
it is a Frame Pointer.  When in fact, at that point in time it is no 
such thing.  Processors do not define "Frame Pointers" some define 
"Stack Pointers" but commonly, as is the case for ARM and PowerPC, the 
stack pointer is just the "suggested" register to use for such.  ABI's 
define "Frame Pointers" and that is fine, provided you are using an ABI 
that GDB knows about, and the processor has been initialised for that ABI.

In our case, when we reset the target, the target is at the point of 
executing the instruction in the reset vector.  This is truly the 
beginning of the world.  We can and need to debug from this state.  But 
the way GDB stands at the moment, it is unusable to debug a system that 
is running up from a hardware reset condition.

Everything might be ok, if you are using a software interface that you 
have "burned and learned" to get executing and which has set up your 
environment for you, but we have the ability to debug right from a 
hardware reset, the registers are in this state completley random.  
There is no ABI in use, and it is inapproriate for GDB to "assume" at 
this stage that it can dereference R11 and that that register contains 
the frame pointer.

Unless what is being told to me is GDB V6.1 is not a debugger that is 
usefull for debugging low level assembler programs (with custom ABI's). 
Which if it is the case, is a retrograde step from GDB V5.

Im not asking for anyone to do the fix for me, I am quite capable of 
doing the fix, what I am after is some "rational" discussions on the 
issue so that I can effect the "correct" fix, not just a cop out of 
blaming it on the stub.  Its been a while since I participated in 
GDB/Insight development, but ive never had this sort of "cop out" 
response before, and I am not very impressed by it.  The GDB list used 
to be well respected for the open and friendly dialogue.  The first 
response I got ammounted to "you are stupid, its your stubs fault".  
Without even bothering to listen to the root of the query.

"If your stub is going to fall down like this I recommend having the
stub initialize registers to point to memory that won't trap when read."

Is very dismissive, and does not appreciate the fact that my stub does not, and will never, initialsie anything.  I want the target as raw as possible.  Everything the stub does to initialise the target is another area where you have a difference between the program under Debug and the program under Live conditions.  Wherever possible I believe these should be removed.  The only initialisation of the processor I want is that which is done by my executing program under debug.  Otherwise I would be potentially masking defects in my own code, by performing those operations from the stub.

How about giving me some credit for an understanding of debuging embedded targets before replying with dismissive answers that do not address the real problems.

Even when we set the ABI to "none" GDB still does this undesirable "FP" dereferencing.

Regards
Steven Johnson
Embedded Systems Engineer for 18 Years.


Mark Salter wrote:

>>>>>>Steven Johnson writes:
>>>>>>            
>>>>>>
>
>  
>
>>I have yet to come across a stub that validates memory addresses.  Stubs 
>>are usually Lean and Mean.  What criteria would a stub use to validate 
>>the memory addresses?
>>    
>>
>
>Pretty much all of the ones I have seen are protected against bad
>memory accesses. For instance, RedBoot stubs use the most usual
>mechanism whereby a fault handler is used to catch accesses which
>throw a cpu exception. The stub is in a much better position to
>determine if a memory space access is valid or not. GDB only knows
>about memory occupied by the program being debugged. A user may
>also want to access h/w registers at addresses not known by GDB.
>
>--Mark
>
>
>  
>


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-08 23:47         ` Steven Johnson
@ 2004-06-09 15:14           ` Andrew Cagney
  2004-06-10  0:06             ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Andrew Cagney @ 2004-06-09 15:14 UTC (permalink / raw)
  To: Steven Johnson; +Cc: Mark Salter, gdb, drow

> Everything might be ok, if you are using a software interface that you have "burned and learned" to get executing and which has set up your environment for you, but we have the ability to debug right from a hardware reset, the registers are in this state completley random.  There is no ABI in use, and it is inapproriate for GDB to "assume" at this stage that it can dereference R11 and that that register contains the frame pointer. 

There's nothing special about the state of the inferior immediatly after 
a reset.  R11 (just like any other register) could become corrupt at any 
moment in the program's execution, and equally could always be valid 
after a reset.

Also, there's nothing special about the debugger generating apparently 
random memory fetches.  Such a fetch could equally come from the user 
(e.g., via a typo), the target must be robust to such accesses (there is 
the "mem" command to help with this).

Andrew



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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-09 15:14           ` Andrew Cagney
@ 2004-06-10  0:06             ` Steven Johnson
  2004-06-10  2:20               ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-10  0:06 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Mark Salter, gdb, drow

OK,
let me restate the problems as I see it.

1. Whats is the FP register when the target does not use a standard ABI?
2. If there is no FP register, or no standard ABI in use, how can what 
GDB does when it de-references a register, without being instructed to  
by the person controlling the debugger be considered as correct?
3. It is a pipe dream to say "all stubs should be immune to bad memory 
reads" its certainly an ideal goal, but unfortuantely it can not always 
be achieved.
4. Surely its not to much to expect that a person debugging a target can 
connect to the target, read the registers, write a single memory 
location, read another and disconnect without there being any more 
operations being performed than that on the target.
5. I understand that at some level, a person debugging might key in the 
wrong value or de-reference a pointer that is invalid, but that is in 
the control of the person debugging.
6. I understand if you ask GDB to perform a complex operation like a 
backward stack trace, that it needs to dereference the frame and stack 
pointer.

Suggestions I have to address the issue are:
1. If the ABI is set to "none" then operations like "backward stack 
trace" and any other "FP" relative operation shouldnt do anything, 
except tell the user of GDB, "cant backward stack trace, no ABI in use:.
2. Instead of continually resetting the Frame Cache when a memory write 
occurs, mark the frame cache as "invalid" and then when the next 
operation that requires the frame cache executes, reset it then.  (This 
would be more efficient in any event.)

Also, the code in question uses a "deprecated" global variable, It would 
seem that point 2 in the suggestions above would allow the use of this 
deprecated global to be removed.

Andrew Cagney wrote:

>> Everything might be ok, if you are using a software interface that 
>> you have "burned and learned" to get executing and which has set up 
>> your environment for you, but we have the ability to debug right from 
>> a hardware reset, the registers are in this state completley random.  
>> There is no ABI in use, and it is inapproriate for GDB to "assume" at 
>> this stage that it can dereference R11 and that that register 
>> contains the frame pointer. 
>
>
> There's nothing special about the state of the inferior immediatly 
> after a reset.  R11 (just like any other register) could become 
> corrupt at any moment in the program's execution, and equally could 
> always be valid after a reset.

I understand an FP could become "corrupted" at any time (which to me 
suggests it shouldnt be dereferenced unless specifically requested by 
the person debugging, because they are performing a FP related 
operation).  However I fail to see how a register can have valid FP 
contents after a "power on" reset or hard reset, ever.  There isnt even 
a stack frame at this point.  Please point me to a processor that does 
have a valid FP register immediately after reset, because I have never 
seen one. (I have used 80x86, PowerPC, ARM, Mips, MSP430, PIC's, Z80, 
6502, and the list goes on).  Even if its a soft reset, and the FP 
contains the FP that was valid immediately prior the reset, it is 
invalid after the reset, because the execution context has completely 
changed. And further, it might point to memory that no longer existis, 
because the Chip Select mechanisims may also have been reset.

>
> Also, there's nothing special about the debugger generating apparently 
> random memory fetches.  Such a fetch could equally come from the user 
> (e.g., via a typo), the target must be robust to such accesses (there 
> is the "mem" command to help with this).
>
This would be ideal, but not always achievable.  There is nothing 
stopping a person debugging from corrupting the registers that control 
how Chip Selects are set up, setting a chip select to be on variable 
wait state, terminated by an external device, accessing that location 
and hanging the target. (For Example)  This isnt however really the 
point.  The point is dereferencing the FP when there is no ABI in use, 
the FP being a completley ABI specific construct.

What exactly is the setting of ABI to "none" supposed to achieve, 
because I cant see any visible operation that it performs?

Steven Johnson


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  0:06             ` Steven Johnson
@ 2004-06-10  2:20               ` Ian Lance Taylor
  2004-06-10  4:37                 ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Ian Lance Taylor @ 2004-06-10  2:20 UTC (permalink / raw)
  To: Steven Johnson; +Cc: gdb

Steven Johnson <sjohnson@neurizon.net> writes:

> 3. It is a pipe dream to say "all stubs should be immune to bad memory
> reads" its certainly an ideal goal, but unfortuantely it can not
> always be achieved.

Let's get concrete about this one.  Why can this not always be
achieved?  Every stub that I've ever worked with achieves it.

For example, let's look at gdb/i386-stub.c, which is a sample stub for
the i386.  This stub presumes the existence of an external function
exceptionHandler which causes a specified function to be a trap
handler for a specifed exception.  For, e.g., exception 13, the stub
installs a trap handler which, among other things, calls the macro
CHECK_FAULT.  That macro checks whether the global variable
_mem_fault_routine is non-zero.  If it is, the exception handler calls
it in a somewhat tricky fashion, and then returns from the exception.

When the stub is asked to read from a memory location, it sets
_mem_fault_routine to set_mem_err.  The set_mem_err function just sets
the global variable mem_err to 1.

The effect is that if the read from memory is from an invalid address,
the function set_mem_err is called, and the program continue running.
After the memory is fetched, the code checks mem_err.  If mem_err is
set, the memory address was invalid, and the stub indicates that to
the caller.

That is a concrete example of how a common stub handles this issue.
That general approach is used by every stub I've worked with.  Every
processor must give you some mechanism to trap invalid memory
addresses.  If it doesn't, many things become impossible.

If we want to continue this discussion, please explain why your stub
can not do something similar.

Ian


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  2:20               ` Ian Lance Taylor
@ 2004-06-10  4:37                 ` Steven Johnson
  2004-06-10  5:10                   ` Ian Lance Taylor
  2004-06-10  9:03                   ` Richard Earnshaw
  0 siblings, 2 replies; 16+ messages in thread
From: Steven Johnson @ 2004-06-10  4:37 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gdb

OK, Ill break it down.
1. We are not using a stub running on our target.
2. We are using the ARM7TDMI JTAG DEBUG Interface, in the context of 
"stub" we have a program running on a PC that translates the GDB Remote 
Serial Protocol into ARM JTAG Debug Commands.

The exact reason why the target is crashing is obscure, we are using a 
SOC, and there arent any real bus state pins one can probe to determine 
the CPU state, and on recovery into a mode where we can inspect things 
again, everything is reset.  The best information we have at the moment 
is, if we access an invalid (unmapped) memory location the processor 
enters a state, which we have not been able to recover from without a 
hardware reset.  Our current guess is it goes into an infinite bus cycle 
waiting for the memory to respond.  The chip does have Memory Mapped IO 
that can wait indefinately on the state of an external XWAIT pin.  But 
what we know for sure, is that immedialtely after reset, a read to an 
invalid memory address crashes the processor, and the only way we have 
found to recover is a hard reset.

The problem is, we want to use GDB to start "investigating" our hardware 
and to start testing our boot code.  But whilever it is making these 
spurious uncontrolled writes to invalid memory addresses, it is 
preventing us from doing this, because they crash our Target CPU.  
Because our "stub" is really a PC, and it is translating the GDB Remote 
Serial Protocol into ARM JTAG operations, it doesnt know anything 
specific about the hardware, it is designed to function with any 
ARM7TDMI chip with this interface.  So it is inappropriate for it to 
filter addresses, because it has no notion of what addresses are valid 
and what are not.  Yes, if the CPU wasnt crashing and it was advising us 
that an invalid memory location was accessed we could report that data 
appropriately to GDB. (Although im not clear what data you return in 
answer to a memory read when the address is invalid). 

NOTE: WE HAVE NO CODE IN OUR TARGET AT THIS STAGE.  THERE ARE NO 
EXCEPTION HANDLERS.  What a software stub in the target does, is largely 
irrelevent for our purposes, our debug interface not being of this 
kind.  And the way things stand, even if we needed to install exception 
handlers or support routines (which i dont think is necessary BTW), we 
are in a deadly embrace, because we would want to download those 
initially using GDB, but the first memory write (which would in this 
example load the exception handlers or support routines) crashes the 
target because it causes a read to invalid memory. CATCH 22.

This isnt the real problem however, yes if possible i need to make my 
JTAG Debugger more resiliant to memory faults. Yes, as it now stands is 
undesirable, but our tests to date are indicating its a deficiency we 
will probably have to live with.  What it dis do is highlight to me a 
defficiency in this logic ,that was the ultimate root of the operation 
crashing the CPU, inside GDB.

In summary, if there is no ABI that GDB knows about in use, it is 
invalid for GDB to assume a register is the Frame Pointer and then to 
start de-referencing it.  The same can be said for the stack pointer on 
architectures that do not have a "Hardware" stack pointer, but just use 
an arbitrary register as one.

Setting the ABI to "none" doesn't appear to do anything.  Should it?  It 
should prevent these "FP" relative accesses if the ABI is set to "none". 
Otherwise when debugging assembler programs, or hand optimised assembler 
routines, GDB could make all sorts of assumptions about the contents of 
the registers that arent correct, which could in turn lead to corruption 
of the running program, target state, (or in our case) crashing the 
CPU.  When otherwise the program is doing exactly what the programmer 
intended, by using the (nominal) FP register for some other purpose.  
Uncontrolled reading of the wrong memory can be destructive to the state 
of a target board, especially if there are Memory mapped IO registers 
that loose their contents once read.  At the very least there needs to 
be some control over these "high level" operations so that "low level" 
things can be debugged without interference from them.

In my opinion, the discussion about the stub is a largely irrelevent 
side issue and ignores the basic underlying question I had which 
concerns ABI's and GDB's handling of them.  Can anyone provide insight 
into GDB's handling of ABI's and these "High Level" operative 
constructs, and the controls that should exist to manipulate GDB's view 
of the ABI's?

Steven

Ian Lance Taylor wrote:

>Steven Johnson <sjohnson@neurizon.net> writes:
>
>  
>
>>3. It is a pipe dream to say "all stubs should be immune to bad memory
>>reads" its certainly an ideal goal, but unfortuantely it can not
>>always be achieved.
>>    
>>
>
>Let's get concrete about this one.  Why can this not always be
>achieved?  Every stub that I've ever worked with achieves it.
>
>For example, let's look at gdb/i386-stub.c, which is a sample stub for
>the i386.  This stub presumes the existence of an external function
>exceptionHandler which causes a specified function to be a trap
>handler for a specifed exception.  For, e.g., exception 13, the stub
>installs a trap handler which, among other things, calls the macro
>CHECK_FAULT.  That macro checks whether the global variable
>_mem_fault_routine is non-zero.  If it is, the exception handler calls
>it in a somewhat tricky fashion, and then returns from the exception.
>
>When the stub is asked to read from a memory location, it sets
>_mem_fault_routine to set_mem_err.  The set_mem_err function just sets
>the global variable mem_err to 1.
>
>The effect is that if the read from memory is from an invalid address,
>the function set_mem_err is called, and the program continue running.
>After the memory is fetched, the code checks mem_err.  If mem_err is
>set, the memory address was invalid, and the stub indicates that to
>the caller.
>
>That is a concrete example of how a common stub handles this issue.
>That general approach is used by every stub I've worked with.  Every
>processor must give you some mechanism to trap invalid memory
>addresses.  If it doesn't, many things become impossible.
>
>If we want to continue this discussion, please explain why your stub
>can not do something similar.
>
>Ian
>
>
>  
>


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  4:37                 ` Steven Johnson
@ 2004-06-10  5:10                   ` Ian Lance Taylor
  2004-06-10  7:16                     ` Steven Johnson
  2004-06-10  9:03                   ` Richard Earnshaw
  1 sibling, 1 reply; 16+ messages in thread
From: Ian Lance Taylor @ 2004-06-10  5:10 UTC (permalink / raw)
  To: Steven Johnson; +Cc: gdb

Steven Johnson <sjohnson@neurizon.net> writes:

> OK, Ill break it down.
> 1. We are not using a stub running on our target.
> 2. We are using the ARM7TDMI JTAG DEBUG Interface, in the context of
> "stub" we have a program running on a PC that translates the GDB
> Remote Serial Protocol into ARM JTAG Debug Commands.
> 
> The exact reason why the target is crashing is obscure, we are using a
> SOC, and there arent any real bus state pins one can probe to
> determine the CPU state, and on recovery into a mode where we can
> inspect things again, everything is reset.  The best information we
> have at the moment is, if we access an invalid (unmapped) memory
> location the processor enters a state, which we have not been able to
> recover from without a hardware reset.  Our current guess is it goes
> into an infinite bus cycle waiting for the memory to respond.  The
> chip does have Memory Mapped IO that can wait indefinately on the
> state of an external XWAIT pin.  But what we know for sure, is that
> immedialtely after reset, a read to an invalid memory address crashes
> the processor, and the only way we have found to recover is a hard
> reset.

Sounds like an unpleasant situation.  I've never tried to use gdb at
this stage of things.  I've also never used gdb with JTAG.  If I were
in your shoes I would be using console output or perhaps a real JTAG
tool.  I wouldn't try gdb until I had something marginally working on
the board.  gdb isn't that great for bare hardware--it really expects
some sort of program to exist.

> The problem is, we want to use GDB to start "investigating" our
> hardware and to start testing our boot code.  But whilever it is
> making these spurious uncontrolled writes to invalid memory addresses,
> it is preventing us from doing this, because they crash our Target
> CPU.

At the risk of pointing out the completely obvious, if writes to
invalid memory addresses crash the CPU, you've got a real problem if
you are running any type of user code.

> Because our "stub" is really a PC, and it is translating the GDB
> Remote Serial Protocol into ARM JTAG operations, it doesnt know
> anything specific about the hardware, it is designed to function with
> any ARM7TDMI chip with this interface.  So it is inappropriate for it
> to filter addresses, because it has no notion of what addresses are
> valid and what are not.

I think it would be entirely appropriate for this tool to read some
sort of memory map, and filter addresses on that basis.

> Yes, if the CPU wasnt crashing and it was
> advising us that an invalid memory location was accessed we could
> report that data appropriately to GDB. (Although im not clear what
> data you return in answer to a memory read when the address is
> invalid).

The stub returns an E response (a read from valid memory would result
in the actual data).

> In summary, if there is no ABI that GDB knows about in use, it is
> invalid for GDB to assume a register is the Frame Pointer and then to
> start de-referencing it.  The same can be said for the stack pointer
> on architectures that do not have a "Hardware" stack pointer, but just
> use an arbitrary register as one.

gdb isn't written for such environments.  It expects stack frames and
frame pointers.  When it first attaches, it tries to figure out what
the stack frame looks like.  gdb doesn't have an "assembly mode" in
which it presumes that code is not in any sort of function context.

> Setting the ABI to "none" doesn't appear to do anything.  Should it?

I don't think so.  Changing the ABI in general doesn't do much.  For
some targets it affects stuff like where parameters should be passed.
Setting the ABI to "none" means that gdb has no information about the
ABI at all.

> At
> the very least there needs to be some control over these "high level"
> operations so that "low level" things can be debugged without
> interference from them.

Sounds reasonable to me: an assembly mode.  Of course, somebody has to
volunteer to do the work.

Ian


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  5:10                   ` Ian Lance Taylor
@ 2004-06-10  7:16                     ` Steven Johnson
  2004-06-10 21:32                       ` Andrew Cagney
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-10  7:16 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gdb

Ian,

Thankyou for your response.  Yes writing JTAG Interfaces can be 
challenging, as sometimes the documentation leaves a lot to be desired, 
but i've done it before and I am up for the challenge :)

Ian Lance Taylor wrote:

>Steven Johnson <sjohnson@neurizon.net> writes:
>
>  
>
>>In summary, if there is no ABI that GDB knows about in use, it is
>>invalid for GDB to assume a register is the Frame Pointer and then to
>>start de-referencing it.  The same can be said for the stack pointer
>>on architectures that do not have a "Hardware" stack pointer, but just
>>use an arbitrary register as one.
>>    
>>
>
>gdb isn't written for such environments.  It expects stack frames and
>frame pointers.  When it first attaches, it tries to figure out what
>the stack frame looks like.  gdb doesn't have an "assembly mode" in
>which it presumes that code is not in any sort of function context.
>
>  
>
Finally, the nub of the problem.  As a comment, GDB is becomming less 
and less so inclined to like such targets.  We have 2 other JTAG/BDM 
targets, one of which we created, both use GDB V5.1 as their debug 
interface.  These are both operating at the same low level, without 
problem.  GDB V5.1 doesnt seem to do as much automatic target sniffing 
(ive never noticed any that wasnt the direct and predictable result of a 
command I had instigated).  Although I specifically dont do stack traces 
when I know the target isnt in a state to do it properly using GDB V5.1.

>>Setting the ABI to "none" doesn't appear to do anything.  Should it?
>>    
>>
>
>I don't think so.  Changing the ABI in general doesn't do much.  For
>some targets it affects stuff like where parameters should be passed.
>Setting the ABI to "none" means that gdb has no information about the
>ABI at all.
>
>  
>
Ok, maybe ABI='none' can do more than it does now.

>>At
>>the very least there needs to be some control over these "high level"
>>operations so that "low level" things can be debugged without
>>interference from them.
>>    
>>
>
>Sounds reasonable to me: an assembly mode.  Of course, somebody has to
>volunteer to do the work.
>
>  
>
As I stated in a previous message, I dont mind doing work on GDB and 
contributing code. Ive done that already in the past (the assignments 
are already in place) [post hooks are one of my previous contributions, 
which I introduced so that I could automatically set GDB up to program 
the Flash in my target when I downloaded my code through GDB. :)].  All 
I need is some friendly advice when I propose my suggested sollution.  
The suggested solution is as follows:

1.  For the case of the memory write causing a FP De-reference, a check 
is added to determine if the ABI is "none".  ABI="none" meaning the high 
level operations GDB performs are blocked.  If it is none, the FP 
handling at that stage is just skipped.
2. For the case of a stack trace operation, early in the stack trace 
operation, a check is made to see if the ABI = "none" if it does a 
friendly message is printed informing the user that Stack Traces are not 
possible with the ABI set to "none" as there is no known context.

These are the 2 areas that come to mind with regard to this problem.  
Are there others?  I Propose that I work on adding these 2 changes, and 
if there are any other GDB Operations that also require knowledge of the 
ABI and could cause unwanted accesses to the target they are blocked 
accordingy.

In this way, GDB will have moved closer to being "assembly mode" 
friendly.  Im not really sure what is meant by "assembly mode" btw. GDB 
will happilly connect to a target, single step etc, without knowing what 
the code in the target is (ie, without having first loaded any symbol 
information).  It can disassemble no problem.  I have a "S" macro, that 
makes GDB look a bit like DOS "debug" , steps one instruction, prints up 
the registers and the next 8 instructions are disassembled.  Nice and 
easy.  And as I say, when doing this with GDB V5.1 I never had a problem 
with unexpected memory accesses caused by GDB.  To me I never considered 
before that GDB wasnt very good at working at this level, it was always 
capable of doing everything I wanted of it at this level.  Even to the 
point of debugging Assembly code in ROM, and using hardware breakpoints.

What I want to do, is add an option so I can return it to "less 
intelligent" mode, when that mode is appropriate.

Any comments on this proposal before I start on it?

Steven.


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  4:37                 ` Steven Johnson
  2004-06-10  5:10                   ` Ian Lance Taylor
@ 2004-06-10  9:03                   ` Richard Earnshaw
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Earnshaw @ 2004-06-10  9:03 UTC (permalink / raw)
  To: Steven Johnson; +Cc: Ian Lance Taylor, gdb

On Thu, 2004-06-10 at 05:37, Steven Johnson wrote:
> OK, Ill break it down.
> 1. We are not using a stub running on our target.
> 2. We are using the ARM7TDMI JTAG DEBUG Interface, in the context of 
> "stub" we have a program running on a PC that translates the GDB Remote 
> Serial Protocol into ARM JTAG Debug Commands.
> 
> The exact reason why the target is crashing is obscure, we are using a 
> SOC, and there arent any real bus state pins one can probe to determine 
> the CPU state, and on recovery into a mode where we can inspect things 
> again, everything is reset.  The best information we have at the moment 
> is, if we access an invalid (unmapped) memory location the processor 
> enters a state, which we have not been able to recover from without a 
> hardware reset.  Our current guess is it goes into an infinite bus cycle 
> waiting for the memory to respond.  The chip does have Memory Mapped IO 
> that can wait indefinately on the state of an external XWAIT pin.  But 
> what we know for sure, is that immedialtely after reset, a read to an 
> invalid memory address crashes the processor, and the only way we have 
> found to recover is a hard reset.

I suspect the easiest thing to do here is to emulate the memory aborts. 
The way to do this is to construct a virtual memory map in the stub that
describes the valid regions of memory.  Then *every* memory access by
the debugger is checked against the map by the stub which then simulates
an abort if the address isn't valid.  It's a bit slower than having the
hardware do it, but it should make things much more robust.  The number
of entry points in the stub that access memory is quite limited, so it
shouldn't be too much work to track them down.

R.


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10  7:16                     ` Steven Johnson
@ 2004-06-10 21:32                       ` Andrew Cagney
  2004-06-11  0:46                         ` Steven Johnson
  0 siblings, 1 reply; 16+ messages in thread
From: Andrew Cagney @ 2004-06-10 21:32 UTC (permalink / raw)
  To: Steven Johnson; +Cc: Ian Lance Taylor, gdb

(BTW, GDB already both supports and tests (gdb.asm) assembler debugging.)

Perhaphs the problem here isn't as simple as described.  Can you 
determine exactly what sequence of events lead to those memory references?

Andrew


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-10 21:32                       ` Andrew Cagney
@ 2004-06-11  0:46                         ` Steven Johnson
  2004-06-11 15:33                           ` Andrew Cagney
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Johnson @ 2004-06-11  0:46 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Ian Lance Taylor, gdb

Andrew,

Im not sure what you mean by "supports and tests (gdb.asm) assembler 
debugging" is there a GDB command to put into "assembler debugging 
mode"? Or a flag that can be set?  Specifically, what is the (gdb.asm) 
reference?  Is it a document, or command, or something else?  Otherwise 
the statement concordes with my long held beliefs about GDB.

Also, I can provide a lot of information about it, but im not sure what 
"sequence" you are referring to.  Are you reffering to the sequence of 
commands I type in to GDB,  the sequence of code within GDB, or a 
combination of the two.

Do you want me to turn on the GDB Debugging flags for the remote 
protocol and FP management, execute the sequence that causes the problem 
and then post the results?

Steven.

Andrew Cagney wrote:

> (BTW, GDB already both supports and tests (gdb.asm) assembler debugging.)
>
> Perhaphs the problem here isn't as simple as described.  Can you 
> determine exactly what sequence of events lead to those memory 
> references?
>
> Andrew
>
>


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

* Re: GDB and ARM Frame Pointer strangeness
  2004-06-11  0:46                         ` Steven Johnson
@ 2004-06-11 15:33                           ` Andrew Cagney
  0 siblings, 0 replies; 16+ messages in thread
From: Andrew Cagney @ 2004-06-11 15:33 UTC (permalink / raw)
  To: Steven Johnson; +Cc: Ian Lance Taylor, gdb

> Andrew,
> 
> Im not sure what you mean by "supports and tests (gdb.asm) assembler debugging" is there a GDB command to put into "assembler debugging mode"? Or a flag that can be set?  Specifically, what is the (gdb.asm) reference?  Is it a document, or command, or something else?  Otherwise the statement concordes with my long held beliefs about GDB.

See the directory src/gdb/testsuite/gdb.asm/.

> Also, I can provide a lot of information about it, but im not sure what "sequence" you are referring to.  Are you reffering to the sequence of commands I type in to GDB,  the sequence of code within GDB, or a combination of the two.
> 
> Do you want me to turn on the GDB Debugging flags for the remote protocol and FP management, execute the sequence that causes the problem and then post the results?

The internal logic that leads to GDB deciding that it should 
de-reference FP.  ``(gdb) set debug frame ; (gdb) set debug remote 1'' 
might give you a hint, however you'll in the end need to examine GDB's 
internals.

However, and regardless, you need to fix your target.

Andrew


> Steven.
> 
> Andrew Cagney wrote:
> 
>> (BTW, GDB already both supports and tests (gdb.asm) assembler debugging.)
>>
>> Perhaphs the problem here isn't as simple as described.  Can you determine exactly what sequence of events lead to those memory references?
>>
>> Andrew
>>
>>
> 
> 


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

end of thread, other threads:[~2004-06-11 15:33 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-06-07  8:50 GDB and ARM Frame Pointer strangeness Steven Johnson
2004-06-08  4:25 ` Steven Johnson
2004-06-08  4:29   ` Daniel Jacobowitz
2004-06-08  5:02     ` Steven Johnson
2004-06-08 12:26       ` Mark Salter
2004-06-08 23:47         ` Steven Johnson
2004-06-09 15:14           ` Andrew Cagney
2004-06-10  0:06             ` Steven Johnson
2004-06-10  2:20               ` Ian Lance Taylor
2004-06-10  4:37                 ` Steven Johnson
2004-06-10  5:10                   ` Ian Lance Taylor
2004-06-10  7:16                     ` Steven Johnson
2004-06-10 21:32                       ` Andrew Cagney
2004-06-11  0:46                         ` Steven Johnson
2004-06-11 15:33                           ` Andrew Cagney
2004-06-10  9:03                   ` Richard Earnshaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox