[lldb] Add constant value mode for RegisterLocation in UnwindPlans (#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.
This commit is contained in:
committed by
GitHub
parent
6d103d7746
commit
9fe455fd0c
@@ -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.
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user