Skip to content

Commit d742903

Browse files
authored
Delegate to ABI plugin to check if call frame addresses are valid (#161398)
Specially when dealing with different address spaces, CFAs could start from addresses like 0. For instance, Nvidia GPUs have instructions to read from local memory that use 0-based offsets and stack memory can be referenced by these offsets rather than global addresses. Note that ABIs could already specify what they consider to be valid CFA values but this was never used in these parts of the unwinder code. For most ABIs, this makes the validation more strict, as they already used to discard 0s and then checked for alignment which would discard 1s. There a few exceptions where 0s were possible and this makes it less strict, like the RISCV and ARC ABIs. @jasonmolenda Would you be the appropriate reviewer for this? Also cc. @clayborg @walter-erquinigo
1 parent 34c0a5f commit d742903

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) {
5252
return ConstString();
5353
}
5454

55+
static bool CallFrameAddressIsValid(ABISP abi_sp, lldb::addr_t cfa) {
56+
if (cfa == LLDB_INVALID_ADDRESS)
57+
return false;
58+
if (abi_sp)
59+
return abi_sp->CallFrameAddressIsValid(cfa);
60+
return cfa != 0 && cfa != 1;
61+
}
62+
5563
RegisterContextUnwind::RegisterContextUnwind(Thread &thread,
5664
const SharedPtr &next_frame,
5765
SymbolContext &sym_ctx,
@@ -448,7 +456,7 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
448456
ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);
449457

450458
// A couple of sanity checks..
451-
if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) {
459+
if (!CallFrameAddressIsValid(abi_sp, m_cfa)) {
452460
UnwindLogMsg("could not find a valid cfa address");
453461
m_frame_type = eNotAValidFrame;
454462
return;
@@ -1847,9 +1855,11 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
18471855
active_row->GetCFAValue().GetValueType() !=
18481856
UnwindPlan::Row::FAValue::unspecified) {
18491857
addr_t new_cfa;
1858+
ProcessSP process_sp = m_thread.GetProcess();
1859+
ABISP abi_sp = process_sp ? process_sp->GetABI() : nullptr;
18501860
if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
1851-
active_row->GetCFAValue(), new_cfa) ||
1852-
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
1861+
active_row->GetCFAValue(), new_cfa) ||
1862+
!CallFrameAddressIsValid(abi_sp, new_cfa)) {
18531863
UnwindLogMsg("failed to get cfa with fallback unwindplan");
18541864
m_fallback_unwind_plan_sp.reset();
18551865
m_full_unwind_plan_sp = original_full_unwind_plan_sp;
@@ -1870,10 +1880,9 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
18701880
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
18711881
reg_value)) {
18721882
new_caller_pc_value = reg_value.GetAsUInt64();
1873-
if (ProcessSP process_sp = m_thread.GetProcess()) {
1874-
if (ABISP abi_sp = process_sp->GetABI())
1875-
new_caller_pc_value = abi_sp->FixCodeAddress(new_caller_pc_value);
1876-
}
1883+
if (process_sp)
1884+
new_caller_pc_value =
1885+
process_sp->FixCodeAddress(new_caller_pc_value);
18771886
}
18781887
}
18791888
}
@@ -1932,9 +1941,11 @@ bool RegisterContextUnwind::ForceSwitchToFallbackUnwindPlan() {
19321941
active_row->GetCFAValue().GetValueType() !=
19331942
UnwindPlan::Row::FAValue::unspecified) {
19341943
addr_t new_cfa;
1944+
ProcessSP process_sp = m_thread.GetProcess();
1945+
ABISP abi_sp = process_sp ? process_sp->GetABI() : nullptr;
19351946
if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
1936-
active_row->GetCFAValue(), new_cfa) ||
1937-
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
1947+
active_row->GetCFAValue(), new_cfa) ||
1948+
!CallFrameAddressIsValid(abi_sp, new_cfa)) {
19381949
UnwindLogMsg("failed to get cfa with fallback unwindplan");
19391950
m_fallback_unwind_plan_sp.reset();
19401951
return false;
@@ -2055,8 +2066,7 @@ bool RegisterContextUnwind::ReadFrameAddress(
20552066
RegisterNumber cfa_reg(m_thread, row_register_kind,
20562067
fa.GetRegisterNumber());
20572068
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
2058-
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
2059-
cfa_reg_contents == 1) {
2069+
if (!CallFrameAddressIsValid(abi_sp, cfa_reg_contents)) {
20602070
UnwindLogMsg(
20612071
"Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
20622072
cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),

0 commit comments

Comments
 (0)