Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [tcf-dev] Question about the step-over logic.

Hi Xavier,

 

It looks like compiler bug to me.

 

If “prepare 2,20” changes r3, CFA rules must be different before and after “prepare 2,20”, but the dump shows <off cfa=00(r3) > in both cases.

 

What compiler is it?

 

> "Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame"

> What happens when there is no previous frame ? (First function ever executed).

 

Words “in the previous frame” are redundant.

The phrase can be shortened to “Typically, the CFA is defined to be the value of the stack pointer at the call”.

Whatever calls the function, stack pointer at the moment of the call is CFA.

 

Regards,

Eugene

 

From: tcf-dev-bounces@xxxxxxxxxxx [mailto:tcf-dev-bounces@xxxxxxxxxxx] On Behalf Of Xavier Pouyollon
Sent: Tuesday, April 22, 2014 12:50 AM
To: TCF Development
Subject: Re: [tcf-dev] Question about the step-over logic.

 

Hi Eugene,

Thanks for the explanation and here is the disassembly and debug_frame rules
So the C-code is :

static void test1(void) {
    test2();
    test2();
    test2();
    test2();
}

          test1:
0010003e:   prepare 2,20
00100042:   jarl    100032,r31
00100046:   jarl    100032,r31
0010004a:   jarl    100032,r31
0010004e:   jarl    100032,r31
00100052:   dispose 20,2
00100056:   jmp     [r31]

The prepare will change SP (aka R3).
The debug_frame says (only dwarf-dump is able to return something valid for RH850)
<    0><0x0010003e:0x00100058><test1><fde offset 0x00000010 length: 0x00000014><eh offset none>
        0x0010003e: <off cfa=00(r3) > <off r31=s >
        0x00100042: <off cfa=00(r3) > <off r31=-4(cfa) >
        0x00100056: <off cfa=00(r3) > <off r31=s >

So let's focus on the first call to test2 : 00100042:   jarl    100032,r31

The CFA is R3.
The JARL does not change R3.

The rule for test2:
<    0><0x00100032:0x0010003e><test2><fde offset 0x00000000 length: 0x0000000c><eh offset none>
        0x00100032: <off cfa=00(r3) > <off r31=s >

So the CFA rules are wrong ? What should they be ?

So R3==R3 leading to broken stepping-over logic in that sample.

I have another question concerning CFA definition:
"Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame".
What happens when there is no previous frame ? (First function ever executed). CFA equals 0 or start stackpointer ?

Thanks !
Xavier.

On 04/18/2014 07:58 PM, Eugene Tarassov wrote:

Hi Xavier,

 

If CFA(printf) equals CFA(a), it will cause stepping problems.

 

However, for example, IAR Systems V850 Calling Convention app note says:

 

If a function (in your case “a”) should call another function (printf) the original value of LP must be stored somewhere. This is normally done on the stack, for example:

ADD –4,SP

ST.W LP,0[SP]

JARL printf,LP

LD.W 0[SP],LP

ADD 4,SP

<do something>

JMP [LP]

 

According to this, CFA(printf) = CFA(a) – 4, because of “ADD –4,SP”. In other words, CFA(a) is not equal CFA(printf)

 

> In fact, this hides another question: The dwarf-specs says:

> "Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame".

> Is it always true ? Can the definition change ?

 

It appears to be true for IAR Systems V850 compiler.

 

However, it is up to compiler to decide how to implement CFA. It might help if you send disassembly to see what compiler has generated in your case.

 

Regards,

Eugene

 

From: tcf-dev-bounces@xxxxxxxxxxx [mailto:tcf-dev-bounces@xxxxxxxxxxx] On Behalf Of Xavier Pouyollon
Sent: Friday, April 18, 2014 1:31 AM
To: TCF Development
Subject: Re: [tcf-dev] Question about the step-over logic.

 

Hi Eugene,

Thanks for the explanation but unfortunately, I'm still a little unclear on some points.

I found this link: http://stackoverflow.com/questions/7534420/gas-explanation-of-cfi-def-cfa-offset
"Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame".

For Pentium arch, I have no issue understanding what's described.

Here, for the nec V850, I have a program doing:

a() {
   printf()   (jarl printf)
}

When I stop in printf(), the calltrace would be:
printf()
a() ==> Caller site.

If I take the definition of the Dwarf-spec : CFA is defined to be the value of stack pointer at the call site in the previous frame.
In a, caller site, we do have r3 (stack pointer).

However, a jarl:
- won't change the stack pointer
- will just store the return @ in r31.

