diff mbox series

powerpc/vdso: Fix incorrect CFI in gettimeofday.S

Message ID 20220502125010.1319370-1-mpe@ellerman.id.au (mailing list archive)
State Accepted
Headers show
Series powerpc/vdso: Fix incorrect CFI in gettimeofday.S | expand

Commit Message

Michael Ellerman May 2, 2022, 12:50 p.m. UTC
As reported by Alan, the CFI (Call Frame Information) in the VDSO time
routines is incorrect since commit ce7d8056e38b ("powerpc/vdso: Prepare
for switching VDSO to generic C implementation.").

In particular the changes to the frame address register (r1) are not
properly described, which prevents gdb from being able to generate a
backtrace from inside VDSO functions, eg:

  Breakpoint 1, 0x00007ffff7f804dc in __kernel_clock_gettime ()
  (gdb) bt
  #0  0x00007ffff7f804dc in __kernel_clock_gettime ()
  #1  0x00007ffff7d8872c in clock_gettime@@GLIBC_2.17 () from /lib64/libc.so.6
  #2  0x00007fffffffd960 in ?? ()
  #3  0x00007ffff7d8872c in clock_gettime@@GLIBC_2.17 () from /lib64/libc.so.6
  Backtrace stopped: frame did not save the PC

Alan helpfully describes some rules for correctly maintaining the CFI information:

  1) Every adjustment to the current frame address reg (ie. r1) must be
     described, and exactly at the instruction where r1 changes. Why?
     Because stack unwinding might want to access previous frames.
  2) If a function changes LR or any non-volatile register, the save
     location for those regs must be given. The cfi can be at any
     instruction after the saves up to the point that the reg is
     changed. (Exception: LR save should be described before a bl.)
  3) If asychronous unwind info is needed then restores of LR and
     non-volatile regs must also be described. The cfi can be at any
     instruction after the reg is restored up to the point where the
     save location is (potentially) trashed.

Fix the inability to backtrace by adding CFI directives describing the
changes to r1, ie. satisfying rule 1.

Also change the information for LR to point to the copy saved on the
stack, not the value in r0 that will be overwritten by the function
call.

Finally, add CFI directives describing the save/restore of r2.

With the fix gdb can correctly back trace and navigate up and down the stack:

  Breakpoint 1, 0x00007ffff7f804dc in __kernel_clock_gettime ()
  (gdb) bt
  #0  0x00007ffff7f804dc in __kernel_clock_gettime ()
  #1  0x00007ffff7d8872c in clock_gettime@@GLIBC_2.17 () from /lib64/libc.so.6
  #2  0x0000000100015b60 in gettime ()
  #3  0x000000010000c8bc in print_long_format ()
  #4  0x000000010000d180 in print_current_files ()
  #5  0x00000001000054ac in main ()
  (gdb) up
  #1  0x00007ffff7d8872c in clock_gettime@@GLIBC_2.17 () from /lib64/libc.so.6
  (gdb)
  #2  0x0000000100015b60 in gettime ()
  (gdb)
  #3  0x000000010000c8bc in print_long_format ()
  (gdb)
  #4  0x000000010000d180 in print_current_files ()
  (gdb)
  #5  0x00000001000054ac in main ()
  (gdb)
  Initial frame selected; you cannot go up.
  (gdb) down
  #4  0x000000010000d180 in print_current_files ()
  (gdb)
  #3  0x000000010000c8bc in print_long_format ()
  (gdb)
  #2  0x0000000100015b60 in gettime ()
  (gdb)
  #1  0x00007ffff7d8872c in clock_gettime@@GLIBC_2.17 () from /lib64/libc.so.6
  (gdb)
  #0  0x00007ffff7f804dc in __kernel_clock_gettime ()
  (gdb)

Fixes: ce7d8056e38b ("powerpc/vdso: Prepare for switching VDSO to generic C implementation.")
Cc: stable@vger.kernel.org # v5.11+
Reported-by: Alan Modra <amodra@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/kernel/vdso/gettimeofday.S | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Alan proposed a larger patch that changed to a single stack frame, but it needs changes to
take into account the red zone.

