summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2016-05-20 00:16:14 +0000
committerJason Molenda <jmolenda@apple.com>2016-05-20 00:16:14 +0000
commit1ebb2c92f2635a7d4182e3b3cb47abcaf44cc572 (patch)
treed3b5e63e75de574affbe2ae13f94fd72d86d2553
parentdcccd929d103e124069931f9aaed258bacc8e180 (diff)
downloadbcm5719-llvm-1ebb2c92f2635a7d4182e3b3cb47abcaf44cc572.tar.gz
bcm5719-llvm-1ebb2c92f2635a7d4182e3b3cb47abcaf44cc572.zip
Some changes to prevent searching down the stack for saved register
values for the pc or return address register. On ios with arm64 and a binary that has multiple functions without individual symbol boundaries, we end up with an assembly profile unwind plan that says lr=<same> - that is, the link register contents are unmodified from the caller's value. This gets the unwinder in a loop. When we're off the 0th frame, we never want to look to a caller for a pc or return-address register value. Add checks to ReadGPRValue and ReadRegister to prevent both the pc and ra register values from recursing. If this causes problems with backtraces on android, let me know or back it out and I'll look into it -- but I think these are straightforward and don't expect problems. <rdar://problem/24610365> llvm-svn: 270162
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp39
1 files changed, 29 insertions, 10 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 64b12009dfa..8bbaeb8e9a5 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -1462,13 +1462,24 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
if (unwindplan_regloc.IsSame())
{
- regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
- regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB);
- m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
- UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)",
- regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
- regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
- return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ if (IsFrameZero() == false
+ && (regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC
+ || regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA))
+ {
+ UnwindLogMsg ("register %s (%d) is marked as 'IsSame' - it is a pc or return address reg on a non-zero frame -- treat as if we have no information",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+ }
+ else
+ {
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+ regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
}
if (unwindplan_regloc.IsCFAPlusOffset())
@@ -1889,12 +1900,13 @@ RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t re
bool pc_register = false;
uint32_t generic_regnum;
- if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC)
+ if (register_kind == eRegisterKindGeneric
+ && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA))
{
pc_register = true;
}
else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
- && generic_regnum == LLDB_REGNUM_GENERIC_PC)
+ && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA))
{
pc_register = true;
}
@@ -1936,9 +1948,16 @@ RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &
return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
}
+ bool is_pc_regnum = false;
+ if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC
+ || reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
+ {
+ is_pc_regnum = true;
+ }
+
lldb_private::UnwindLLDB::RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum))
return false;
return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
OpenPOWER on IntegriCloud