llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) <details> <summary>Changes</summary> 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. --- 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: - (modified) lldb/source/Expression/DWARFExpression.cpp (+126-249) - (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+182-182) - (modified) llvm/include/llvm/BinaryFormat/Dwarf.h (+10-1) - (modified) llvm/include/llvm/ObjectYAML/DWARFYAML.h (+1-1) - (modified) llvm/lib/BinaryFormat/Dwarf.cpp (+30-4) ``````````diff 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] `````````` </details> https://github.com/llvm/llvm-project/pull/94679 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits