[llvm-bugs] [Bug 39752] New: [DebugInfo] Location list entries expressed in caller-saved registers are incompatible for unwinding with GDB

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Nov 22 04:57:55 PST 2018


https://bugs.llvm.org/show_bug.cgi?id=39752

            Bug ID: 39752
           Summary: [DebugInfo] Location list entries expressed in
                    caller-saved registers are incompatible for unwinding
                    with GDB
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: DebugInfo
          Assignee: unassignedbugs at nondot.org
          Reporter: david.stenberg at ericsson.com
                CC: jdevlieghere at apple.com, keith.walker at arm.com,
                    llvm-bugs at lists.llvm.org,
                    paul_robinson at playstation.sony.com

(This might be a known issue.)

Consider the following example:

    int global;

    __attribute__((noinline)) void fn3(int p3) {
      global = p3;
      /* Thrash parameter register. */
      __asm volatile ("movl $999, %%edi" : : : "%edi");
    }

    __attribute__((noinline)) int fn2(int p2) {
      global = p2;
      fn3(p2);
      return 0;
    }

    __attribute__((noinline)) int fn1(int p1) {
      global = p1;
      fn2(p1);
      return 0;
    }

    int main() {
      return fn1(111);
    }

compiled using:

    clang -target x86_64 -O3 -g test.c -o test.out

For fn2 we emit the following assembly:

    (gdb) disas fn2
    Dump of assembler code for function fn2:
       0x0000000000400500 <+0>:     push   %rbp
       0x0000000000400501 <+1>:     mov    %rsp,%rbp
       0x0000000000400504 <+4>:     mov    %edi,0x200b2a(%rip)        #
0x601034 <global>
       0x000000000040050a <+10>:    callq  0x4004e0 <fn3>
       0x000000000040050f <+15>:    xor    %eax,%eax
       0x0000000000400511 <+17>:    pop    %rbp
       0x0000000000400512 <+18>:    retq
    End of assembler dump.

and the following location list for p2:

    (gdb) info addr p2
    Symbol "p2" is multi-location:
      Range 0x400500-0x40050f: a variable in $rdi

As seen, we say that p2 is valid during the call. The same situation holds for
fn1 and p1.

When unwinding with GDB, which (at least for x86-64) relies on the DWARF
information to tell if a register is caller-saved, we will print invalid values
for the unwound p1 and p2 variables after we have thrashed $edi in fn3:

    (gdb) disas
    Dump of assembler code for function fn3:
       0x00000000004004e0 <+0>:     push   %rbp
       0x00000000004004e1 <+1>:     mov    %rsp,%rbp
       0x00000000004004e4 <+4>:     mov    %edi,0x200b4a(%rip)        #
0x601034 <global>
       0x00000000004004ea <+10>:    mov    $0x3e7,%edi
    => 0x00000000004004ef <+15>:    pop    %rbp
       0x00000000004004f0 <+16>:    retq
    End of assembler dump.
    (gdb) bt
    #0  fn3 (p3=<optimized out>) at test.c:11
    #1  0x000000000040050f in fn2 (p2=999) at test.c:15
    #2  0x000000000040052f in fn1 (p1=999) at test.c:21
    #3  0x000000000040054e in main () at test.c:26

This is not an issue with LLDB, as it is ABI-aware, and does not print out any
caller-saved registers in outer frames.

When unwinding, GDB and LLDB assume that the address is (return_address - 1)
when printing variables, etc. GCC seems to utilize this fact to get the
location expression correct for the caller-saved described variable, by ending
the location list entry right before that:

GCC 5.4.0 output:

    (gdb) disas fn2
    Dump of assembler code for function fn2:
       0x0000000000400500 <+0>:     mov    %edi,0x200b2e(%rip)        #
0x601034 <global>
       0x0000000000400506 <+6>:     callq  0x4004f0 <fn3>
       0x000000000040050b <+11>:    xor    %eax,%eax
       0x000000000040050d <+13>:    retq
    End of assembler dump.

    (gdb) info addr p2
    Symbol "p2" is multi-location:
      Range 0x400500-0x40050a: a variable in $rdi
      Range 0x40050a-0x40050e: a complex DWARF expression:
         0: DW_OP_GNU_entry_value
           2: DW_OP_reg5 [$rdi]
         3: DW_OP_stack_value

As seen, the first address after the call is 0x40050b, but the (exclusive)
ending address for p2 in the location list entry is 0x40050a.

Would it make sense to adapt LLVM to this behavior to be GDB compatible? Or is
it an acceptable incompatibility?

If we instead want to go the CFI route, maybe the compiler could emit
DW_CFA_undefined for caller-saved registers when they are clobbered?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181122/efe65f3d/attachment.html>


More information about the llvm-bugs mailing list