(this is a followup to <http://reviews.llvm.org/D9150>)
Hello Jason, I am trying to get stack unwinding to work from within deep bowels of glibc. Glibc contains a lot of functions (and "functions"), which do crazy stuff with the stack, frame and instruction pointers. Luckily, most (all?) of these functions contain CFI which generally does "the right thing". Unfortunately, these UnwindPlans are sometimes not picked by LLDB because they are too strange. For example take the "function" _L_lock_4746, which has the following dissassembly: $ disassemble -n _L_lock_4746 libc.so.6`_L_lock_4746: 0x7ffff70519bc <+0>: leaq (%rdx), %rdi 0x7ffff70519bf <+3>: subq $0x80, %rsp 0x7ffff70519c6 <+10>: callq 0x7ffff70df120 ; __lll_lock_wait_private 0x7ffff70519cb <+15>: addq $0x80, %rsp 0x7ffff70519d2 <+22>: jmp 0x7ffff70515fa ; _IO_new_file_underflow + 138 at fileops.c:592 And the following unwind plans: $ image show-unwind -n _L_lock_4746 UNWIND PLANS for libc.so.6`_L_lock_4746 (start addr 0x7ffff70519bc) Asynchronous (not restricted to call-sites) UnwindPlan is 'assembly insn profiling' Synchronous (restricted to call-sites) UnwindPlan is 'eh_frame CFI' Assembly language inspection UnwindPlan: This UnwindPlan originally sourced from assembly insn profiling 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 + 374044-0x000000000005b537) row[0]: 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] row[1]: 10: CFA=rsp+136 => rsp=CFA+0 rip=[CFA-8] row[2]: 22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] eh_frame UnwindPlan: 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 + 374044-0x000000000005b537) row[0]: 0: CFA=rsp-128 => rip=dwarf-expr row[1]: 3: CFA=rsp-128 => rip=dwarf-expr row[2]: 10: CFA=rsp +0 => rip=dwarf-expr row[3]: 14: CFA=rsp+128 => rip=dwarf-expr row[4]: 22: CFA=rsp-128 => rip=dwarf-expr Arch default UnwindPlan: This UnwindPlan originally sourced from x86_64 default unwind plan This UnwindPlan is sourced from the compiler: no. This UnwindPlan is valid at all instruction locations: no. row[0]: 0: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] Arch default at entry point UnwindPlan: This UnwindPlan originally sourced from x86_64 at-func-entry default This UnwindPlan is sourced from the compiler: no. This UnwindPlan is valid at all instruction locations: not specified. row[0]: 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] The "eh_frame CFI" plan is hand crafted to be valid at all locations within the function and if I force its use it actually produces the correct backtrace. However, the problem is that it is not selected by default. This happens because when we try to augment it, we fail because UnwindAssembly_x86::AugmentUnwindPlanFromCallSite expects the CFI plan to be in a very specific form. Then we end up falling back to "assembly insn profiling", which is completely bogus in this case. So, I would like to teach LLDB to use the provided CFI for unwinding in strange functions like these. However, I am unsure what is the cleanest solution. I would probably need to short-circuit the augementing logic to avoid trying to augment plans like these and just use the CFI plan as-is. Do yo have suggestions on how to do this? Perhaps set plan-valid-at-all-locations to true if we detect the author has gone through extra trouble to produce the CFI (use "rip set by dwarf-expr", or some more complex contidion as an indicator)? Then we could use the presence of this flag as an indicator that we can avoid augmentation? What do you think? cheers, pavel _______________________________________________ lldb-dev mailing list lldb-dev@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev