labath created this revision.
labath added reviewers: vsk, dblaikie.
Herald added a project: LLDB.

The code changes are very straight-forward -- just handle both DW_AT_GNU
and DW_AT_call versions of all tags and attributes. There is just one
small gotcha: in the GNU version, DW_AT_low_pc was used both for the
"return pc" and the "call pc" values, depending on whether the tag was
describing a tail call, while the official scheme uses different
attributes for the two things.

Depends on D80518 <https://reviews.llvm.org/D80518>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80519

Files:
  lldb/source/Expression/DWARFExpression.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  
lldb/test/API/functionalities/param_entry_vals/basic_entry_values/TestBasicEntryValues.py
  lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp

Index: lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
===================================================================
--- lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
+++ lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
@@ -18,8 +18,10 @@
   use<int &>(dummy);
 
   ++global;
-  //% self.filecheck("image lookup -v -a $pc", "main.cpp", "-check-prefix=FUNC1-DESC")
-  // FUNC1-DESC: name = "sink", type = "int &", location = DW_OP_entry_value
+  //% prefix = "FUNC1-GNU" if "GNU" in self.name else "FUNC1-V5"
+  //% self.filecheck("image lookup -v -a $pc", "main.cpp", "-check-prefix="+prefix)
+  // FUNC1-GNU: name = "sink", type = "int &", location = DW_OP_GNU_entry_value
+  // FUNC1-V5: name = "sink", type = "int &", location = DW_OP_entry_value
 }
 
 __attribute__((noinline)) void func2(int &sink, int x) {
Index: lldb/test/API/functionalities/param_entry_vals/basic_entry_values/TestBasicEntryValues.py
===================================================================
--- lldb/test/API/functionalities/param_entry_vals/basic_entry_values/TestBasicEntryValues.py
+++ lldb/test/API/functionalities/param_entry_vals/basic_entry_values/TestBasicEntryValues.py
@@ -11,3 +11,7 @@
 lldbinline.MakeInlineTest(__file__, globals(), decorators=decorators,
         name="BasicEntryValues_V5",
         build_dict=dict(CXXFLAGS_EXTRAS="-O2 -glldb"))
+
+lldbinline.MakeInlineTest(__file__, globals(), decorators=decorators,
+        name="BasicEntryValues_GNU",
+        build_dict=dict(CXXFLAGS_EXTRAS="-O2 -ggdb"))
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3601,7 +3601,8 @@
   CallSiteParameterArray parameters;
   for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid();
        child = child.GetSibling()) {
-    if (child.Tag() != DW_TAG_call_site_parameter)
+    if (child.Tag() != DW_TAG_call_site_parameter &&
+        child.Tag() != DW_TAG_GNU_call_site_parameter)
       continue;
 
     llvm::Optional<DWARFExpression> LocationInCallee;
@@ -3631,7 +3632,7 @@
       dw_attr_t attr = attributes.AttributeAtIndex(i);
       if (attr == DW_AT_location)
         LocationInCallee = parse_simple_location(i);
-      if (attr == DW_AT_call_value)
+      if (attr == DW_AT_call_value || attr == DW_AT_GNU_call_site_value)
         LocationInCaller = parse_simple_location(i);
     }
 
@@ -3648,8 +3649,9 @@
 SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
   // Check if the function has a supported call site-related attribute.
   // TODO: In the future it may be worthwhile to support call_all_source_calls.
-  uint64_t has_call_edges =
-      function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0);
+  bool has_call_edges =
+      function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0) ||
+      function_die.GetAttributeValueAsUnsigned(DW_AT_GNU_all_call_sites, 0);
   if (!has_call_edges)
     return {};
 
@@ -3665,13 +3667,15 @@
   std::vector<std::unique_ptr<CallEdge>> call_edges;
   for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
        child = child.GetSibling()) {
-    if (child.Tag() != DW_TAG_call_site)
+    if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site)
       continue;
 
     llvm::Optional<DWARFDIE> call_origin;
     llvm::Optional<DWARFExpression> call_target;
     addr_t return_pc = LLDB_INVALID_ADDRESS;
     addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
+    addr_t low_pc = LLDB_INVALID_ADDRESS;
+    bool tail_call = false;
 
     DWARFAttributes attributes;
     const size_t num_attributes = child.GetAttributes(attributes);
@@ -3684,8 +3688,11 @@
 
       dw_attr_t attr = attributes.AttributeAtIndex(i);
 
+      if (attr == DW_AT_call_tail_call || attr == DW_AT_GNU_tail_call)
+        tail_call = form_value.Boolean();
+
       // Extract DW_AT_call_origin (the call target's DIE).
-      if (attr == DW_AT_call_origin) {
+      if (attr == DW_AT_call_origin || attr == DW_AT_abstract_origin) {
         call_origin = form_value.Reference();
         if (!call_origin->IsValid()) {
           LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
@@ -3694,6 +3701,9 @@
         }
       }
 
+      if (attr == DW_AT_low_pc)
+        low_pc = form_value.Address();
+
       // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
       // available. It should only ever be unavailable for tail call edges, in
       // which case use LLDB_INVALID_ADDRESS.
@@ -3708,7 +3718,7 @@
 
       // Extract DW_AT_call_target (the location of the address of the indirect
       // call).
-      if (attr == DW_AT_call_target) {
+      if (attr == DW_AT_call_target || attr == DW_AT_GNU_call_site_target) {
         if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
           LLDB_LOG(log,
                    "CollectCallEdges: AT_call_target does not have block form");
@@ -3723,6 +3733,15 @@
             child.GetCU());
       }
     }
+    // In DWARF v4 low_pc is either the address of the call instruction or the
+    // "return to" address, depending on whether the call is a tail call.
+    if (child.Tag() == DW_TAG_GNU_call_site) {
+      if (tail_call)
+        call_inst_pc = low_pc;
+      else
+        return_pc = low_pc;
+    }
+
     if (!call_origin && !call_target) {
       LLDB_LOG(log, "CollectCallEdges: call site without any call target");
       continue;
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -396,6 +396,7 @@
     return offset - data_offset;
   }
 
+  case DW_OP_GNU_entry_value:
   case DW_OP_entry_value: // 0xa3 ULEB128 size + variable-length block
   {
     uint64_t subexpr_len = data.GetULEB128(&offset);
@@ -2522,6 +2523,7 @@
       stack.push_back(Scalar(value));
     } break;
 
+    case DW_OP_GNU_entry_value:
     case DW_OP_entry_value: {
       if (!Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, opcodes, offset,
                                       error_ptr, log)) {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to