[lldb] [llvm] [lldb] Use llvm::DWARFExpression::iterator in DWARFExpression::Evaluate (PR #190556)

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 5 15:37:02 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb

@llvm/pr-subscribers-debuginfo

Author: Sergei Barannikov (s-barannikov)

<details>
<summary>Changes</summary>



---

Patch is 31.05 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/190556.diff


12 Files Affected:

- (modified) lldb/include/lldb/Expression/DWARFExpression.h (+1-1) 
- (modified) lldb/source/Expression/CMakeLists.txt (+1) 
- (modified) lldb/source/Expression/DWARFExpression.cpp (+105-84) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (+2-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (+2-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+2-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp (+1-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h (+1-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp (+6-6) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h (+1-1) 
- (modified) lldb/unittests/Expression/DWARFExpressionTest.cpp (+4-5) 
- (modified) llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h (+2) 


``````````diff
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 1f8464cf5cf85..b1895690985a7 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -53,7 +53,7 @@ class DWARFExpression {
                              const lldb::offset_t data_offset,
                              const uint8_t op) const = 0;
     virtual bool
-    ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+    ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
                            lldb::offset_t &offset, RegisterContext *reg_ctx,
                            lldb::RegisterKind reg_kind, Stack &stack) const = 0;
 
diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt
index 515289cd0f091..d40bf184eb02e 100644
--- a/lldb/source/Expression/CMakeLists.txt
+++ b/lldb/source/Expression/CMakeLists.txt
@@ -25,6 +25,7 @@ add_lldb_library(lldbExpression NO_PLUGIN_DEPENDENCIES
   LINK_COMPONENTS
     Core
     DebugInfoDWARF
+    DebugInfoDWARFLowLevel
     ExecutionEngine
     Support
   LINK_LIBS
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 1e12b868191ab..a3f6ccc304da5 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -593,8 +593,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
 static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
                                               ExecutionContext *exe_ctx,
                                               RegisterContext *reg_ctx,
-                                              const DataExtractor &opcodes,
-                                              lldb::offset_t &opcode_offset,
+                                              llvm::ArrayRef<uint8_t> subexpr,
                                               Log *log) {
   // DW_OP_entry_value(sub-expr) describes the location a variable had upon
   // function entry: this variable location is presumed to be optimized out at
@@ -729,11 +728,6 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
   // 3. Attempt to locate the DW_OP_entry_value expression in the set of
   //    available call site parameters. If found, evaluate the corresponding
   //    parameter in the context of the parent frame.
-  const uint32_t subexpr_len = opcodes.GetULEB128(&opcode_offset);
-  const void *subexpr_data = opcodes.GetData(&opcode_offset, subexpr_len);
-  if (!subexpr_data)
-    return llvm::createStringError("subexpr could not be read");
-
   const CallSiteParameter *matched_param = nullptr;
   for (const CallSiteParameter &param : call_edge->GetCallSiteParameters()) {
     DataExtractor param_subexpr_extractor;
@@ -741,7 +735,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
       continue;
     lldb::offset_t param_subexpr_offset = 0;
     const void *param_subexpr_data =
-        param_subexpr_extractor.GetData(&param_subexpr_offset, subexpr_len);
+        param_subexpr_extractor.GetData(&param_subexpr_offset, subexpr.size());
     if (!param_subexpr_data ||
         param_subexpr_extractor.BytesLeft(param_subexpr_offset) != 0)
       continue;
@@ -753,7 +747,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
     // Note that an equality check is sufficient: the contents of the
     // DW_OP_entry_value subexpression are only used to identify the right call
     // site parameter in the parent, and do not require any special handling.
-    if (memcmp(subexpr_data, param_subexpr_data, subexpr_len) == 0) {
+    if (memcmp(subexpr.data(), param_subexpr_data, subexpr.size()) == 0) {
       matched_param = ¶m;
       break;
     }
@@ -1026,8 +1020,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     const DWARFExpression::Delegate *dwarf_cu,
     const lldb::RegisterKind reg_kind, const Value *initial_value_ptr,
     const Value *object_address_ptr) {
+  uint32_t address_size = opcodes.GetAddressByteSize();
+  llvm::DataExtractor expr_data = opcodes.GetAsLLVM();
+  llvm::DWARFExpression expr(expr_data, address_size);
 
-  if (opcodes.GetByteSize() == 0)
+  if (expr_data.size() == 0)
     return llvm::createStringError(
         "no location, value may have been optimized out");
 
@@ -1048,7 +1045,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   if (initial_value_ptr)
     stack.push_back(*initial_value_ptr);
 
-  lldb::offset_t offset = 0;
   Value tmp;
   uint32_t reg_num;
 
@@ -1065,9 +1061,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // TODO: Avoid implicit trunc?
     // See https://github.com/llvm/llvm-project/issues/112510.
     bool is_signed = std::is_signed<decltype(v)>::value;
-    return Scalar(llvm::APSInt(llvm::APInt(8 * opcodes.GetAddressByteSize(), v,
-                                           is_signed, /*implicitTrunc=*/true),
-                               !is_signed));
+    return Scalar(llvm::APSInt(
+        llvm::APInt(8 * address_size, v, is_signed, /*implicitTrunc=*/true),
+        !is_signed));
   };
 
   // The default kind is a memory location. This is updated by any
@@ -1075,9 +1071,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   // by composition operations like DW_OP_piece.
   LocationDescriptionKind dwarf4_location_description_kind = Memory;
 
-  while (opcodes.ValidOffset(offset)) {
-    const lldb::offset_t op_offset = offset;
-    const uint8_t op = opcodes.GetU8(&offset);
+  llvm::DWARFExpression::iterator op = expr.begin(), op_end = expr.end();
+  while (op != op_end) {
+    const uint64_t op_offset = op.getOffset();
+    const LocationAtom opcode = static_cast<LocationAtom>(op->getCode());
 
     if (log && log->GetVerbose()) {
       size_t count = stack.size();
@@ -1090,22 +1087,21 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         LLDB_LOGF(log, "  %s", new_value.GetData());
       }
       LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset,
-                DW_OP_value_to_name(op));
+                DW_OP_value_to_name(opcode));
     }
 
-    if (std::optional<unsigned> arity =
-            llvm::dwarf::OperationArity(static_cast<LocationAtom>(op))) {
+    if (std::optional<unsigned> arity = OperationArity(opcode)) {
       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());
+            DW_OP_value_to_name(opcode), *arity, stack.size());
     }
 
-    switch (op) {
+    switch (opcode) {
     // 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.
     case DW_OP_addr:
-      stack.push_back(Scalar(opcodes.GetAddress(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       if (target &&
           target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) {
         // wasm file sections aren't mapped into memory, therefore addresses can
@@ -1160,7 +1156,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // retrieved from the dereferenced address is the size of an address on the
     // target machine.
     case DW_OP_deref: {
-      size_t size = opcodes.GetAddressByteSize();
+      size_t size = address_size;
       if (llvm::Error err = Evaluate_DW_OP_deref_size(
               stack, exe_ctx, module_sp, process, target, size, size,
               dwarf4_location_description_kind))
@@ -1180,10 +1176,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the size of an address on the target machine before being pushed on the
     // expression stack.
     case DW_OP_deref_size: {
-      size_t size = opcodes.GetU8(&offset);
+      size_t size = op->getRawOperand(0);
       if (llvm::Error err = Evaluate_DW_OP_deref_size(
-              stack, exe_ctx, module_sp, process, target, size,
-              opcodes.GetAddressByteSize(), dwarf4_location_description_kind))
+              stack, exe_ctx, module_sp, process, target, size, address_size,
+              dwarf4_location_description_kind))
         return err;
     } break;
 
@@ -1231,36 +1227,36 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DW_OP_constu     unsigned LEB128 integer constant
     // DW_OP_consts     signed LEB128 integer constant
     case DW_OP_const1u:
-      stack.push_back(to_generic(opcodes.GetU8(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const1s:
-      stack.push_back(to_generic((int8_t)opcodes.GetU8(&offset)));
+      stack.push_back(to_generic((int8_t)op->getRawOperand(0)));
       break;
     case DW_OP_const2u:
-      stack.push_back(to_generic(opcodes.GetU16(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const2s:
-      stack.push_back(to_generic((int16_t)opcodes.GetU16(&offset)));
+      stack.push_back(to_generic((int16_t)op->getRawOperand(0)));
       break;
     case DW_OP_const4u:
-      stack.push_back(to_generic(opcodes.GetU32(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const4s:
-      stack.push_back(to_generic((int32_t)opcodes.GetU32(&offset)));
+      stack.push_back(to_generic((int32_t)op->getRawOperand(0)));
       break;
     case DW_OP_const8u:
-      stack.push_back(to_generic(opcodes.GetU64(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const8s:
-      stack.push_back(to_generic((int64_t)opcodes.GetU64(&offset)));
+      stack.push_back(to_generic((int64_t)op->getRawOperand(0)));
       break;
     // These should also use to_generic, but we can't do that due to a
     // producer-side bug in llvm. See llvm.org/pr48087.
     case DW_OP_constu:
-      stack.push_back(Scalar(opcodes.GetULEB128(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       break;
     case DW_OP_consts:
-      stack.push_back(Scalar(opcodes.GetSLEB128(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       break;
 
     // OPCODE: DW_OP_dup
@@ -1296,7 +1292,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: The stack entry with the specified index (0 through 255,
     // inclusive) is pushed on the stack
     case DW_OP_pick: {
-      uint8_t pick_idx = opcodes.GetU8(&offset);
+      uint8_t pick_idx = op->getRawOperand(0);
       if (pick_idx < stack.size())
         stack.push_back(stack[stack.size() - 1 - pick_idx]);
       else {
@@ -1447,7 +1443,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
     // constant operand and pushes the result.
     case DW_OP_plus_uconst: {
-      const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+      const uint64_t uconst_value = op->getRawOperand(0);
       // Implicit conversion from a UINT to a Scalar...
       stack.back().GetScalar() += uconst_value;
       if (!stack.back().GetScalar().IsValid())
@@ -1506,18 +1502,18 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the DWARF expression to skip forward or backward from the current
     // operation, beginning after the 2-byte constant.
     case DW_OP_skip: {
-      int16_t skip_offset = (int16_t)opcodes.GetU16(&offset);
-      lldb::offset_t new_offset = offset + skip_offset;
+      int16_t skip_offset = (int16_t)op->getRawOperand(0);
+      lldb::offset_t new_offset = op->getEndOffset() + skip_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::createStringErrorV(
-            "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset,
-            skip_offset, opcodes.GetByteSize());
+      if (new_offset <= expr_data.size()) {
+        op = op.skipBytes(skip_offset);
+        continue;
       }
+      return llvm::createStringErrorV(
+          "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}",
+          op->getEndOffset(), skip_offset, expr_data.size());
     } break;
 
     // OPCODE: DW_OP_bra
@@ -1530,20 +1526,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_bra: {
       tmp = stack.back();
       stack.pop_back();
-      int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+      int16_t bra_offset = (int16_t)op->getRawOperand(0);
       Scalar zero(0);
       if (tmp.GetScalar() != zero) {
-        lldb::offset_t new_offset = offset + bra_offset;
+        lldb::offset_t new_offset = op->getEndOffset() + 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::createStringErrorV(
-              "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
-              bra_offset, opcodes.GetByteSize());
+        if (new_offset <= expr_data.size()) {
+          op = op.skipBytes(bra_offset);
+          continue;
         }
+        return llvm::createStringErrorV(
+            "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}",
+            op->getEndOffset(), bra_offset, expr_data.size());
       }
     } break;
 
@@ -1662,7 +1658,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_lit29:
     case DW_OP_lit30:
     case DW_OP_lit31:
-      stack.push_back(to_generic(op - DW_OP_lit0));
+      stack.push_back(to_generic(opcode - DW_OP_lit0));
       break;
 
     // OPCODE: DW_OP_regN
@@ -1701,7 +1697,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_reg30:
     case DW_OP_reg31: {
       dwarf4_location_description_kind = Register;
-      reg_num = op - DW_OP_reg0;
+      reg_num = opcode - DW_OP_reg0;
 
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
@@ -1714,7 +1710,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Push the value in register on the top of the stack.
     case DW_OP_regx: {
       dwarf4_location_description_kind = Register;
-      reg_num = opcodes.GetULEB128(&offset);
+      reg_num = op->getRawOperand(0);
       Status read_err;
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
@@ -1759,12 +1755,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_breg29:
     case DW_OP_breg30:
     case DW_OP_breg31: {
-      reg_num = op - DW_OP_breg0;
+      reg_num = opcode - DW_OP_breg0;
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
         return err;
 
-      int64_t breg_offset = opcodes.GetSLEB128(&offset);
+      int64_t breg_offset = op->getRawOperand(0);
       tmp.GetScalar() += (uint64_t)breg_offset;
       tmp.ClearContext();
       stack.push_back(tmp);
@@ -1777,12 +1773,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Value is in memory at the address specified by register
     // N plus an offset.
     case DW_OP_bregx: {
-      reg_num = opcodes.GetULEB128(&offset);
+      reg_num = op->getRawOperand(0);
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
         return err;
 
-      int64_t breg_offset = opcodes.GetSLEB128(&offset);
+      int64_t breg_offset = op->getRawOperand(0);
       tmp.GetScalar() += (uint64_t)breg_offset;
       tmp.ClearContext();
       stack.push_back(tmp);
@@ -1795,7 +1791,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
           Scalar value;
           if (llvm::Error err = frame->GetFrameBaseValue(value))
             return err;
-          int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
+          int64_t fbreg_offset = op->getRawOperand(0);
           value += fbreg_offset;
           stack.push_back(value);
           stack.back().SetValueType(Value::ValueType::LoadAddress);
@@ -1835,7 +1831,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       // Reset for the next piece.
       dwarf4_location_description_kind = Memory;
 
-      const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
+      const uint64_t piece_byte_size = op->getRawOperand(0);
 
       if (piece_byte_size > 0) {
         Value curr_piece;
@@ -1972,8 +1968,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
             log, dwarf_cu, dwarf4_location_description_kind, &stack.back());
         // Reset for the next piece.
         dwarf4_location_description_kind = Memory;
-        const uint64_t piece_bit_size = opcodes.GetULEB128(&offset);
-        const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset);
+        const uint64_t piece_bit_size = op->getRawOperand(0);
+        const uint64_t piece_bit_offset = op->getRawOperand(1);
         switch (stack.back().GetValueType()) {
         case Value::ValueType::Invalid:
           return llvm::createStringError(
@@ -2010,16 +2006,17 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_implicit_value: {
       dwarf4_location_description_kind = Implicit;
 
-      const uint32_t len = opcodes.GetULEB128(&offset);
-      const void *data = opcodes.GetData(&offset, len);
+      const uint64_t block_size = op->getRawOperand(0);
+      uint64_t block_offset = op->getRawOperand(1);
 
-      if (!data) {
-        LLDB_LOG(log, "Evaluate_DW_OP_implicit_value: could not be read data");
-        return llvm::createStringError("could not evaluate %s",
-                                       DW_OP_value_to_name(op));
-      }
+      llvm::Error error = llvm::Error::success();
+      llvm::StringRef block_data =
+          expr_data.getBytes(&block_offset, block_size, &error);
 
-      Value result(data, len);
+      if (error)
+        return error;
+
+      Value result(block_data.data(), block_data.size());
       stack.push_back(result);
       break;
     }
@@ -2027,7 +2024,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_implicit_pointer: {
       dwarf4_location_description_kind = Implicit;
       return llvm::createStringError("could not evaluate %s",
-                                     DW_OP_value_to_name(op));
+                                     DW_OP_value_to_name(opcode));
     }
 
     // OPCODE: DW_OP_push_object_address
@@ -2107,7 +2104,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Pop the top stack element, convert it to a
     // different type, and push the result.
     case DW_OP_convert: {
-      const uint64_t relative_die_offset = opcodes.GetULEB128(&offset);
+      const uint64_t relative_die_offset = op->getRawOperand(0);
       uint64_t bit_size;
       bool sign;
       if (relative_die_offset == 0) {
@@ -2168,7 +2165,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_form_tls_address:
     case DW_OP_GNU_push_tls_address: {
       if (stack.size() < 1) {
-        if (op == DW_OP_form_tls_address)
+        if (opcode == DW_OP_form_tls_address)
           return llvm::createStringError(
               "DW_OP_form_tls_address needs an argument");
         else
@@ -2208,7 +2205,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (!dwarf_cu)
         return llvm::createStringError("DW_OP_GNU_addr_index found without a "
                                        "compile unit being specified");
-      uint64_t index = opcodes.GetULEB128(&offset);
+      uint64_t index = op->getRawOperand(0);
       lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index);
       stack.push_back(Scalar(value));
       if (target &&
@@ -2233,31 +2230,55 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return llvm::createStringError("DW_OP_GNU_const_index found without a "
                                        "compile unit being specified");
       }
-      uint64_t index = opcodes.GetULEB128(&offset);
+      uint64_t index = op->getRawOperand(0);
       lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSectio...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/190556


More information about the llvm-commits mailing list