diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index ebb0ec421da7..a9e8406608ff 100644 --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -68,7 +68,8 @@ public: isAFAPlusOffset, // reg = AFA + offset inOtherRegister, // reg = other reg atDWARFExpression, // reg = deref(eval(dwarf_expr)) - isDWARFExpression // reg = eval(dwarf_expr) + isDWARFExpression, // reg = eval(dwarf_expr) + isConstant // reg = constant }; RegisterLocation() : m_location() {} @@ -105,6 +106,15 @@ public: bool IsDWARFExpression() const { return m_type == isDWARFExpression; } + bool IsConstant() const { return m_type == isConstant; } + + void SetIsConstant(uint64_t value) { + m_type = isConstant; + m_location.constant_value = value; + } + + uint64_t GetConstant() const { return m_location.constant_value; } + void SetAtCFAPlusOffset(int32_t offset) { m_type = atCFAPlusOffset; m_location.offset = offset; @@ -192,6 +202,8 @@ public: const uint8_t *opcodes; uint16_t length; } expr; + // For m_type == isConstant + uint64_t constant_value; } m_location; }; @@ -358,6 +370,9 @@ public: bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace); + bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant, + bool can_replace); + // When this UnspecifiedRegistersAreUndefined mode is // set, any register that is not specified by this Row will // be described as Undefined. diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index e258a4e3d82f..e2dbd81a82c8 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -46,6 +46,8 @@ operator==(const UnwindPlan::Row::RegisterLocation &rhs) const { return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length); break; + case isConstant: + return m_location.constant_value == rhs.m_location.constant_value; } } return false; @@ -153,6 +155,9 @@ void UnwindPlan::Row::RegisterLocation::Dump(Stream &s, if (m_type == atDWARFExpression) s.PutChar(']'); } break; + case isConstant: + s.Printf("=0x%" PRIx64, m_location.constant_value); + break; } } @@ -351,6 +356,18 @@ bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num, return true; } +bool UnwindPlan::Row::SetRegisterLocationToIsConstant(uint32_t reg_num, + uint64_t constant, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetIsConstant(constant); + m_register_locations[reg_num] = reg_loc; + return true; +} + bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const { return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value && m_afa_value == rhs.m_afa_value && diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index bc8081f4e3b3..a61228d092d8 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -1694,6 +1694,15 @@ RegisterContextUnwind::SavedLocationForRegister( return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } + if (unwindplan_regloc.IsConstant()) { + regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; + regloc.location.inferred_value = unwindplan_regloc.GetConstant(); + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg("supplying caller's register %s (%d) via constant value", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + UnwindLogMsg("no save location for %s (%d) in this stack frame", regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));