From 7311bb34f63df58edb4819e5b483b49932b371bd Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 14 Apr 2016 14:25:20 +0000 Subject: [PATCH] Add new ABI callback to provide fallback unwind register locations If the UnwindPlan did not identify how to unwind the stack pointer register, LLDB currently assumes it can determine to caller's SP from the current frame's CFA. This is true on most platforms where CFA is by definition equal to the incoming SP at function entry. However, on the s390x target, we instead define the CFA to equal the incoming SP plus an offset of 160 bytes. This is because our ABI defines that the caller has to provide a register save area of size 160 bytes. This area is allocated by the caller, but is considered part of the callee's stack frame, and therefore the CFA is defined as pointing to the top of this area. In order to make this work on s390x, this patch introduces a new ABI callback GetFallbackRegisterLocation that provides platform- specific fallback register locations for unwinding. The existing code to handle SP unwinding as well as volatile registers is moved into the default implementation of that ABI callback, to allow targets where that implementation is incorrect to override it. This patch in itself is a no-op for all existing platforms. But it is a pre-requisite for adding s390x support. Differential Revision: http://reviews.llvm.org/D18977 llvm-svn: 266307 --- lldb/include/lldb/Symbol/UnwindPlan.h | 6 ++++ lldb/include/lldb/Target/ABI.h | 5 +++ .../Process/Utility/RegisterContextLLDB.cpp | 42 +++++++++------------- lldb/source/Target/ABI.cpp | 24 +++++++++++++ 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index 83cb6f8..64c00bf 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 94826d1..cd0b57e 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 d3f9089..6feec5b 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 6cea996..f5fd594 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; +} -- 2.7.4