Anyway for stable I'd prefer to just fix the CFI, we can rework the stack frame in a
subsequent patch.

Comments

Segher Boessenkool May 2, 2022, 2:27 p.m. UTC | #1
Hi!

On Mon, May 02, 2022 at 10:50:10PM +1000, Michael Ellerman wrote:
> As reported by Alan, the CFI (Call Frame Information) in the VDSO time
> routines is incorrect since commit ce7d8056e38b ("powerpc/vdso: Prepare
> for switching VDSO to generic C implementation.").
> 
> In particular the changes to the frame address register (r1) are not
> properly described, which prevents gdb from being able to generate a
> backtrace from inside VDSO functions, eg:

Note that r1 is not the same as the CFA: r1 is the stack pointer, while
the CFA is a DWARF concept.  Often (but not always) they point to the
same thing, for us.  "When we change the stack pointer we should change
the DWARF CFA as well"?

> Alan helpfully describes some rules for correctly maintaining the CFI information:
> 
>   1) Every adjustment to the current frame address reg (ie. r1) must be
>      described, and exactly at the instruction where r1 changes. Why?
>      Because stack unwinding might want to access previous frames.
>   2) If a function changes LR or any non-volatile register, the save
>      location for those regs must be given. The cfi can be at any
>      instruction after the saves up to the point that the reg is
>      changed. (Exception: LR save should be described before a bl.)

That isn't an exception?  bl changes the current LR after all :-)

>   3) If asychronous unwind info is needed then restores of LR and
>      non-volatile regs must also be described. The cfi can be at any
>      instruction after the reg is restored up to the point where the
>      save location is (potentially) trashed.

The general rule is that your CFI must enable a debugger to reconstruct
the state at function entry (or it can explicitly say something has been
clobbered), using only data available at any point in the program we are
at now.  If something is available in multiple places (in some
registers, somewhere in memory) either place can be used; only one such
place is described in the CFI.  A store or even a restore does not have
to be described at the exact spot it happens (but that is by far the
most readable / least confusing way to do it).

> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
> @@ -22,12 +22,15 @@
>  .macro cvdso_call funct call_time=0
>    .cfi_startproc
>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>  	mflr		r0
> -  .cfi_register lr, r0
>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
> +  .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF

So you don't need to describe lr being saved in r0, because at all times
it is available elsewhere, namely in the lr reg still, or on the stack.
If lr could be clobbered before r0 is saved to the stack slot you would
still need to describe r0 containing the value of lr at function entry,
because that value then isn't available elsewhere.

The patch looks good to me :-)

Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>


Segher
Alan Modra May 2, 2022, 11:53 p.m. UTC | #2
On Mon, May 02, 2022 at 09:27:05AM -0500, Segher Boessenkool wrote:
> >   2) If a function changes LR or any non-volatile register, the save
> >      location for those regs must be given. The cfi can be at any
> >      instruction after the saves up to the point that the reg is
> >      changed. (Exception: LR save should be described before a bl.)
> 
> That isn't an exception?  bl changes the current LR after all :-)

The point is that in other cases the cfi can be as late as the
instruction that changes the reg.  For calls it must be at least one
instruction before the call.

Also, I'll note for the wider audience that delaying cfi is slightly
better than playing it safe as Michael has done in his patch in
describing the saves right at the save instruction.  Register save cfi
can usually be grouped together, resulting in fewer CFI_advance codes
in .eh_frame.

> Alan proposed a larger patch that changed to a single stack frame, but it needs changes to
> take into account the red zone.

