Skip to content

Commit 447cc61

Browse files
committed
Clear non-addressable bits from pc/fp/sp in unwinds
Some Darwin corefiles can have the pc/fp/sp/lr in the live register context signed with pointer authentication; this patch changes RegisterContextUnwind to strip those bits off of those values as we try to walk the stack. Differential Revision: https://reviews.llvm.org/D152861 rdar://109185291 (cherry picked from commit 0ce7037)
1 parent 8031915 commit 447cc61

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
137137
// (which would be a no-op in frame 0 where we get it from the register set,
138138
// but still a good idea to make the call here for other ABIs that may
139139
// exist.)
140-
ABI *abi = process->GetABI().get();
141-
if (abi)
142-
current_pc = abi->FixCodeAddress(current_pc);
140+
if (ABISP abi_sp = process->GetABI())
141+
current_pc = abi_sp->FixCodeAddress(current_pc);
143142

144143
UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
145144
m_thread, this, m_behaves_like_zeroth_frame);
@@ -355,17 +354,23 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
355354

356355
// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
357356
// this will strip bit zero in case we read a PC from memory or from the LR.
358-
ABI *abi = process->GetABI().get();
359-
if (abi)
360-
pc = abi->FixCodeAddress(pc);
357+
ABISP abi_sp = process->GetABI();
358+
if (abi_sp)
359+
pc = abi_sp->FixCodeAddress(pc);
361360

362361
if (log) {
363362
UnwindLogMsg("pc = 0x%" PRIx64, pc);
364363
addr_t reg_val;
365-
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
364+
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) {
365+
if (abi_sp)
366+
reg_val = abi_sp->FixDataAddress(reg_val);
366367
UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
367-
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
368+
}
369+
if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) {
370+
if (abi_sp)
371+
reg_val = abi_sp->FixDataAddress(reg_val);
368372
UnwindLogMsg("sp = 0x%" PRIx64, reg_val);
373+
}
369374
}
370375

371376
// A pc of 0x0 means it's the end of the stack crawl unless we're above a trap
@@ -424,11 +429,11 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
424429
}
425430
}
426431

427-
if (abi) {
432+
if (abi_sp) {
428433
m_fast_unwind_plan_sp.reset();
429434
m_full_unwind_plan_sp =
430435
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
431-
abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
436+
abi_sp->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
432437
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
433438
{
434439
m_frame_type = eNormalFrame;
@@ -1751,8 +1756,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
17511756
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
17521757
old_caller_pc_value = reg_value.GetAsUInt64();
17531758
if (ProcessSP process_sp = m_thread.GetProcess()) {
1754-
if (ABISP abi = process_sp->GetABI())
1755-
old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value);
1759+
if (ABISP abi_sp = process_sp->GetABI())
1760+
old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
17561761
}
17571762
}
17581763
}
@@ -1811,8 +1816,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
18111816
reg_value)) {
18121817
new_caller_pc_value = reg_value.GetAsUInt64();
18131818
if (ProcessSP process_sp = m_thread.GetProcess()) {
1814-
if (ABISP abi = process_sp->GetABI())
1815-
new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value);
1819+
if (ABISP abi_sp = process_sp->GetABI())
1820+
new_caller_pc_value = abi_sp->FixCodeAddress(new_caller_pc_value);
18161821
}
18171822
}
18181823
}
@@ -1953,6 +1958,7 @@ bool RegisterContextUnwind::ReadFrameAddress(
19531958

19541959
address = LLDB_INVALID_ADDRESS;
19551960
addr_t cfa_reg_contents;
1961+
ABISP abi_sp = m_thread.GetProcess()->GetABI();
19561962

19571963
switch (fa.GetValueType()) {
19581964
case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
@@ -1963,11 +1969,13 @@ bool RegisterContextUnwind::ReadFrameAddress(
19631969
GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
19641970
RegisterValue reg_value;
19651971
if (reg_info) {
1972+
if (abi_sp)
1973+
cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
19661974
Status error = ReadRegisterValueFromMemory(
19671975
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
19681976
if (error.Success()) {
19691977
address = reg_value.GetAsUInt64();
1970-
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
1978+
if (abi_sp)
19711979
address = abi_sp->FixCodeAddress(address);
19721980
UnwindLogMsg(
19731981
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
@@ -1989,6 +1997,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
19891997
RegisterNumber cfa_reg(m_thread, row_register_kind,
19901998
fa.GetRegisterNumber());
19911999
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
2000+
if (abi_sp)
2001+
cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
19922002
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
19932003
cfa_reg_contents == 1) {
19942004
UnwindLogMsg(
@@ -2076,6 +2086,8 @@ lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
20762086
return LLDB_INVALID_ADDRESS;
20772087
if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
20782088
return LLDB_INVALID_ADDRESS;
2089+
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
2090+
hint = abi_sp->FixCodeAddress(hint);
20792091

20802092
hint += plan_offset;
20812093

@@ -2133,28 +2145,38 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
21332145
return false;
21342146
}
21352147

2148+
uint32_t generic_regnum = LLDB_INVALID_REGNUM;
2149+
if (register_kind == eRegisterKindGeneric)
2150+
generic_regnum = regnum;
2151+
else
2152+
m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
2153+
register_kind, regnum, eRegisterKindGeneric, generic_regnum);
2154+
ABISP abi_sp = m_thread.GetProcess()->GetABI();
2155+
21362156
RegisterValue reg_value;
21372157
// if this is frame 0 (currently executing frame), get the requested reg
21382158
// contents from the actual thread registers
21392159
if (IsFrameZero()) {
21402160
if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
21412161
value = reg_value.GetAsUInt64();
2162+
if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
2163+
if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
2164+
generic_regnum == LLDB_REGNUM_GENERIC_RA)
2165+
value = abi_sp->FixCodeAddress(value);
2166+
if (generic_regnum == LLDB_REGNUM_GENERIC_SP ||
2167+
generic_regnum == LLDB_REGNUM_GENERIC_FP)
2168+
value = abi_sp->FixDataAddress(value);
2169+
}
21422170
return true;
21432171
}
21442172
return false;
21452173
}
21462174

21472175
bool pc_register = false;
2148-
uint32_t generic_regnum;
2149-
if (register_kind == eRegisterKindGeneric &&
2150-
(regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) {
2176+
if (generic_regnum != LLDB_INVALID_REGNUM &&
2177+
(generic_regnum == LLDB_REGNUM_GENERIC_PC ||
2178+
generic_regnum == LLDB_REGNUM_GENERIC_RA))
21512179
pc_register = true;
2152-
} else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
2153-
register_kind, regnum, eRegisterKindGeneric, generic_regnum) &&
2154-
(generic_regnum == LLDB_REGNUM_GENERIC_PC ||
2155-
generic_regnum == LLDB_REGNUM_GENERIC_RA)) {
2156-
pc_register = true;
2157-
}
21582180

21592181
lldb_private::UnwindLLDB::RegisterLocation regloc;
21602182
if (!m_parent_unwind.SearchForSavedLocationForRegister(
@@ -2164,9 +2186,8 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
21642186
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
21652187
value = reg_value.GetAsUInt64();
21662188
if (pc_register) {
2167-
if (ProcessSP process_sp = m_thread.GetProcess()) {
2168-
if (ABISP abi = process_sp->GetABI())
2169-
value = abi->FixCodeAddress(value);
2189+
if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
2190+
value = abi_sp->FixCodeAddress(value);
21702191
}
21712192
}
21722193
return true;
@@ -2215,10 +2236,8 @@ bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
22152236
if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
22162237
addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
22172238
if (reg_value != LLDB_INVALID_ADDRESS) {
2218-
if(ProcessSP process_sp = m_thread.GetProcess()) {
2219-
if (ABISP abi = process_sp->GetABI())
2220-
value = abi->FixCodeAddress(reg_value);
2221-
}
2239+
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
2240+
value = abi_sp->FixCodeAddress(reg_value);
22222241
}
22232242
}
22242243
}
@@ -2300,9 +2319,8 @@ bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
23002319
ProcessSP process_sp (m_thread.GetProcess());
23012320
if (process_sp)
23022321
{
2303-
ABI *abi = process_sp->GetABI().get();
2304-
if (abi)
2305-
start_pc = abi->FixCodeAddress(start_pc);
2322+
if (ABISP abi_sp = process_sp->GetABI())
2323+
start_pc = abi_sp->FixCodeAddress(start_pc);
23062324
}
23072325
}
23082326
return read_successfully;
@@ -2330,13 +2348,8 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) {
23302348
// through a NULL pointer -- we want to be able to unwind past that frame
23312349
// to help find the bug.
23322350

2333-
ProcessSP process_sp (m_thread.GetProcess());
2334-
if (process_sp)
2335-
{
2336-
ABI *abi = process_sp->GetABI().get();
2337-
if (abi)
2338-
pc = abi->FixCodeAddress(pc);
2339-
}
2351+
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
2352+
pc = abi_sp->FixCodeAddress(pc);
23402353

23412354
return !(m_all_registers_available == false &&
23422355
above_trap_handler == false && (pc == 0 || pc == 1));

0 commit comments

Comments
 (0)