[lldb-dev] [Bug 43561] New: Unwind augmentation on x86 is off by one instruction

via lldb-dev lldb-dev at lists.llvm.org
Fri Oct 4 03:56:11 PDT 2019


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

            Bug ID: 43561
           Summary: Unwind augmentation on x86 is off by one instruction
           Product: lldb
           Version: 9.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: All Bugs
          Assignee: lldb-dev at lists.llvm.org
          Reporter: jarin at google.com
                CC: jdevlieghere at apple.com, llvm-bugs at lists.llvm.org

I believe the x86 augmentation of eh_frame info from assembly is broken: it
computes the unwinding info for offset x from instruction at offset x, but
instead it should be computed from the previous instruction (here is the loop
in question:
https://github.com/llvm/llvm-project/blob/c118a03e6945805edc88732a33ff51cc4d96db09/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp#L1381).
Looking back at the history of the file, this was likely introduced by the very
first revision of the file
(https://github.com/llvm/llvm-project/commit/1c9858b298d79ce82c45a2954096718b39550109#diff-375a2be066db6f34bb9a71442c9b71fcL913);
the original version handled this properly by copying the previous instruction
out before advancing the instruction pointer.

It is quite nicely visible in the glibc’s raise function, which has the
following unwinding plan (according to “image show-unwind -a $pc”):

This UnwindPlan originally sourced from eh_frame CFI plus augmentation from
assembly parsing
This UnwindPlan is sourced from the compiler: no.
This UnwindPlan is valid at all instruction locations: yes.
Address range of this UnwindPlan: [libc.so.6..text + 79344-0x00000000000136de)
row[0]:    0: CFA=rsp +8 => rip=[CFA-8]
row[1]:    1: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
row[2]:   28: CFA=rsp+152 => rbx=[CFA-16] rip=[CFA-8]  << Comes from
augmentation
row[3]:   35: CFA=rsp+152 => rbx=[CFA-16] rip=[CFA-8]
row[4]:  207: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]  << Comes from
augmentation
row[5]:  214: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
row[6]:  217: CFA=rsp +8 => rbx=[CFA-16] rip=[CFA-8]
row[7]:  218: CFA=rsp +8 => rbx=[CFA-16] rip=[CFA-8]
row[8]:  224: CFA=rsp+152 => rbx=[CFA-16] rip=[CFA-8]

This is already suspicious because of the duplicate lines. Disassembling
confirms the suspicion: offsets 28 and 207 should be still on their original
unwinding rows.

0x7ffff5e94f44:  movl   $0x8, %r10d
0x7ffff5e94f4a:  xorl   %edi, %edi
0x7ffff5e94f4c:  subq   $0x88, %rsp       ;; offset 28
0x7ffff5e94f53:  leaq   -0x78(%rsp), %r9  ;; offset 35
0x7ffff5e94f58:  movq   %rax, 0x8(%rsp)
...
0x7ffff5e94ff8:  movl   $0xe, %eax
0x7ffff5e94ffd:  syscall
0x7ffff5e94fff:  addq   $0x88, %rsp       ;; offset 207
0x7ffff5e95006:  movl   %r8d, %eax        ;; offset 214

It is worth noting the the eh_frame unwinding info is actually correct:

This UnwindPlan originally sourced from eh_frame CFI
This UnwindPlan is sourced from the compiler: yes.
This UnwindPlan is valid at all instruction locations: no.
Address range of this UnwindPlan: [libc.so.6..text + 79344-0x00000000000136de)
row[0]:    0: CFA=rsp +8 => rip=[CFA-8]
row[1]:    1: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
row[2]:   35: CFA=rsp+152 => rbx=[CFA-16] rip=[CFA-8]
row[3]:  214: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
row[4]:  218: CFA=rsp +8 => rbx=[CFA-16] rip=[CFA-8]
row[5]:  224: CFA=rsp+152 => rbx=[CFA-16] rip=[CFA-8]


Here is my program and the lldb session that shows the missing stack entry for
the SHOULD_BE_ON_STACK function.

--- main.cpp ---
#include <stdlib.h>

void SHOULD_BE_ON_STACK() {
        abort();
}

int main(int argc, char** argv) {
        SHOULD_BE_ON_STACK();
}

$ lldb MissingStack
(lldb) target create "MissingStack"
Current executable set to 'MissingStack' (x86_64).
(lldb) r
Process 8262 launched: '/srv/game/assets/MissingStack' (x86_64)
Process 8262 stopped
* thread #1, name = 'MissingStack', stop reason = signal SIGABRT
    frame #0: 0x00007ffff5e94fff libc.so.6`__GI_raise(sig=6) at raise.c:51
(lldb) bt
* thread #1, name = 'MissingStack', stop reason = signal SIGABRT
  * frame #0: 0x00007ffff5e94fff libc.so.6`__GI_raise(sig=6) at raise.c:51
    frame #1: 0xfffffffe7fffffff
    frame #2: 0x0000000000201174 MissingStack`main(argc=1,
argv=0x00007fffffffe5e8) at main.cpp:8
    frame #3: 0x00007ffff5e822e1
libc.so.6`__libc_start_main(main=(MissingStack`main at main.cpp:7), argc=1,
argv=0x00007fffffffe5e8, init=<unavailable>, fini=<unavailable>,
rtld_fini=<unavailable>, stack_end=0x00007fffffffe5d8) at libc-start.c:291
    frame #4: 0x000000000020102a MissingStack`_start + 42

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20191004/2eacb889/attachment.html>


More information about the lldb-dev mailing list