Yes, now that you mention it, I see the obvious error in the patch I
wrote.  I did say it was untested!
Michael Ellerman May 4, 2022, 12:27 p.m. UTC | #3
Segher Boessenkool <segher@kernel.crashing.org> writes:
> Hi!
>
> On Mon, May 02, 2022 at 10:50:10PM +1000, Michael Ellerman wrote:
>> As reported by Alan, the CFI (Call Frame Information) in the VDSO time
>> routines is incorrect since commit ce7d8056e38b ("powerpc/vdso: Prepare
>> for switching VDSO to generic C implementation.").
>> 
>> In particular the changes to the frame address register (r1) are not
>> properly described, which prevents gdb from being able to generate a
>> backtrace from inside VDSO functions, eg:
>
> Note that r1 is not the same as the CFA: r1 is the stack pointer, while
> the CFA is a DWARF concept.  Often (but not always) they point to the
> same thing, for us.  "When we change the stack pointer we should change
> the DWARF CFA as well"?
 
Thanks, I reworded it a bit:

    DWARF has a concept called the CFA (Canonical Frame Address), which on
    powerpc is calculated as an offset from the stack pointer (r1). That
    means when the stack pointer is changed there must be a corresponding
    CFI directive to update the calculation of the CFA.

    The current code is missing those directives for the changes to r1,
    which prevents gdb from being able to generate a backtrace from inside
    VDSO functions, eg

>> Alan helpfully describes some rules for correctly maintaining the CFI information:
>> 
>>   1) Every adjustment to the current frame address reg (ie. r1) must be
>>      described, and exactly at the instruction where r1 changes. Why?
>>      Because stack unwinding might want to access previous frames.
>>   2) If a function changes LR or any non-volatile register, the save
>>      location for those regs must be given. The cfi can be at any
>>      instruction after the saves up to the point that the reg is
>>      changed. (Exception: LR save should be described before a bl.)
>
> That isn't an exception?  bl changes the current LR after all :-)
 
As Alan mentioned the exception is the the CFI has to appear before the
bl not after, I noted that in the change log.

>>   3) If asychronous unwind info is needed then restores of LR and
>>      non-volatile regs must also be described. The cfi can be at any
>>      instruction after the reg is restored up to the point where the
>>      save location is (potentially) trashed.
>
> The general rule is that your CFI must enable a debugger to reconstruct
> the state at function entry (or it can explicitly say something has been
> clobbered), using only data available at any point in the program we are
> at now.  If something is available in multiple places (in some
> registers, somewhere in memory) either place can be used; only one such
> place is described in the CFI.  A store or even a restore does not have
> to be described at the exact spot it happens (but that is by far the
> most readable / least confusing way to do it).

Ack.

I moved the LR restore down one line, which saves one CFA_advance_loc and
is not hard on the reader.

>> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
>> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
>> @@ -22,12 +22,15 @@
>>  .macro cvdso_call funct call_time=0
>>    .cfi_startproc
>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>  	mflr		r0
>> -  .cfi_register lr, r0
>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
>> +  .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF
>
> So you don't need to describe lr being saved in r0, because at all times
> it is available elsewhere, namely in the lr reg still, or on the stack.
> If lr could be clobbered before r0 is saved to the stack slot you would
> still need to describe r0 containing the value of lr at function entry,
> because that value then isn't available elsewhere.
>
> The patch looks good to me :-)
>
> Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>

Thanks.

cheers
Michael Ellerman May 4, 2022, 12:34 p.m. UTC | #4
Alan Modra <amodra@gmail.com> writes:
> On Mon, May 02, 2022 at 09:27:05AM -0500, Segher Boessenkool wrote:
>> >   2) If a function changes LR or any non-volatile register, the save
>> >      location for those regs must be given. The cfi can be at any
>> >      instruction after the saves up to the point that the reg is
>> >      changed. (Exception: LR save should be described before a bl.)
>> 
>> That isn't an exception?  bl changes the current LR after all :-)
>
> The point is that in other cases the cfi can be as late as the
> instruction that changes the reg.  For calls it must be at least one
> instruction before the call.

Got it.

> Also, I'll note for the wider audience that delaying cfi is slightly
> better than playing it safe as Michael has done in his patch in
> describing the saves right at the save instruction.  Register save cfi
> can usually be grouped together, resulting in fewer CFI_advance codes
> in .eh_frame.

