Skip to content

Commit 9fe455f

Browse files
[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.
1 parent 6d103d7 commit 9fe455f

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

lldb/include/lldb/Symbol/UnwindPlan.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class UnwindPlan {
6868
isAFAPlusOffset, // reg = AFA + offset
6969
inOtherRegister, // reg = other reg
7070
atDWARFExpression, // reg = deref(eval(dwarf_expr))
71-
isDWARFExpression // reg = eval(dwarf_expr)
71+
isDWARFExpression, // reg = eval(dwarf_expr)
72+
isConstant // reg = constant
7273
};
7374

7475
RegisterLocation() : m_location() {}
@@ -105,6 +106,15 @@ class UnwindPlan {
105106

106107
bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
107108

109+
bool IsConstant() const { return m_type == isConstant; }
110+
111+
void SetIsConstant(uint64_t value) {
112+
m_type = isConstant;
113+
m_location.constant_value = value;
114+
}
115+
116+
uint64_t GetConstant() const { return m_location.constant_value; }
117+
108118
void SetAtCFAPlusOffset(int32_t offset) {
109119
m_type = atCFAPlusOffset;
110120
m_location.offset = offset;
@@ -192,6 +202,8 @@ class UnwindPlan {
192202
const uint8_t *opcodes;
193203
uint16_t length;
194204
} expr;
205+
// For m_type == isConstant
206+
uint64_t constant_value;
195207
} m_location;
196208
};
197209

@@ -358,6 +370,9 @@ class UnwindPlan {
358370

359371
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
360372

373+
bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant,
374+
bool can_replace);
375+
361376
// When this UnspecifiedRegistersAreUndefined mode is
362377
// set, any register that is not specified by this Row will
363378
// be described as Undefined.

lldb/source/Symbol/UnwindPlan.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
4646
return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
4747
m_location.expr.length);
4848
break;
49+
case isConstant:
50+
return m_location.constant_value == rhs.m_location.constant_value;
4951
}
5052
}
5153
return false;
@@ -153,6 +155,9 @@ void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
153155
if (m_type == atDWARFExpression)
154156
s.PutChar(']');
155157
} break;
158+
case isConstant:
159+
s.Printf("=0x%" PRIx64, m_location.constant_value);
160+
break;
156161
}
157162
}
158163

@@ -351,6 +356,18 @@ bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
351356
return true;
352357
}
353358

359+
bool UnwindPlan::Row::SetRegisterLocationToIsConstant(uint32_t reg_num,
360+
uint64_t constant,
361+
bool can_replace) {
362+
if (!can_replace &&
363+
m_register_locations.find(reg_num) != m_register_locations.end())
364+
return false;
365+
RegisterLocation reg_loc;
366+
reg_loc.SetIsConstant(constant);
367+
m_register_locations[reg_num] = reg_loc;
368+
return true;
369+
}
370+
354371
bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
355372
return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
356373
m_afa_value == rhs.m_afa_value &&

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,15 @@ RegisterContextUnwind::SavedLocationForRegister(
16941694
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
16951695
}
16961696

1697+
if (unwindplan_regloc.IsConstant()) {
1698+
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
1699+
regloc.location.inferred_value = unwindplan_regloc.GetConstant();
1700+
m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
1701+
UnwindLogMsg("supplying caller's register %s (%d) via constant value",
1702+
regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
1703+
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
1704+
}
1705+
16971706
UnwindLogMsg("no save location for %s (%d) in this stack frame",
16981707
regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16991708

0 commit comments

Comments
 (0)