summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/UnwindPlan.h6
-rw-r--r--lldb/include/lldb/Target/ABI.h5
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp42
-rw-r--r--lldb/source/Target/ABI.cpp24
4 files changed, 51 insertions, 26 deletions
diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h
index 83cb6f8126b..64c00bf12c2 100644
--- a/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -116,6 +116,12 @@ public:
return m_type == unspecified;
}
+ bool
+ IsUndefined () const
+ {
+ return m_type == undefined;
+ }
+
bool
IsCFAPlusOffset () const
{
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index 94826d17350..cd0b57e61ff 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -16,6 +16,7 @@
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/ArrayRef.h"
@@ -110,6 +111,10 @@ public:
virtual bool
RegisterIsVolatile (const RegisterInfo *reg_info) = 0;
+ virtual bool
+ GetFallbackRegisterLocation (const RegisterInfo *reg_info,
+ UnwindPlan::Row::RegisterLocation &unwind_regloc);
+
// Should take a look at a call frame address (CFA) which is just the stack
// pointer value upon entry to a function. ABIs usually impose alignment
// restrictions (4, 8 or 16 byte aligned), and zero is usually not allowed.
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index d3f9089a49b..6feec5b8f2e 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -1390,45 +1390,28 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
}
}
- if (have_unwindplan_regloc == false)
- {
- // Did the UnwindPlan fail to give us the caller's stack pointer?
- // The stack pointer is defined to be the same as THIS frame's CFA, so return the CFA value as
- // the caller's stack pointer. This is true on x86-32/x86-64 at least.
-
- RegisterNumber sp_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
- if (sp_regnum.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM
- && sp_regnum.GetAsKind (eRegisterKindLLDB) == regnum.GetAsKind (eRegisterKindLLDB))
- {
- // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
- assert (sizeof (addr_t) <= sizeof (uint64_t));
- regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
- regloc.location.inferred_value = m_cfa;
- m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
- UnwindLogMsg ("supplying caller's stack pointer %s (%d) value, computed from CFA",
- regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
- return UnwindLLDB::RegisterSearchResult::eRegisterFound;
- }
- }
-
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
if (have_unwindplan_regloc == false)
{
- // If a volatile register is being requested, we don't want to forward the next frame's register contents
- // up the stack -- the register is not retrievable at this frame.
+ // If the UnwindPlan failed to give us an unwind location for this register, we may be able to fall back
+ // to some ABI-defined default. For example, some ABIs allow to determine the caller's SP via the CFA.
+ // Also, the ABI may set volatile registers to the undefined state.
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi)
{
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB));
- if (reg_info && abi->RegisterIsVolatile (reg_info))
+ if (reg_info && abi->GetFallbackRegisterLocation (reg_info, unwindplan_regloc))
{
- UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile",
+ UnwindLogMsg ("supplying caller's saved %s (%d)'s location using ABI default",
regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
- return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
+ have_unwindplan_regloc = true;
}
}
+ }
+ if (have_unwindplan_regloc == false)
+ {
if (IsFrameZero ())
{
// This is frame 0 - we should return the actual live register context value
@@ -1468,6 +1451,13 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
+ if (unwindplan_regloc.IsUndefined())
+ {
+ UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
+ return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
+ }
+
if (unwindplan_regloc.IsSame())
{
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp
index 6cea996a296..f5fd594877f 100644
--- a/lldb/source/Target/ABI.cpp
+++ b/lldb/source/Target/ABI.cpp
@@ -205,3 +205,27 @@ ABI::PrepareTrivialCall (Thread &thread,
assert( !"Should never get here!" );
return false;
}
+
+bool
+ABI::GetFallbackRegisterLocation (const RegisterInfo *reg_info,
+ UnwindPlan::Row::RegisterLocation &unwind_regloc)
+{
+ // Did the UnwindPlan fail to give us the caller's stack pointer?
+ // The stack pointer is defined to be the same as THIS frame's CFA, so return the CFA value as
+ // the caller's stack pointer. This is true on x86-32/x86-64 at least.
+ if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP)
+ {
+ unwind_regloc.SetIsCFAPlusOffset(0);
+ return true;
+ }
+
+ // If a volatile register is being requested, we don't want to forward the next frame's register contents
+ // up the stack -- the register is not retrievable at this frame.
+ if (RegisterIsVolatile(reg_info))
+ {
+ unwind_regloc.SetUndefined();
+ return true;
+ }
+
+ return false;
+}
OpenPOWER on IntegriCloud