I didn't want to go overboard on combining them, because it's harder to
read the source, especially with the #ifdefs we have for 64-bit.

I was able to save one CFA_advance_loc by moving the LR restore down one
line.

The .eh_frame didn't shrink, I guess because it's padded to some
alignment anyway.

>> Alan proposed a larger patch that changed to a single stack frame, but it needs changes to
>> take into account the red zone.
>
> Yes, now that you mention it, I see the obvious error in the patch I
> wrote.  I did say it was untested!

No worries, identifying the source of the bug as the missing CFI is the
key thing, it would have taken me a while to realise that.

cheers
Segher Boessenkool May 4, 2022, 2:08 p.m. UTC | #5
Hi!

On Wed, May 04, 2022 at 10:27:54PM +1000, Michael Ellerman wrote:
> Segher Boessenkool <segher@kernel.crashing.org> writes:
> > Note that r1 is not the same as the CFA: r1 is the stack pointer, while
> > the CFA is a DWARF concept.  Often (but not always) they point to the
> > same thing, for us.  "When we change the stack pointer we should change
> > the DWARF CFA as well"?
>  
> Thanks, I reworded it a bit:
> 
>     DWARF has a concept called the CFA (Canonical Frame Address), which on
>     powerpc is calculated as an offset from the stack pointer (r1). That
>     means when the stack pointer is changed there must be a corresponding
>     CFI directive to update the calculation of the CFA.

The CFA only uses r1 if it does not have a separate frame pointer, in
which case that is used.  "... is usually calculated ..." maybe?  A bit
of handwaving is better than giving the impression you are stating
something exact, if you don't.

> >>   2) If a function changes LR or any non-volatile register, the save
> >>      location for those regs must be given. The cfi can be at any
> >>      instruction after the saves up to the point that the reg is
> >>      changed. (Exception: LR save should be described before a bl.)
> >
> > That isn't an exception?  bl changes the current LR after all :-)
>  
> As Alan mentioned the exception is the the CFI has to appear before the
> bl not after, I noted that in the change log.

You have a bit of freedom where you place your CFI statements, but you
cannot place them too late (or too early).  This is true for all CFI
statements.  I suppose the final consequence of that can be a bit
surprising here :-)


Segher
Michael Ellerman May 8, 2022, 11:11 a.m. UTC | #6
On Mon, 2 May 2022 22:50:10 +1000, Michael Ellerman wrote:
> As reported by Alan, the CFI (Call Frame Information) in the VDSO time
> routines is incorrect since commit ce7d8056e38b ("powerpc/vdso: Prepare
> for switching VDSO to generic C implementation.").
> 
> In particular the changes to the frame address register (r1) are not
> properly described, which prevents gdb from being able to generate a
> backtrace from inside VDSO functions, eg:
> 
> [...]

Applied to powerpc/fixes.

[1/1] powerpc/vdso: Fix incorrect CFI in gettimeofday.S
      https://git.kernel.org/powerpc/c/6d65028eb67dbb7627651adfc460d64196d38bd8

cheers
Naveen N. Rao May 17, 2022, 7:33 a.m. UTC | #7
Michael Ellerman wrote:
> 
> diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
> index eb9c81e1c218..0aee255e9cbb 100644
> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
> @@ -22,12 +22,15 @@
>  .macro cvdso_call funct call_time=0
>    .cfi_startproc
>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>  	mflr		r0
> -  .cfi_register lr, r0
>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)

<snip>

> @@ -46,6 +50,7 @@
>  	mtlr		r0
>    .cfi_restore lr
>  	addi		r1, r1, 2 * PPC_MIN_STKFRM
> +  .cfi_def_cfa_offset 0

Should this be .cfi_adjust_cfa_offset, given that we used that at the 
start of the function?


- Naveen
Michael Ellerman May 17, 2022, 12:32 p.m. UTC | #8
"Naveen N. Rao" <naveen.n.rao@linux.ibm.com> writes:
> Michael Ellerman wrote:
>>
>> diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
>> index eb9c81e1c218..0aee255e9cbb 100644
>> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
>> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
>> @@ -22,12 +22,15 @@
>>  .macro cvdso_call funct call_time=0
>>    .cfi_startproc
>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>  	mflr		r0
>> -  .cfi_register lr, r0
>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
>
> <snip>
>
>> @@ -46,6 +50,7 @@
>>  	mtlr		r0
>>    .cfi_restore lr
>>  	addi		r1, r1, 2 * PPC_MIN_STKFRM
>> +  .cfi_def_cfa_offset 0
>
> Should this be .cfi_adjust_cfa_offset, given that we used that at the
> start of the function?
 
AIUI "adjust x" is offset += x, whereas "def x" is offset = x.

So we could use adjust here, but we'd need to adjust by -(2 * PPC_MIN_STKFRM).

It seemed clearer to just set the offset back to 0, which is what it is
at the start of the function.

But I'm not a CFI expert at all, so I'll defer to anyone else who has an
opinion :)

cheers
Naveen N. Rao May 18, 2022, 9:38 a.m. UTC | #9
Michael Ellerman wrote:
> "Naveen N. Rao" <naveen.n.rao@linux.ibm.com> writes:
>> Michael Ellerman wrote:
>>>
>>> diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
>>> index eb9c81e1c218..0aee255e9cbb 100644
>>> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
>>> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
>>> @@ -22,12 +22,15 @@
>>>  .macro cvdso_call funct call_time=0
>>>    .cfi_startproc
>>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>>  	mflr		r0
>>> -  .cfi_register lr, r0
>>>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>>> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>>>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
>>
>> <snip>
>>
>>> @@ -46,6 +50,7 @@
>>>  	mtlr		r0
>>>    .cfi_restore lr
>>>  	addi		r1, r1, 2 * PPC_MIN_STKFRM
>>> +  .cfi_def_cfa_offset 0
>>
>> Should this be .cfi_adjust_cfa_offset, given that we used that at the
>> start of the function?
>  
> AIUI "adjust x" is offset += x, whereas "def x" is offset = x.
> 
> So we could use adjust here, but we'd need to adjust by -(2 * PPC_MIN_STKFRM).
> 
> It seemed clearer to just set the offset back to 0, which is what it is
> at the start of the function.

I read the first .cfi_adjust_cfa_offset directive (rather than the 
.cfi_def_cfa_offset directive) in this macro to be intentionally 
retaining the offset to what it was before the VDSO. If that is 
desirable, then setting it to 0 here will change it, I _think_.

> 
> But I'm not a CFI expert at all, so I'll defer to anyone else who has an
> opinion :)

Oh, the above is just my hypothesis. Would be good to get confirmation.


- Naveen
Alan Modra May 19, 2022, 1:30 a.m. UTC | #10
On Tue, May 17, 2022 at 10:32:09PM +1000, Michael Ellerman wrote:
> "Naveen N. Rao" <naveen.n.rao@linux.ibm.com> writes:
> > Michael Ellerman wrote:
> >>
> >> diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
> >> index eb9c81e1c218..0aee255e9cbb 100644
> >> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
> >> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
> >> @@ -22,12 +22,15 @@
> >>  .macro cvdso_call funct call_time=0
> >>    .cfi_startproc
> >>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> >> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
> >>  	mflr		r0
> >> -  .cfi_register lr, r0
> >>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
> >> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
> >>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
> >
> > <snip>
> >
> >> @@ -46,6 +50,7 @@
> >>  	mtlr		r0
> >>    .cfi_restore lr
> >>  	addi		r1, r1, 2 * PPC_MIN_STKFRM
> >> +  .cfi_def_cfa_offset 0
> >
> > Should this be .cfi_adjust_cfa_offset, given that we used that at the
> > start of the function?
>  
> AIUI "adjust x" is offset += x, whereas "def x" is offset = x.

Yes.

