Skip to content

Commit

Permalink
[lldb] Add constant value mode for RegisterLocation in UnwindPlans (#…
Browse files Browse the repository at this point in the history
…100624)

This is useful for language runtimes that compute register values by
inspecting the state of the currently running process. Currently, there
are no mechanisms enabling these runtimes to set register values to
arbitrary values.

The alternative considered would involve creating a dwarf expression
that produces an arbitrary integer (e.g. using OP_constu). However, the
current data structure for Rows is such that they do not own any memory
associated with dwarf expressions, which implies any such expression
would need to have static storage and therefore could not contain a
runtime value.

Adding a new rule for constants leads to a simpler implementation. It's
also worth noting that this does not make the "Location" union any
bigger, since it already contains a pointer+size pair.
  • Loading branch information
felipepiovezan authored Jul 31, 2024
1 parent 6d103d7 commit 9fe455f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
17 changes: 16 additions & 1 deletion lldb/include/lldb/Symbol/UnwindPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class UnwindPlan {
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() {}
Expand Down Expand Up @@ -105,6 +106,15 @@ class UnwindPlan {

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;
Expand Down Expand Up @@ -192,6 +202,8 @@ class UnwindPlan {
const uint8_t *opcodes;
uint16_t length;
} expr;
// For m_type == isConstant
uint64_t constant_value;
} m_location;
};

Expand Down Expand Up @@ -358,6 +370,9 @@ class UnwindPlan {

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.
Expand Down
17 changes: 17 additions & 0 deletions lldb/source/Symbol/UnwindPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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 &&
Expand Down
9 changes: 9 additions & 0 deletions lldb/source/Target/RegisterContextUnwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down

0 comments on commit 9fe455f

Please sign in to comment.