-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb] Parse DWARF CFI for discontinuous functions #137006
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,6 +122,13 @@ AddressRanges UnwindTable::GetAddressRanges(const Address &addr, | |
return {}; | ||
} | ||
|
||
static Address GetFunctionOrSymbolAddress(const Address &addr, | ||
const SymbolContext &sc) { | ||
if (Address result = sc.GetFunctionOrSymbolAddress(); result.IsValid()) | ||
return result; | ||
return addr; | ||
} | ||
|
||
FuncUnwindersSP | ||
UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr, | ||
const SymbolContext &sc) { | ||
|
@@ -131,25 +138,20 @@ UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr, | |
|
||
// There is an UnwindTable per object file, so we can safely use file handles | ||
addr_t file_addr = addr.GetFileAddress(); | ||
iterator end = m_unwinds.end(); | ||
iterator insert_pos = end; | ||
if (!m_unwinds.empty()) { | ||
insert_pos = m_unwinds.lower_bound(file_addr); | ||
iterator pos = insert_pos; | ||
if ((pos == m_unwinds.end()) || | ||
(pos != m_unwinds.begin() && | ||
pos->second->GetFunctionStartAddress() != addr)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realized that checking for the start address is not correct here as we're storing the FuncUnwinders multiple times here -- once per address range. |
||
--pos; | ||
|
||
iterator insert_pos = m_unwinds.upper_bound(file_addr); | ||
if (insert_pos != m_unwinds.begin()) { | ||
auto pos = std::prev(insert_pos); | ||
if (pos->second->ContainsAddress(addr)) | ||
return pos->second; | ||
} | ||
|
||
Address start_addr = GetFunctionOrSymbolAddress(addr, sc); | ||
AddressRanges ranges = GetAddressRanges(addr, sc); | ||
if (ranges.empty()) | ||
return nullptr; | ||
|
||
auto func_unwinder_sp = std::make_shared<FuncUnwinders>(*this, addr, ranges); | ||
auto func_unwinder_sp = | ||
std::make_shared<FuncUnwinders>(*this, start_addr, ranges); | ||
for (const AddressRange &range : ranges) | ||
m_unwinds.emplace_hint(insert_pos, range.GetBaseAddress().GetFileAddress(), | ||
func_unwinder_sp); | ||
|
@@ -164,11 +166,12 @@ FuncUnwindersSP UnwindTable::GetUncachedFuncUnwindersContainingAddress( | |
const Address &addr, const SymbolContext &sc) { | ||
Initialize(); | ||
|
||
Address start_addr = GetFunctionOrSymbolAddress(addr, sc); | ||
AddressRanges ranges = GetAddressRanges(addr, sc); | ||
if (ranges.empty()) | ||
return nullptr; | ||
|
||
return std::make_shared<FuncUnwinders>(*this, addr, std::move(ranges)); | ||
return std::make_shared<FuncUnwinders>(*this, start_addr, std::move(ranges)); | ||
} | ||
|
||
void UnwindTable::Dump(Stream &s) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -868,13 +868,11 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() { | |
|
||
// Even with -fomit-frame-pointer, we can try eh_frame to get back on | ||
// track. | ||
DWARFCallFrameInfo *eh_frame = | ||
pc_module_sp->GetUnwindTable().GetEHFrameInfo(); | ||
if (eh_frame) { | ||
auto unwind_plan_sp = | ||
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); | ||
if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) | ||
return unwind_plan_sp; | ||
if (DWARFCallFrameInfo *eh_frame = | ||
pc_module_sp->GetUnwindTable().GetEHFrameInfo()) { | ||
if (std::unique_ptr<UnwindPlan> plan_up = | ||
eh_frame->GetUnwindPlan(m_current_pc)) | ||
return plan_up; | ||
} | ||
|
||
ArmUnwindInfo *arm_exidx = | ||
|
@@ -1345,9 +1343,9 @@ RegisterContextUnwind::SavedLocationForRegister( | |
// value instead of the Return Address register. | ||
// If $pc is not available, fall back to the RA reg. | ||
UnwindPlan::Row::AbstractRegisterLocation scratch; | ||
if (m_frame_type == eTrapHandlerFrame && | ||
active_row->GetRegisterInfo | ||
(pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) { | ||
if (m_frame_type == eTrapHandlerFrame && active_row && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a splattering of defensive checks as it's easier to get a null active row now (some places around here are already checking it, but not all of them). |
||
active_row->GetRegisterInfo( | ||
pc_regnum.GetAsKind(unwindplan_registerkind), scratch)) { | ||
UnwindLogMsg("Providing pc register instead of rewriting to " | ||
"RA reg because this is a trap handler and there is " | ||
"a location for the saved pc register value."); | ||
|
@@ -1377,7 +1375,7 @@ RegisterContextUnwind::SavedLocationForRegister( | |
} | ||
} | ||
|
||
if (regnum.IsValid() && | ||
if (regnum.IsValid() && active_row && | ||
active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), | ||
unwindplan_regloc)) { | ||
have_unwindplan_regloc = true; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,23 +17,32 @@ | |
image show-unwind --cached true -n foo | ||
# CHECK: UNWIND PLANS for {{.*}}`foo | ||
# | ||
# CHECK: Assembly language inspection UnwindPlan: | ||
# CHECK-NEXT: This UnwindPlan originally sourced from assembly insn profiling | ||
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: no. | ||
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: yes. | ||
# CHECK: eh_frame UnwindPlan: | ||
# CHECK-NEXT: This UnwindPlan originally sourced from eh_frame CFI | ||
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. | ||
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no. | ||
# CHECK-NEXT: This UnwindPlan is for a trap handler function: no. | ||
# TODO: This address range isn't correct right now. We're just checking that | ||
# it's a different range from the one in the next query. | ||
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 6-0x0000000000000046) | ||
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 6-0x0000000000000010)[{{.*}}.text + 17-0x000000000000001c)[{{.*}}.text + 44-0x0000000000000037)[{{.*}}.text + 56-0x000000000000003d) | ||
# CHECK-NEXT: row[0]: 0: CFA=rsp +8 => rip=[CFA-8] | ||
# CHECK-NEXT: row[1]: 1: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[2]: 11: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[3]: 15: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[4]: 38: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[5]: 42: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[6]: 50: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-NEXT: row[7]: 54: CFA=rsp +8 => rbx=[CFA-16] rip=[CFA-8] | ||
# CHECK-EMPTY: | ||
|
||
image show-unwind --cached true -n bar | ||
# CHECK: UNWIND PLANS for {{.*}}`bar | ||
|
||
# CHECK: Assembly language inspection UnwindPlan: | ||
# CHECK-NEXT: This UnwindPlan originally sourced from assembly insn profiling | ||
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: no. | ||
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: yes. | ||
# CHECK: eh_frame UnwindPlan: | ||
# CHECK-NEXT: This UnwindPlan originally sourced from eh_frame CFI | ||
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. | ||
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no. | ||
# CHECK-NEXT: This UnwindPlan is for a trap handler function: no. | ||
# TODO: This address range isn't correct right now. We're just checking that | ||
# it's a different range from the one in the previous query. | ||
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 35-0x0000000000000033) | ||
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 28-0x000000000000002c) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. obviously not relevant to this PR but man There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it's quite a mess. I've been planning to look into that. |
||
# CHECK-NEXT: row[0]: 0: CFA=rsp +8 => rip=[CFA-8] | ||
# CHECK-NEXT: row[1]: 4: CFA=rsp+32 => rip=[CFA-8] | ||
# CHECK-NEXT: row[2]: 15: CFA=rsp +8 => rip=[CFA-8] | ||
# CHECK-EMPTY: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol at first I was like wait, does that actually work, but sure enough in C++17.