<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - [DebugInfo] Location list entries expressed in caller-saved registers are incompatible for unwinding with GDB"
href="https://bugs.llvm.org/show_bug.cgi?id=39752">39752</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[DebugInfo] Location list entries expressed in caller-saved registers are incompatible for unwinding with GDB
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>DebugInfo
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>david.stenberg@ericsson.com
</td>
</tr>
<tr>
<th>CC</th>
<td>jdevlieghere@apple.com, keith.walker@arm.com, llvm-bugs@lists.llvm.org, paul_robinson@playstation.sony.com
</td>
</tr></table>
<p>
<div>
<pre>(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?</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>