So when I'm at the first instruction of printf(), then CFA should be r3 ? (stack-pointer of caller site).
But in such case,  it would break the stepping-over logic because CFA of a() would be equal to CFA of printf()
The compiler gives for a()
CFA = r3 + 0 (which doesn't look wrong because jarl does not change the stack pointer)
Moreover, since a() is very small and has no local, the rule is the same in the whole function.

If we take the CFA to be the value of the stack-pointer at the call site, since jarl does NOT change the stack-pointer, how could the step-over logic work in such case ?

In fact, this hides another question: The dwarf-specs says:
"Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame".
Is it always true ? Can the definition change ?

I'm having trouble with architectures (ppc, v850) which do NOT change the stack-pointer when doing a call: I can't see how the step-over logic could work with the CFA definition being "value of the stack pointer at the call site in the previous frame".
Yes, the caller function is very small and doesn't "play" with r3. If it did before the call, yes, we could have CFA_of_a() != r3_at_jarl so step-logic would work ?

I must be missing something !

Thanks,
Xavier.

On 04/17/2014 07:46 PM, Eugene Tarassov wrote:

Hi Xavier,
 
First, I would like someone to confirm if my understanding is good.
 
Yes, it is good.
 
Now my question comes when the stepped-line has a call to a function
that has no debug info.
 
In such case the code relies on stack crawl logic (aka crawl_stack_frame()) to compute CFA.
 
... that would be a problem because ext->step_frame_fp == info->fp.
 
Yes, if a non-leaf function frame has 0 size, it would cause ambiguity. However, this is not normal. Non-leaf function frame must at least have space to store return address.
 
Conceptually, I have trouble understanding what CFA should be at the
first instruction of a function.
 
CFA, by definition, should be same at any instruction of a function. However rules to compute CFA can be different at different places in the function.
 
Regards,
Eugene
 
-----Original Message-----
From: tcf-dev-bounces@xxxxxxxxxxx [mailto:tcf-dev-bounces@xxxxxxxxxxx] On Behalf Of Xavier Pouyollon
Sent: Tuesday, April 15, 2014 8:33 AM
To: tcf-dev@xxxxxxxxxxx
Subject: [tcf-dev] Question about the step-over logic.
 
Hi,
 
I'm trying to understand how the line-step-over logic works. Here is my
current understanding (see below).
First, I would like someone to confirm if my understanding is good.
Then, I have a few questions when we try to step-over a function that
has NO debug_informations.
Thanks.
 
First, let's consider we have debug-info / debug-frames generated.
 
When we start a step-over:
in runctrl.c:
             if (ext->step_cnt == 0) {
                 StackFrame * info = NULL;
                 ext->step_frame_fp = 0;
                 if (get_frame_info(ctx, STACK_TOP_FRAME, &info) < 0)
return -1;
==> We get the current "fp" for the current function.
 
Can someone confirm:
    "fp" means "frame address" aka CFA (canonical frame address)
     So the value retrieved for the ctx is the one described by the CFA
rule matching the instruction pointer.:
    cfa = 00(r3) (for example using dwarfdump -f)
 
Then the stepping of the line range starts. When we are out-of the
range, it means:
a) Either we have finish the step-over.
b) Either we are in a function called by the stepped line.
 
When out-of-range:
We get the "fp". If the computed fp is the same as previous, we are in
case a). Easy, done.
If the the computed "fp" is different, we are in case b) and we retrieve
the caller @ in step_bp_addr, resume the target.
 
Now my question comes when the stepped-line has a call to a function
that has no debug info.
We end-up at the very beginning of the function.
We go into the "stack crawl" code. Either the one from open-source or a
custom-one.
 
I'm currently writing a custom-one for a an architecture that works with
way:
Let's say the stack-pointer is r3.
jarl <foo>
 
When in <foo>
r3 has NOT changed.
r31 acts as LR and contains the return @.
 
The prolog will create a "frame pointer". But we are currently stopped
at the first instruction of the function.
So prolog has NOT been executed.
 
What should we return to (get_frame_info(ctx, STACK_TOP_FRAME, &info)
for info.fp ?
Can we return 0 as "fp" in the following case ?
     - we have no debug_information.
    -  we are stopped at the beginning of the function (so prolog has
NOT been executed).
 
Returning 0 as "fp" (aka cfa) will ensure that the following code in
runctrl.c will pass.
 
(step_cnt > 0)
                 if (get_frame_info(ctx, n, &info) < 0) return -1;
                 if (ext->step_frame_fp != info->fp) {
             .... retrieve caller, set step_bp_addr ....
             }
 
I've taken a look at what the compiler generates at the beginning of
function:
cfa = 0(r3).
 
So if I return r3, which was my first idea, that would be a problem
because ext->step_frame_fp == info->fp.
Or is cfa = 0(r3) a compiler bug ? I have this rule as the first
instruction of any function.
 
Conceptually, I have trouble understanding what CFA should be at the
first instruction of a function.
 
Thanks !
 
 
_______________________________________________
tcf-dev mailing list
tcf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/tcf-dev
 
 
 
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
 
 
_______________________________________________
tcf-dev mailing list
tcf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/tcf-dev

 



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.





_______________________________________________
tcf-dev mailing list
tcf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/tcf-dev

 



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



Back to the top