-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[lldb] Encode operands and arity in Dwarf.def and use them in LLDB. #94679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add the number of operands to Dwarf.h as documented in Table 7.6 in the DWARF 5 standard.
@llvm/pr-subscribers-llvm-binary-utilities @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) ChangesThis PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack) and use it from the LLDB DWARF expression evaluator. Patch is 42.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/94679.diff 5 Files Affected:
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 4681dbafb6f9c..b10c3d4ac5ad9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -912,6 +912,14 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
DW_OP_value_to_name(op));
}
+ if (std::optional<unsigned> arity =
+ llvm::dwarf::OperationArity(static_cast<LocationAtom>(op))) {
+ if (stack.size() < *arity)
+ return llvm::createStringError(
+ "%s needs at least %d stack entries (stack has %d entries)",
+ DW_OP_value_to_name(op), *arity, stack.size());
+ }
+
switch (op) {
// The DW_OP_addr operation has a single operand that encodes a machine
// address and whose size is the size of an address on the target machine.
@@ -1280,11 +1288,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: Duplicates the entry currently second in the stack at
// the top of the stack.
case DW_OP_over:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_over");
- } else
- stack.push_back(stack[stack.size() - 2]);
+ stack.push_back(stack[stack.size() - 2]);
break;
// OPCODE: DW_OP_pick
@@ -1307,14 +1311,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the stack becomes the second stack entry, and the second entry
// becomes the top of the stack
case DW_OP_swap:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_swap");
- } else {
- tmp = stack.back();
- stack.back() = stack[stack.size() - 2];
- stack[stack.size() - 2] = tmp;
- }
+ tmp = stack.back();
+ stack.back() = stack[stack.size() - 2];
+ stack[stack.size() - 2] = tmp;
break;
// OPCODE: DW_OP_rot
@@ -1323,18 +1322,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// the top of the stack becomes the third stack entry, the second entry
// becomes the top of the stack, and the third entry becomes the second
// entry.
- case DW_OP_rot:
- if (stack.size() < 3) {
- return llvm::createStringError(
- "expression stack needs at least 3 items for DW_OP_rot");
- } else {
- size_t last_idx = stack.size() - 1;
- Value old_top = stack[last_idx];
- stack[last_idx] = stack[last_idx - 1];
- stack[last_idx - 1] = stack[last_idx - 2];
- stack[last_idx - 2] = old_top;
- }
- break;
+ case DW_OP_rot: {
+ size_t last_idx = stack.size() - 1;
+ Value old_top = stack[last_idx];
+ stack[last_idx] = stack[last_idx - 1];
+ stack[last_idx - 1] = stack[last_idx - 2];
+ stack[last_idx - 2] = old_top;
+ } break;
// OPCODE: DW_OP_abs
// OPERANDS: none
@@ -1342,10 +1336,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// value and pushes its absolute value. If the absolute value can not be
// represented, the result is undefined.
case DW_OP_abs:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_abs");
- } else if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
+ if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
return llvm::createStringError(
"failed to take the absolute value of the first stack item");
}
@@ -1356,15 +1347,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack values, performs a bitwise and
// operation on the two, and pushes the result.
case DW_OP_and:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_and");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_div
@@ -1372,42 +1358,32 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack values, divides the former second
// entry by the former top of the stack using signed division, and pushes
// the result.
- case DW_OP_div:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_div");
- } else {
- tmp = stack.back();
- if (tmp.ResolveValue(exe_ctx).IsZero())
- return llvm::createStringError("divide by zero");
-
- stack.pop_back();
- Scalar divisor, dividend;
- divisor = tmp.ResolveValue(exe_ctx);
- dividend = stack.back().ResolveValue(exe_ctx);
- divisor.MakeSigned();
- dividend.MakeSigned();
- stack.back() = dividend / divisor;
-
- if (!stack.back().ResolveValue(exe_ctx).IsValid())
- return llvm::createStringError("divide failed");
- }
- break;
+ case DW_OP_div: {
+ tmp = stack.back();
+ if (tmp.ResolveValue(exe_ctx).IsZero())
+ return llvm::createStringError("divide by zero");
+
+ stack.pop_back();
+ Scalar divisor, dividend;
+ divisor = tmp.ResolveValue(exe_ctx);
+ dividend = stack.back().ResolveValue(exe_ctx);
+ divisor.MakeSigned();
+ dividend.MakeSigned();
+ stack.back() = dividend / divisor;
+
+ if (!stack.back().ResolveValue(exe_ctx).IsValid())
+ return llvm::createStringError("divide failed");
+ } break;
// OPCODE: DW_OP_minus
// OPERANDS: none
// DESCRIPTION: pops the top two stack values, subtracts the former top
// of the stack from the former second entry, and pushes the result.
case DW_OP_minus:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_minus");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_mod
@@ -1416,15 +1392,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// the calculation: former second stack entry modulo the former top of the
// stack.
case DW_OP_mod:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_mod");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_mul
@@ -1432,28 +1403,18 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, multiplies them
// together, and pushes the result.
case DW_OP_mul:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_mul");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_neg
// OPERANDS: none
// DESCRIPTION: pops the top stack entry, and pushes its negation.
case DW_OP_neg:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_neg");
- } else {
- if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
- return llvm::createStringError("unary negate failed");
- }
+ if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
+ return llvm::createStringError("unary negate failed");
break;
// OPCODE: DW_OP_not
@@ -1461,14 +1422,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top stack entry, and pushes its bitwise
// complement
case DW_OP_not:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_not");
- } else {
- if (!stack.back().ResolveValue(exe_ctx).OnesComplement()) {
- return llvm::createStringError("logical NOT failed");
- }
- }
+ if (!stack.back().ResolveValue(exe_ctx).OnesComplement())
+ return llvm::createStringError("logical NOT failed");
break;
// OPCODE: DW_OP_or
@@ -1476,15 +1431,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, performs a bitwise or
// operation on the two, and pushes the result.
case DW_OP_or:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_or");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_plus
@@ -1492,32 +1442,22 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, adds them together, and
// pushes the result.
case DW_OP_plus:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_plus");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().GetScalar() += tmp.GetScalar();
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().GetScalar() += tmp.GetScalar();
break;
// OPCODE: DW_OP_plus_uconst
// OPERANDS: none
// DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
// constant operand and pushes the result.
- case DW_OP_plus_uconst:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_plus_uconst");
- } else {
- const uint64_t uconst_value = opcodes.GetULEB128(&offset);
- // Implicit conversion from a UINT to a Scalar...
- stack.back().GetScalar() += uconst_value;
- if (!stack.back().GetScalar().IsValid())
- return llvm::createStringError("DW_OP_plus_uconst failed");
- }
- break;
+ case DW_OP_plus_uconst: {
+ const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+ // Implicit conversion from a UINT to a Scalar...
+ stack.back().GetScalar() += uconst_value;
+ if (!stack.back().GetScalar().IsValid())
+ return llvm::createStringError("DW_OP_plus_uconst failed");
+ } break;
// OPCODE: DW_OP_shl
// OPERANDS: none
@@ -1525,14 +1465,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// second entry left by the number of bits specified by the former top of
// the stack, and pushes the result.
case DW_OP_shl:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shl");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_shr
@@ -1541,17 +1476,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// entry right logically (filling with zero bits) by the number of bits
// specified by the former top of the stack, and pushes the result.
case DW_OP_shr:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shr");
- } else {
- tmp = stack.back();
- stack.pop_back();
- if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
- tmp.ResolveValue(exe_ctx))) {
- return llvm::createStringError("DW_OP_shr failed");
- }
- }
+ tmp = stack.back();
+ stack.pop_back();
+ if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
+ tmp.ResolveValue(exe_ctx)))
+ return llvm::createStringError("DW_OP_shr failed");
break;
// OPCODE: DW_OP_shra
@@ -1561,14 +1490,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// sign for the result) by the number of bits specified by the former top
// of the stack, and pushes the result.
case DW_OP_shra:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shra");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_xor
@@ -1576,15 +1500,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, performs the bitwise
// exclusive-or operation on the two, and pushes the result.
case DW_OP_xor:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_xor");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_skip
@@ -1615,30 +1534,25 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// value popped is not the constant 0, the 2-byte constant operand is the
// number of bytes of the DWARF expression to skip forward or backward from
// the current operation, beginning after the 2-byte constant.
- case DW_OP_bra:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_bra");
- } else {
- tmp = stack.back();
- stack.pop_back();
- int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
- Scalar zero(0);
- if (tmp.ResolveValue(exe_ctx) != zero) {
- lldb::offset_t new_offset = offset + bra_offset;
- // New offset can point at the end of the data, in this case we should
- // terminate the DWARF expression evaluation (will happen in the loop
- // condition).
- if (new_offset <= opcodes.GetByteSize())
- offset = new_offset;
- else {
- return llvm::createStringError(llvm::formatv(
- "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
- bra_offset, opcodes.GetByteSize()));
- }
+ case DW_OP_bra: {
+ tmp = stack.back();
+ stack.pop_back();
+ int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+ Scalar zero(0);
+ if (tmp.ResolveValue(exe_ctx) != zero) {
+ lldb::offset_t new_offset = offset + bra_offset;
+ // New offset can point at the end of the data, in this case we should
+ // terminate the DWARF expression evaluation (will happen in the loop
+ // condition).
+ if (new_offset <= opcodes.GetByteSize())
+ offset = new_offset;
+ else {
+ return llvm::createStringError(llvm::formatv(
+ "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
+ bra_offset, opcodes.GetByteSize()));
}
}
- break;
+ } break;
// OPCODE: DW_OP_eq
// OPERANDS: none
@@ -1648,15 +1562,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_eq:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_eq");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_ge
@@ -1667,15 +1576,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_ge:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_ge");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_gt
@@ -1686,15 +1590,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_gt:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_gt");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_le
@@ -1705,15 +1604,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_le:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_le");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_lt
@@ -1724,15 +1618,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_lt:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_lt");
- } else {
- t...
[truncated]
|
@llvm/pr-subscribers-objectyaml Author: Jonas Devlieghere (JDevlieghere) ChangesThis PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack) and use it from the LLDB DWARF expression evaluator. Patch is 42.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/94679.diff 5 Files Affected:
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 4681dbafb6f9c..b10c3d4ac5ad9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -912,6 +912,14 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
DW_OP_value_to_name(op));
}
+ if (std::optional<unsigned> arity =
+ llvm::dwarf::OperationArity(static_cast<LocationAtom>(op))) {
+ if (stack.size() < *arity)
+ return llvm::createStringError(
+ "%s needs at least %d stack entries (stack has %d entries)",
+ DW_OP_value_to_name(op), *arity, stack.size());
+ }
+
switch (op) {
// The DW_OP_addr operation has a single operand that encodes a machine
// address and whose size is the size of an address on the target machine.
@@ -1280,11 +1288,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: Duplicates the entry currently second in the stack at
// the top of the stack.
case DW_OP_over:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_over");
- } else
- stack.push_back(stack[stack.size() - 2]);
+ stack.push_back(stack[stack.size() - 2]);
break;
// OPCODE: DW_OP_pick
@@ -1307,14 +1311,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the stack becomes the second stack entry, and the second entry
// becomes the top of the stack
case DW_OP_swap:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_swap");
- } else {
- tmp = stack.back();
- stack.back() = stack[stack.size() - 2];
- stack[stack.size() - 2] = tmp;
- }
+ tmp = stack.back();
+ stack.back() = stack[stack.size() - 2];
+ stack[stack.size() - 2] = tmp;
break;
// OPCODE: DW_OP_rot
@@ -1323,18 +1322,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// the top of the stack becomes the third stack entry, the second entry
// becomes the top of the stack, and the third entry becomes the second
// entry.
- case DW_OP_rot:
- if (stack.size() < 3) {
- return llvm::createStringError(
- "expression stack needs at least 3 items for DW_OP_rot");
- } else {
- size_t last_idx = stack.size() - 1;
- Value old_top = stack[last_idx];
- stack[last_idx] = stack[last_idx - 1];
- stack[last_idx - 1] = stack[last_idx - 2];
- stack[last_idx - 2] = old_top;
- }
- break;
+ case DW_OP_rot: {
+ size_t last_idx = stack.size() - 1;
+ Value old_top = stack[last_idx];
+ stack[last_idx] = stack[last_idx - 1];
+ stack[last_idx - 1] = stack[last_idx - 2];
+ stack[last_idx - 2] = old_top;
+ } break;
// OPCODE: DW_OP_abs
// OPERANDS: none
@@ -1342,10 +1336,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// value and pushes its absolute value. If the absolute value can not be
// represented, the result is undefined.
case DW_OP_abs:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_abs");
- } else if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
+ if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
return llvm::createStringError(
"failed to take the absolute value of the first stack item");
}
@@ -1356,15 +1347,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack values, performs a bitwise and
// operation on the two, and pushes the result.
case DW_OP_and:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_and");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_div
@@ -1372,42 +1358,32 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack values, divides the former second
// entry by the former top of the stack using signed division, and pushes
// the result.
- case DW_OP_div:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_div");
- } else {
- tmp = stack.back();
- if (tmp.ResolveValue(exe_ctx).IsZero())
- return llvm::createStringError("divide by zero");
-
- stack.pop_back();
- Scalar divisor, dividend;
- divisor = tmp.ResolveValue(exe_ctx);
- dividend = stack.back().ResolveValue(exe_ctx);
- divisor.MakeSigned();
- dividend.MakeSigned();
- stack.back() = dividend / divisor;
-
- if (!stack.back().ResolveValue(exe_ctx).IsValid())
- return llvm::createStringError("divide failed");
- }
- break;
+ case DW_OP_div: {
+ tmp = stack.back();
+ if (tmp.ResolveValue(exe_ctx).IsZero())
+ return llvm::createStringError("divide by zero");
+
+ stack.pop_back();
+ Scalar divisor, dividend;
+ divisor = tmp.ResolveValue(exe_ctx);
+ dividend = stack.back().ResolveValue(exe_ctx);
+ divisor.MakeSigned();
+ dividend.MakeSigned();
+ stack.back() = dividend / divisor;
+
+ if (!stack.back().ResolveValue(exe_ctx).IsValid())
+ return llvm::createStringError("divide failed");
+ } break;
// OPCODE: DW_OP_minus
// OPERANDS: none
// DESCRIPTION: pops the top two stack values, subtracts the former top
// of the stack from the former second entry, and pushes the result.
case DW_OP_minus:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_minus");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_mod
@@ -1416,15 +1392,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// the calculation: former second stack entry modulo the former top of the
// stack.
case DW_OP_mod:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_mod");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_mul
@@ -1432,28 +1403,18 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, multiplies them
// together, and pushes the result.
case DW_OP_mul:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_mul");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_neg
// OPERANDS: none
// DESCRIPTION: pops the top stack entry, and pushes its negation.
case DW_OP_neg:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_neg");
- } else {
- if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
- return llvm::createStringError("unary negate failed");
- }
+ if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
+ return llvm::createStringError("unary negate failed");
break;
// OPCODE: DW_OP_not
@@ -1461,14 +1422,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top stack entry, and pushes its bitwise
// complement
case DW_OP_not:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_not");
- } else {
- if (!stack.back().ResolveValue(exe_ctx).OnesComplement()) {
- return llvm::createStringError("logical NOT failed");
- }
- }
+ if (!stack.back().ResolveValue(exe_ctx).OnesComplement())
+ return llvm::createStringError("logical NOT failed");
break;
// OPCODE: DW_OP_or
@@ -1476,15 +1431,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, performs a bitwise or
// operation on the two, and pushes the result.
case DW_OP_or:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_or");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_plus
@@ -1492,32 +1442,22 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, adds them together, and
// pushes the result.
case DW_OP_plus:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_plus");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().GetScalar() += tmp.GetScalar();
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().GetScalar() += tmp.GetScalar();
break;
// OPCODE: DW_OP_plus_uconst
// OPERANDS: none
// DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
// constant operand and pushes the result.
- case DW_OP_plus_uconst:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_plus_uconst");
- } else {
- const uint64_t uconst_value = opcodes.GetULEB128(&offset);
- // Implicit conversion from a UINT to a Scalar...
- stack.back().GetScalar() += uconst_value;
- if (!stack.back().GetScalar().IsValid())
- return llvm::createStringError("DW_OP_plus_uconst failed");
- }
- break;
+ case DW_OP_plus_uconst: {
+ const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+ // Implicit conversion from a UINT to a Scalar...
+ stack.back().GetScalar() += uconst_value;
+ if (!stack.back().GetScalar().IsValid())
+ return llvm::createStringError("DW_OP_plus_uconst failed");
+ } break;
// OPCODE: DW_OP_shl
// OPERANDS: none
@@ -1525,14 +1465,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// second entry left by the number of bits specified by the former top of
// the stack, and pushes the result.
case DW_OP_shl:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shl");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_shr
@@ -1541,17 +1476,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// entry right logically (filling with zero bits) by the number of bits
// specified by the former top of the stack, and pushes the result.
case DW_OP_shr:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shr");
- } else {
- tmp = stack.back();
- stack.pop_back();
- if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
- tmp.ResolveValue(exe_ctx))) {
- return llvm::createStringError("DW_OP_shr failed");
- }
- }
+ tmp = stack.back();
+ stack.pop_back();
+ if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
+ tmp.ResolveValue(exe_ctx)))
+ return llvm::createStringError("DW_OP_shr failed");
break;
// OPCODE: DW_OP_shra
@@ -1561,14 +1490,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// sign for the result) by the number of bits specified by the former top
// of the stack, and pushes the result.
case DW_OP_shra:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_shra");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_xor
@@ -1576,15 +1500,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: pops the top two stack entries, performs the bitwise
// exclusive-or operation on the two, and pushes the result.
case DW_OP_xor:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_xor");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_skip
@@ -1615,30 +1534,25 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// value popped is not the constant 0, the 2-byte constant operand is the
// number of bytes of the DWARF expression to skip forward or backward from
// the current operation, beginning after the 2-byte constant.
- case DW_OP_bra:
- if (stack.empty()) {
- return llvm::createStringError(
- "expression stack needs at least 1 item for DW_OP_bra");
- } else {
- tmp = stack.back();
- stack.pop_back();
- int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
- Scalar zero(0);
- if (tmp.ResolveValue(exe_ctx) != zero) {
- lldb::offset_t new_offset = offset + bra_offset;
- // New offset can point at the end of the data, in this case we should
- // terminate the DWARF expression evaluation (will happen in the loop
- // condition).
- if (new_offset <= opcodes.GetByteSize())
- offset = new_offset;
- else {
- return llvm::createStringError(llvm::formatv(
- "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
- bra_offset, opcodes.GetByteSize()));
- }
+ case DW_OP_bra: {
+ tmp = stack.back();
+ stack.pop_back();
+ int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+ Scalar zero(0);
+ if (tmp.ResolveValue(exe_ctx) != zero) {
+ lldb::offset_t new_offset = offset + bra_offset;
+ // New offset can point at the end of the data, in this case we should
+ // terminate the DWARF expression evaluation (will happen in the loop
+ // condition).
+ if (new_offset <= opcodes.GetByteSize())
+ offset = new_offset;
+ else {
+ return llvm::createStringError(llvm::formatv(
+ "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
+ bra_offset, opcodes.GetByteSize()));
}
}
- break;
+ } break;
// OPCODE: DW_OP_eq
// OPERANDS: none
@@ -1648,15 +1562,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_eq:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_eq");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_ge
@@ -1667,15 +1576,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_ge:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_ge");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_gt
@@ -1686,15 +1590,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_gt:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_gt");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_le
@@ -1705,15 +1604,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_le:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_le");
- } else {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) =
- stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
- }
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
break;
// OPCODE: DW_OP_lt
@@ -1724,15 +1618,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// of the operation is true or the constant value 0 if the result of the
// operation is false.
case DW_OP_lt:
- if (stack.size() < 2) {
- return llvm::createStringError(
- "expression stack needs at least 2 items for DW_OP_lt");
- } else {
- t...
[truncated]
|
The number of operands comes directly from Table 7.6 in the DWARF 5 spec. I'm less confident in the arity which required me to consult the description of the operations. I think I got them right and everything covered by the LLDB test suite still passes, but I would definitely appreciate a second pair of eyes on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nice cleanup. I found a few minor issues in the table.
I'm also not sure the number of operands is ever useful without having the encoding ready, but maybe for DIExpression it actually is (because there we always use the same encoding).
Yeah, I came to the same conclusion, which is why LLDB isn't using the data. I primarily added it to avoid mistakes where someone confuses the number of operands with the arity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me as long as the data is correct. Cleans up the code nicely.
It would be possible to encode the argument values using DW_FORM enumerations with variadic macros. If we move the OPERANDS, ARITY
to the end and have ARITY come first:
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR, ARITY, OPERANDS, ...)
And then for DW_OP_addr:
HANDLE_DW_OP(0x03, addr, 2, DWARF, 0, 1, DW_FORM_addr)
Then clients can use the __VA_ARGS__
if they want this info.
@clayborg that's a cool idea. We might be able to use that to implement |
Revert for now, work it later 6d01a350ce9 [lldb] Encode operands and arity in Dwarf.def and use them in LLDB. (llvm#94679) Change-Id: I6fb991b11e7afd53e66090c3ba2c487e509786e7
…lvm#94679) This PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack). - The arity is used in LLDB's DWARF expression evaluator. - The number of operands is unused, but is present in the table to avoid confusing the arity with the operands. Keeping the latter up to date should be straightforward as it maps directly to a table present in the DWARF standard. Signed-off-by: Hafidz Muzakky <[email protected]>
…lvm#94679) This PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack). - The arity is used in LLDB's DWARF expression evaluator. - The number of operands is unused, but is present in the table to avoid confusing the arity with the operands. Keeping the latter up to date should be straightforward as it maps directly to a table present in the DWARF standard. Change-Id: I19dc4cf8c13f046d09f0a58199e373702b2a2389
This PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack) and use it from the LLDB DWARF expression evaluator.