Chirag created this revision.
Chirag added a project: LLDB.
Herald added subscribers: lldb-commits, aprantl.
Chirag added a reviewer: jingham.

dwarf expression DW_OP_call2/DW_OP_call4 performs dwarf procedure calls during 
evaluation of a dwarf expression or location description. The 2-byte unsigned 
offset for DW_OP_call2 (4-byte unsigned offset for DW_OP_call4) is a die entry 
in the current compilation unit. These operations transfer control of DWARF 
expression evaluation to the DW_AT_location attribute of the referenced die 
entry. If there is no such attribute present then there is no effect. the 
evaluation stack is shared between caller/callee and callee may add to/remove 
from the value on stack.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D61587

Files:
  include/lldb/Expression/DWARFExpression.h
  source/Expression/DWARFExpression.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Target/RegisterContext.cpp
  unittests/Expression/DWARFExpressionTest.cpp

Index: unittests/Expression/DWARFExpressionTest.cpp
===================================================================
--- unittests/Expression/DWARFExpressionTest.cpp
+++ unittests/Expression/DWARFExpressionTest.cpp
@@ -22,11 +22,12 @@
 
   Value result;
   Status status;
+  std::vector<Value> stack;
   if (!DWARFExpression::Evaluate(
           /*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, /*opcode_ctx*/ nullptr,
           extractor, /*dwarf_cu*/ nullptr, /*offset*/ 0, expr.size(),
           lldb::eRegisterKindLLDB, /*initial_value_ptr*/ nullptr,
-          /*object_address_ptr*/ nullptr, result, &status))
+          /*object_address_ptr*/ nullptr, stack, result, &status))
     return status.ToError();
 
   return result.GetScalar();
Index: source/Target/RegisterContext.cpp
===================================================================
--- source/Target/RegisterContext.cpp
+++ source/Target/RegisterContext.cpp
@@ -87,9 +87,10 @@
   Value result;
   Status error;
   const lldb::offset_t offset = 0;
+  std::vector<Value> stack;
   if (dwarf_expr.Evaluate(&exe_ctx, this, opcode_ctx, dwarf_data, nullptr,
                           offset, dwarf_opcode_len, eRegisterKindDWARF, nullptr,
-                          nullptr, result, &error)) {
+                          nullptr, stack, result, &error)) {
     expr_result = result.GetScalar().SInt(-1);
     switch (expr_result) {
     case 0:
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2780,12 +2780,13 @@
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
+                std::vector<Value> stack;
                 if (DWARFExpression::Evaluate(
                         nullptr, // ExecutionContext *
                         nullptr, // RegisterContext *
                         module_sp, debug_info_data, die.GetCU(), block_offset,
                         block_length, eRegisterKindDWARF, &initialValue,
-                        nullptr, memberOffset, nullptr)) {
+                        nullptr, stack, memberOffset, nullptr)) {
                   member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
                 }
               } else {
@@ -3229,6 +3230,7 @@
                 Value initialValue(0);
                 Value memberOffset(0);
                 const DWARFDataExtractor &debug_info_data = die.GetData();
+                std::vector<Value> stack;
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
@@ -3236,7 +3238,8 @@
                                               debug_info_data, die.GetCU(),
                                               block_offset, block_length,
                                               eRegisterKindDWARF, &initialValue,
-                                              nullptr, memberOffset, nullptr)) {
+                                              nullptr, stack, memberOffset,
+                                              nullptr)) {
                   member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
                 }
               } else {
Index: source/Expression/DWARFExpression.cpp
===================================================================
--- source/Expression/DWARFExpression.cpp
+++ source/Expression/DWARFExpression.cpp
@@ -1248,6 +1248,7 @@
                                const Value *object_address_ptr, Value &result,
                                Status *error_ptr) const {
   ModuleSP module_sp = m_module_wp.lock();
+  std::vector<Value> stack;
 
   if (IsLocationList()) {
     lldb::offset_t offset = 0;
@@ -1293,7 +1294,7 @@
         if (length > 0 && lo_pc <= pc && pc < hi_pc) {
           return DWARFExpression::Evaluate(
               exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, offset, length,
-              m_reg_kind, initial_value_ptr, object_address_ptr, result,
+              m_reg_kind, initial_value_ptr, object_address_ptr, stack, result,
               error_ptr);
         }
         offset += length;
@@ -1307,7 +1308,8 @@
   // Not a location list, just a single expression.
   return DWARFExpression::Evaluate(
       exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, m_data.GetByteSize(),
-      m_reg_kind, initial_value_ptr, object_address_ptr, result, error_ptr);
+      m_reg_kind, initial_value_ptr, object_address_ptr, stack, result,
+      error_ptr);
 }
 
 bool DWARFExpression::Evaluate(
@@ -1316,7 +1318,7 @@
     DWARFUnit *dwarf_cu, const lldb::offset_t opcodes_offset,
     const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind,
     const Value *initial_value_ptr, const Value *object_address_ptr,
-    Value &result, Status *error_ptr) {
+    std::vector<Value> &stack, Value &result, Status *error_ptr) {
 
   if (opcodes_length == 0) {
     if (error_ptr)
@@ -1324,7 +1326,6 @@
           "no location, value may have been optimized out");
     return false;
   }
