Chirag updated this revision to Diff 198439.
Chirag added a comment.

Fixed as per comments. passed proper execution/register context. for the time 
being DW_OP_piece is not allowed in call op. Working on testcase.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61587/new/

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))
+          lldb::eRegisterKindLLDB, /*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)) {
+                          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
@@ -2774,18 +2774,20 @@
               break;
             case DW_AT_data_member_location:
               if (form_value.BlockData()) {
-                Value initialValue(0);
                 Value memberOffset(0);
                 const DWARFDataExtractor &debug_info_data = die.GetData();
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
+                std::vector<Value> stack;
+                stack.push_back(Value(0));
+
                 if (DWARFExpression::Evaluate(
                         nullptr, // ExecutionContext *
                         nullptr, // RegisterContext *
                         module_sp, debug_info_data, die.GetCU(), block_offset,
-                        block_length, eRegisterKindDWARF, &initialValue,
-                        nullptr, memberOffset, nullptr)) {
+                        block_length, eRegisterKindDWARF, nullptr, stack,
+                        memberOffset, nullptr)) {
                   member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
                 }
               } else {
@@ -3229,14 +3231,17 @@
                 Value initialValue(0);
                 Value memberOffset(0);
                 const DWARFDataExtractor &debug_info_data = die.GetData();
+                std::vector<Value> stack;
+                stack.push_back(Value(0));
+
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
                 if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp,
                                               debug_info_data, die.GetCU(),
                                               block_offset, block_length,
-                                              eRegisterKindDWARF, &initialValue,
-                                              nullptr, memberOffset, nullptr)) {
+                                              eRegisterKindDWARF, 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,9 @@
                                const Value *object_address_ptr, Value &result,
                                Status *error_ptr) const {
   ModuleSP module_sp = m_module_wp.lock();
+  std::vector<Value> stack;
+  if (initial_value_ptr)
+    stack.push_back(*initial_value_ptr);
 
   if (IsLocationList()) {
     lldb::offset_t offset = 0;
@@ -1293,8 +1296,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,
-              error_ptr);
+              m_reg_kind, object_address_ptr, stack, result, error_ptr);
         }
         offset += length;
       }
@@ -1307,7 +1309,7 @@
   // 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, object_address_ptr, stack, result, error_ptr);
 }
 
 bool DWARFExpression::Evaluate(
@@ -1315,8 +1317,8 @@
     lldb::ModuleSP module_sp, const DataExtractor &opcodes,
     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) {
+    const Value *object_address_ptr, std::vector<Value> &stack, Value &result,
+    Status *error_ptr, bool expression_call) {
 
   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;
@@ -1336,9 +1337,6 @@
   if (reg_ctx == NULL && frame)
     reg_ctx = frame->GetRegisterContext().get();
 
-  if (initial_value_ptr)
-    stack.push_back(*initial_value_ptr);
-
   lldb::offset_t offset = opcodes_offset;
   const lldb::offset_t end_offset = opcodes_offset + opcodes_length;
   Value tmp;
@@ -2478,6 +2476,13 @@
     // provides a way of describing how large a part of a variable a particular
     // DWARF expression refers to.
     case DW_OP_piece: {
+      if (expression_call) {
+        if (error_ptr)
+          error_ptr->SetErrorStringWithFormat(
+              "dwarf expression call with DW_OP_piece not supported.");
+        return false;
+      }
+
       const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
 
       if (piece_byte_size > 0) {
@@ -2690,10 +2695,19 @@
     // 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) + dwarf_cu->GetOffset();
+      auto 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;
+      }
+      EvaluateCall(exe_ctx, reg_ctx, module_sp, dwarf_cu, &ref_die, reg_kind,
+                   object_address_ptr, stack, error_ptr);
+    } break;
+
     // OPCODE: DW_OP_call4
     // OPERANDS: 1
     //      uint32_t compile unit relative offset of a DIE
@@ -2713,10 +2727,18 @@
     // 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) + dwarf_cu->GetOffset();
+      auto 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;
+      }
+      EvaluateCall(exe_ctx, reg_ctx, module_sp, dwarf_cu, &ref_die, reg_kind,
+                   object_address_ptr, stack, error_ptr);
+    } break;
 
     // OPCODE: DW_OP_stack_value
     // OPERANDS: None
@@ -2896,6 +2918,40 @@
   return true; // Return true on success
 }
 
+bool DWARFExpression::EvaluateCall(ExecutionContext *exe_ctx,
+                                   RegisterContext *reg_ctx,
+                                   ModuleSP module_sp,
+                                   DWARFUnit *dwarf_cu,
+                                   DWARFDIE *ref_die,
+                                   const RegisterKind reg_kind,
+                                   const Value *object_address_ptr,
+                                   std::vector<Value> &stack,
+                                   Status *error_ptr) {
+  if (!ref_die)
+    return false;
+
+  DWARFAttributes attributes;
+  const size_t num_attrib = ref_die->GetAttributes(attributes);
+  if (num_attrib == 0)
+    return false;
+
+  const uint32_t attr_index = attributes.FindAttributeIndex(DW_AT_location);
+  if (attr_index == UINT32_MAX)
+    return false;
+
+  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 result(0);
+  return Evaluate(exe_ctx, reg_ctx, module_sp, ref_debug_info_data, dwarf_cu,
+                  location_offset, location_length, reg_kind,
+                  object_address_ptr, stack, result, error_ptr, true);
+}
+
 size_t DWARFExpression::LocationListSize(const DWARFUnit *dwarf_cu,
                                          const DataExtractor &debug_loc_data,
                                          lldb::offset_t offset) {
Index: include/lldb/Expression/DWARFExpression.h
===================================================================
--- include/lldb/Expression/DWARFExpression.h
+++ include/lldb/Expression/DWARFExpression.h
@@ -18,6 +18,7 @@
 #include <functional>
 
 class DWARFUnit;
+class DWARFDIE;
 
 namespace lldb_private {
 
@@ -281,9 +282,9 @@
   /// \param[in] reg_set
   ///     The call-frame-info style register kind.
   ///
-  /// \param[in] initial_value_ptr
-  ///     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
@@ -300,9 +301,15 @@
                        DWARFUnit *dwarf_cu, const lldb::offset_t offset,
                        const lldb::offset_t length,
                        const lldb::RegisterKind reg_set,
-                       const Value *initial_value_ptr,
-                       const Value *object_address_ptr, Value &result,
-                       Status *error_ptr);
+                       const Value *object_address_ptr,
+                       std::vector<Value> &stack, Value &result,
+                       Status *error_ptr, bool expression_call = false);
+
+  static bool EvaluateCall(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
+                           lldb::ModuleSP module_sp, DWARFUnit *dwarf_cu,
+                           DWARFDIE *ref_die, const lldb::RegisterKind reg_set,
+                           const Value *object_address_ptr,
+                           std::vector<Value> &stack, Status *error_ptr);
 
   bool GetExpressionData(DataExtractor &data) const {
     data = m_data;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to