Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Cleanup/documentation for simgrid::mc::Frame
[simgrid.git] / src / mc / mc_dwarf.cpp
index b312366..d5afe09 100644 (file)
 #include <elfutils/libdw.h>
 
 #include <simgrid_config.h>
-#include <simgrid/util.hpp>
+#include "src/simgrid/util.hpp"
 #include <xbt/log.h>
 #include <xbt/sysdep.h>
 
-#include <simgrid/util.hpp>
+#include "src/mc/mc_object_info.h"
+#include "src/mc/mc_private.h"
+#include "src/mc/mc_dwarf.hpp"
 
-#include "mc_object_info.h"
-#include "mc_private.h"
-
-#include "mc/Process.hpp"
-#include "mc/ObjectInformation.hpp"
-#include "mc/Variable.hpp"
+#include "src/mc/Process.hpp"
+#include "src/mc/ObjectInformation.hpp"
+#include "src/mc/Variable.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
 
@@ -133,8 +132,7 @@ enum class FormClass {
   RangeListPtr
 };
 
-namespace {
-
+static
 TagClass classify_tag(int tag)
 {
   switch (tag) {
@@ -193,6 +191,7 @@ TagClass classify_tag(int tag)
  *  \param form The form (values taken from the DWARF spec)
  *  \return An internal representation for the corresponding class
  * */
+static
 FormClass classify_form(int form)
 {
   switch (form) {
@@ -232,18 +231,18 @@ FormClass classify_form(int form)
   }
 }
 
-}
-}
-}
-
 /** \brief Get the name of the tag of a given DIE
  *
  *  \param die DIE
  *  \return name of the tag of this DIE
  */
-static inline const char *MC_dwarf_die_tagname(Dwarf_Die * die)
+inline XBT_PRIVATE
+const char *tagname(Dwarf_Die * die)
 {
-  return MC_dwarf_tagname(dwarf_tag(die));
+  return simgrid::dwarf::tagname(dwarf_tag(die));
+}
+
+}
 }
 
 // ***** Attributes
@@ -351,7 +350,8 @@ static bool MC_dwarf_attr_flag(Dwarf_Die * die, int attribute, bool integrate)
 
   bool result;
   if (dwarf_formflag(&attr, &result))
-    xbt_die("Unexpected form for attribute %s", MC_dwarf_attrname(attribute));
+    xbt_die("Unexpected form for attribute %s",
+      simgrid::dwarf::attrname(attribute));
   return result;
 }
 
@@ -407,7 +407,7 @@ static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die,
   xbt_assert(dwarf_tag(die) == DW_TAG_enumeration_type
              || dwarf_tag(die) == DW_TAG_subrange_type,
              "MC_dwarf_subrange_element_count called with DIE of type %s",
-             MC_dwarf_die_tagname(die));
+             simgrid::dwarf::tagname(die));
 
   // Use DW_TAG_count if present:
   if (dwarf_hasattr_integrate(die, DW_AT_count))
@@ -442,7 +442,7 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit)
 {
   xbt_assert(dwarf_tag(die) == DW_TAG_array_type,
              "MC_dwarf_array_element_count called with DIE of type %s",
-             MC_dwarf_die_tagname(die));
+             simgrid::dwarf::tagname(die));
 
   int result = 1;
   Dwarf_Die child;
@@ -515,7 +515,7 @@ static void MC_dwarf_fill_member_location(
             ("Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%"
              PRIx64 ">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name),
              (uint64_t) type->id, type->name.c_str());
-      member->location_expression = simgrid::mc::DwarfExpression(expr, expr+len);
+      member->location_expression = simgrid::dwarf::DwarfExpression(expr, expr+len);
       break;
     }
   case simgrid::dwarf::FormClass::Constant:
@@ -751,7 +751,7 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
         uintptr_t base = (uintptr_t) info->base_address();
         variable->address = (void *) (base + offset);
       } else {
-        simgrid::mc::LocationListEntry entry;
+        simgrid::dwarf::LocationListEntry entry;
         entry.expression = {expr, expr + len};
         variable->location_list = { std::move(entry) };
       }
