• Michael Ellerman's avatar
    powerpc/vdso: Fix incorrect CFI in gettimeofday.S · 6d65028e
    Michael Ellerman authored
    As reported by Alan, the CFI (Call Frame Information) in the VDSO time
    routines is incorrect since commit ce7d8056 ("powerpc/vdso: Prepare
    for switching VDSO to generic C implementation.").
    
    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:
    
      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. not after)
    
      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: ce7d8056 ("powerpc/vdso: Prepare for switching VDSO to generic C implementation.")
    Cc: stable@vger.kernel.org # v5.11+
    Reported-by: default avatarAlan Modra <amodra@gmail.com>
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    Reviewed-by: default avatarSegher Boessenkool <segher@kernel.crashing.org>
    Link: https://lore.kernel.org/r/20220502125010.1319370-1-mpe@ellerman.id.au
    6d65028e
gettimeofday.S 3.01 KB