> So we could use adjust here, but we'd need to adjust by -(2 * PPC_MIN_STKFRM).

Yes.

> It seemed clearer to just set the offset back to 0, which is what it is
> at the start of the function.

Yes.  In detail, both .cfi_def_cfa_offset and .cfi_adjust_cfa_offset
are interpreteted by the assembler into DW_CFA_def_cfa_offset byte
codes, so you should get the same .eh_frame contents if using Naveen's
suggestion.  It boils down to style really, and the most common style
is to use ".cfi_def_cfa_offset 0" here.
Naveen N. Rao May 20, 2022, 12:14 p.m. UTC | #11
Alan Modra wrote:
> On Tue, May 17, 2022 at 10:32:09PM +1000, Michael Ellerman wrote:
>> "Naveen N. Rao" <naveen.n.rao@linux.ibm.com> writes:
>> > Michael Ellerman wrote:
>> >>
>> >> diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
>> >> index eb9c81e1c218..0aee255e9cbb 100644
>> >> --- a/arch/powerpc/kernel/vdso/gettimeofday.S
>> >> +++ b/arch/powerpc/kernel/vdso/gettimeofday.S
>> >> @@ -22,12 +22,15 @@
>> >>  .macro cvdso_call funct call_time=0
>> >>    .cfi_startproc
>> >>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> >> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>> >>  	mflr		r0
>> >> -  .cfi_register lr, r0
>> >>  	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
>> >> +  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
>> >>  	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
>> >
>> > <snip>
>> >
>> >> @@ -46,6 +50,7 @@
>> >>  	mtlr		r0
>> >>    .cfi_restore lr
>> >>  	addi		r1, r1, 2 * PPC_MIN_STKFRM
>> >> +  .cfi_def_cfa_offset 0
>> >
>> > Should this be .cfi_adjust_cfa_offset, given that we used that at the
>> > start of the function?
>>  
>> AIUI "adjust x" is offset += x, whereas "def x" is offset = x.
> 
> Yes.
> 
>> So we could use adjust here, but we'd need to adjust by -(2 * PPC_MIN_STKFRM).
> 
> Yes.
> 
>> It seemed clearer to just set the offset back to 0, which is what it is
>> at the start of the function.
> 
> Yes.  In detail, both .cfi_def_cfa_offset and .cfi_adjust_cfa_offset
> are interpreteted by the assembler into DW_CFA_def_cfa_offset byte
> codes, so you should get the same .eh_frame contents if using Naveen's
> suggestion.  It boils down to style really, and the most common style
> is to use ".cfi_def_cfa_offset 0" here.

Thank you, that clarifies things.


- Naveen
diff mbox series

Patch

diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
index eb9c81e1c218..0aee255e9cbb 100644
--- a/arch/powerpc/kernel/vdso/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso/gettimeofday.S
@@ -22,12 +22,15 @@ 
 .macro cvdso_call funct call_time=0
   .cfi_startproc
 	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
+  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
 	mflr		r0
-  .cfi_register lr, r0
 	PPC_STLU	r1, -PPC_MIN_STKFRM(r1)
+  .cfi_adjust_cfa_offset PPC_MIN_STKFRM
 	PPC_STL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
+  .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF
 #ifdef __powerpc64__
 	PPC_STL		r2, PPC_MIN_STKFRM + STK_GOT(r1)
+  .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
 #endif
 	get_datapage	r5
 	.ifeq	\call_time
@@ -39,6 +42,7 @@ 
 	PPC_LL		r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
 #ifdef __powerpc64__
 	PPC_LL		r2, PPC_MIN_STKFRM + STK_GOT(r1)
+  .cfi_restore r2
 #endif
 	.ifeq	\call_time
 	cmpwi		r3, 0
@@ -46,6 +50,7 @@ 
 	mtlr		r0
   .cfi_restore lr
 	addi		r1, r1, 2 * PPC_MIN_STKFRM
+  .cfi_def_cfa_offset 0
 	crclr		so
 	.ifeq	\call_time
 	beqlr+