-  std::vector<Value> stack;
 
   Process *process = NULL;
   StackFrame *frame = NULL;
@@ -2690,10 +2691,38 @@
     // may be used as parameters by the called expression and values left on
     // the stack by the called expression may be used as return values by prior
     // agreement between the calling and called expressions.
-    case DW_OP_call2:
-      if (error_ptr)
-        error_ptr->SetErrorString("Unimplemented opcode DW_OP_call2.");
-      return false;
+    case DW_OP_call2: {
+      dw_offset_t die_ref_offset = opcodes.GetU16(&offset);
+      const DWARFDIE ref_die = dwarf_cu->GetDIE(die_ref_offset);
+      if (!ref_die.IsValid()) {
+        if (error_ptr)
+          error_ptr->SetErrorString("opcode DW_OP_call2 reference not found");
+        return false;
+      }
+
+      DWARFAttributes attributes;
+      const size_t num_attrib = ref_die.GetAttributes(attributes);
+      if (num_attrib == 0)
+        break;
+
+      const uint32_t attr_index = attributes.FindAttributeIndex(DW_AT_location);
+      if (attr_index == UINT32_MAX)
+        break;
+
+      DWARFFormValue form_value;
+      attributes.ExtractFormValueAtIndex(attr_index, form_value);
+
+      const DWARFDataExtractor &ref_debug_info_data = ref_die.GetData();
+      uint32_t location_offset =
+          form_value.BlockData() - ref_debug_info_data.GetDataStart();
+      uint32_t location_length = form_value.Unsigned();
+      Value memberOffset(0);
+      Evaluate(nullptr, nullptr, module_sp, ref_debug_info_data,
+               dwarf_cu, location_offset, location_length,
+               eRegisterKindDWARF, nullptr, nullptr, stack, memberOffset,
+               nullptr);
+    } break;
+
     // OPCODE: DW_OP_call4
     // OPERANDS: 1
     //      uint32_t compile unit relative offset of a DIE
@@ -2713,10 +2742,37 @@
     // may be used as parameters by the called expression and values left on
     // the stack by the called expression may be used as return values by prior
     // agreement between the calling and called expressions.
-    case DW_OP_call4:
-      if (error_ptr)
-        error_ptr->SetErrorString("Unimplemented opcode DW_OP_call4.");
-      return false;
+    case DW_OP_call4: {
+      dw_offset_t die_ref_offset = opcodes.GetU32(&offset);
+      const DWARFDIE ref_die = dwarf_cu->GetDIE(die_ref_offset);
+      if (!ref_die.IsValid()) {
+        if (error_ptr)
+          error_ptr->SetErrorString("opcode DW_OP_call4 reference not found");
+        return false;
+      }
+
+      DWARFAttributes attributes;
+      const size_t num_attrib = ref_die.GetAttributes(attributes);
+      if (num_attrib == 0)
+        break;
+
+      const uint32_t attr_index = attributes.FindAttributeIndex(DW_AT_location);
+      if (attr_index == UINT32_MAX)
+        break;
+
+      DWARFFormValue form_value;
+      attributes.ExtractFormValueAtIndex(attr_index, form_value);
+
+      const DWARFDataExtractor &ref_debug_info_data = ref_die.GetData();
+      uint32_t location_offset =
+          form_value.BlockData() - ref_debug_info_data.GetDataStart();
+      uint32_t location_length = form_value.Unsigned();
+      Value memberOffset(0);
+      Evaluate(nullptr, nullptr, module_sp, ref_debug_info_data,
+               dwarf_cu, location_offset, location_length,
+               eRegisterKindDWARF, nullptr, nullptr, stack, memberOffset,
+               nullptr);
+    } break;
 
     // OPCODE: DW_OP_stack_value
     // OPERANDS: None
Index: include/lldb/Expression/DWARFExpression.h
===================================================================
--- include/lldb/Expression/DWARFExpression.h
+++ include/lldb/Expression/DWARFExpression.h
@@ -285,6 +285,10 @@
   ///     A value to put on top of the interpreter stack before evaluating
   ///     the expression, if the expression is parametrized.  Can be NULL.
   ///
+  /// \param[in] stack
+  ///     interpreter stack for evaluation of dwarf expression. It is shared
+  ///     between calls in case of adding/removing entries from stack.
+  ///
   /// \param[in] result
   ///     A value into which the result of evaluating the expression is
   ///     to be placed.
@@ -301,7 +305,9 @@
                        const lldb::offset_t length,
                        const lldb::RegisterKind reg_set,
                        const Value *initial_value_ptr,
-                       const Value *object_address_ptr, Value &result,
+                       const Value *object_address_ptr,
+                       std::vector<Value> &stack,
+                       Value &result,
                        Status *error_ptr);
 
   bool GetExpressionData(DataExtractor &data) const {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to