@@ -762,9 +762,8 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
   case simgrid::dwarf::FormClass::LocListPtr:
   case simgrid::dwarf::FormClass::Constant:
     // Reference to location list:
-    mc_dwarf_location_list_init(
-      &variable->location_list, info, die,
-      &attr_location);
+    variable->location_list = simgrid::dwarf::location_list(
+      *info, attr_location);
     break;
 
   default:
@@ -845,19 +844,16 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
     xbt_assert(parent_frame, "No parent scope for this scope");
 
   simgrid::mc::Frame frame;
-
   frame.tag = tag;
   frame.id = dwarf_dieoffset(die);
   frame.object_info = info;
 
   if (klass == simgrid::dwarf::TagClass::Subprogram) {
     const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
-    if(ns)
+    if (ns)
       frame.name  = std::string(ns) + "::" + name;
     else if (name)
       frame.name = name;
-    else
-      frame.name.clear();
   }
 
   frame.abstract_origin_id =
@@ -866,11 +862,11 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
   // This is the base address for DWARF addresses.
   // Relocated addresses are offset from this base address.
   // See DWARF4 spec 7.5
-  void *base = info->base_address();
+  std::uint64_t base = (std::uint64_t) info->base_address();
 
   // TODO, support DW_AT_ranges
   uint64_t low_pc = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc);
-  frame.low_pc = low_pc ? ((char *) base) + low_pc : 0;
+  frame.range.begin() = low_pc ? (std::uint64_t) base + low_pc : 0;
   if (low_pc) {
     // DW_AT_high_pc:
     Dwarf_Attribute attr;
@@ -888,14 +884,14 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
 
       if (dwarf_formsdata(&attr, &offset) != 0)
         xbt_die("Could not read constant");
-      frame.high_pc = (void *) ((char *) frame.low_pc + offset);
+      frame.range.end() = frame.range.begin() + offset;
       break;
 
       // DW_AT_high_pc is a relocatable address:
     case simgrid::dwarf::FormClass::Address:
       if (dwarf_formaddr(&attr, &high_pc) != 0)
         xbt_die("Could not read address");
-      frame.high_pc = ((char *) base) + high_pc;
+      frame.range.begin() = base + high_pc;
       break;
 
     default:
@@ -907,20 +903,21 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
   if (klass == simgrid::dwarf::TagClass::Subprogram) {
     Dwarf_Attribute attr_frame_base;
     if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base))
-      mc_dwarf_location_list_init(&frame.frame_base, info, die,
-                                  &attr_frame_base);
+      frame.frame_base_location = simgrid::dwarf::location_list(*info,
+                                  attr_frame_base);
   }
 
   // Handle children:
   MC_dwarf_handle_children(info, die, unit, &frame, ns);
 
-  // Someone needs this to be sorted but who?
+  // We sort them in order to have an (somewhat) efficient by name
+  // lookup:
   std::sort(frame.variables.begin(), frame.variables.end(),
     MC_compare_variable);
 
   // Register it:
   if (klass == simgrid::dwarf::TagClass::Subprogram)
-    info->subprograms[frame.id] = frame;
+    info->subprograms[frame.id] = std::move(frame);
   else if (klass == simgrid::dwarf::TagClass::Scope)
     parent_frame->scopes.push_back(std::move(frame));
 }
@@ -986,11 +983,25 @@ static void MC_dwarf_handle_die(simgrid::mc::ObjectInformation* info, Dwarf_Die
   }
 }
 
+static
+Elf64_Half MC_dwarf_elf_type(Dwarf* dwarf)
+{
+  Elf* elf = dwarf_getelf(dwarf);
+  Elf64_Ehdr* ehdr64 = elf64_getehdr(elf);
+  if (ehdr64)
+    return ehdr64->e_type;
+  Elf32_Ehdr* ehdr32 = elf32_getehdr(elf);
+  if (ehdr32)
+    return ehdr32->e_type;
+  xbt_die("Could not get ELF heeader");
+}
+
 /** \brief Populate the debugging informations of the given ELF object
  *
  *  Read the DWARf information of the EFFL object and populate the
  *  lists of types, variables, functions.
  */
+static
 void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
 {
   int fd = open(info->file_name.c_str(), O_RDONLY);
@@ -1002,6 +1013,11 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
       "Your program and its dependencies must have debugging information.\n"
       "You might want to recompile with -g or install the suitable debugging package.\n",
       info->file_name.c_str());
+
+  Elf64_Half elf_type = MC_dwarf_elf_type(dwarf);
+  if (elf_type == ET_EXEC)
+    info->flags |= simgrid::mc::ObjectInformation::Executable;
+
   // For each compilation unit:
   Dwarf_Off offset = 0;
   Dwarf_Off next_offset = 0;
@@ -1037,10 +1053,10 @@ static void MC_make_functions_index(simgrid::mc::ObjectInformation* info)
   info->functions_index.clear();
 
   for (auto& e : info->subprograms) {
-    if (e.second.low_pc == nullptr)
+    if (e.second.range.begin() == 0)
       continue;
     simgrid::mc::FunctionIndexEntry entry;
-    entry.low_pc = e.second.low_pc;
+    entry.low_pc = (void*) e.second.range.begin();
     entry.function = &e.second;
     info->functions_index.push_back(entry);
   }
@@ -1131,12 +1147,10 @@ static void MC_post_process_types(simgrid::mc::ObjectInformation* info)
 
 /** \brief Finds informations about a given shared object/executable */
 std::shared_ptr<simgrid::mc::ObjectInformation> MC_find_object_info(
-  std::vector<simgrid::mc::VmMap> const& maps, const char *name, int executable)
+  std::vector<simgrid::xbt::VmMap> const& maps, const char *name)
 {
   std::shared_ptr<simgrid::mc::ObjectInformation> result =
     std::make_shared<simgrid::mc::ObjectInformation>();
-  if (executable)
-    result->flags |= simgrid::mc::ObjectInformation::Executable;
   result->file_name = name;
   MC_find_object_address(maps, result.get());
   MC_dwarf_get_variables(result.get());
@@ -1178,3 +1192,80 @@ void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::Obj
 
   }
 }
+
+namespace simgrid {
+namespace dwarf {
+
+/** Convert a DWARF register into a libunwind register
+ *
+ *  DWARF and libunwind does not use the same convention for numbering the
+ *  registers on some architectures. The function makes the necessary
+ *  convertion.
+ */
+int dwarf_register_to_libunwind(int dwarf_register)
+{
+#if defined(__x86_64__)
+  // It seems for this arch, DWARF and libunwind agree in the numbering:
+  return dwarf_register;
+#elif defined(__i386__)
+  // Could't find the authoritative source of information for this.
+  // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
+  switch (dwarf_register) {
+  case 0:
+    return UNW_X86_EAX;
+  case 1:
+    return UNW_X86_ECX;
+  case 2:
+    return UNW_X86_EDX;
+  case 3:
+    return UNW_X86_EBX;
+  case 4:
+    return UNW_X86_ESP;
+  case 5:
+    return UNW_X86_EBP;
+  case 6:
+    return UNW_X86_ESI;
+  case 7:
+    return UNW_X86_EDI;
+  case 8:
+    return UNW_X86_EIP;
+  case 9:
+    return UNW_X86_EFLAGS;
+  case 10:
+    return UNW_X86_CS;
+  case 11:
+    return UNW_X86_SS;
+  case 12:
+    return UNW_X86_DS;
+  case 13:
+    return UNW_X86_ES;
+  case 14:
+    return UNW_X86_FS;
+  case 15:
+    return UNW_X86_GS;
+  case 16:
+    return UNW_X86_ST0;
+  case 17:
+    return UNW_X86_ST1;
+  case 18:
+    return UNW_X86_ST2;
+  case 19:
+    return UNW_X86_ST3;
+  case 20:
+    return UNW_X86_ST4;
+  case 21:
+    return UNW_X86_ST5;
+  case 22:
+    return UNW_X86_ST6;
+  case 23:
+    return UNW_X86_ST7;
+  default:
+    xbt_die("Bad/unknown register number.");
+  }
+#else
+#error This architecture is not supported yet for DWARF expression evaluation.
+#endif
+}
+
+}
+}