Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] OOify DWARF stack/evaluation expression
[simgrid.git] / src / mc / mc_dwarf.cpp
index 1ee412e..9d30fcf 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "mc_object_info.h"
 #include "mc_private.h"
+#include "mc_dwarf.hpp"
 
 #include "mc/Process.hpp"
 #include "mc/ObjectInformation.hpp"
@@ -117,8 +118,23 @@ enum class TagClass {
   Namespace
 };
 
-namespace {
+/*** Class of forms defined in the DWARF standard */
+enum class FormClass {
+  Unknown,
+  Address,   // Location in the program's address space
+  Block,     // Arbitrary block of bytes
+  Constant,
+  String,
+  Flag,      // Boolean value
+  Reference, // Reference to another DIE
+  ExprLoc,   // DWARF expression/location description
+  LinePtr,
+  LocListPtr,
+  MacPtr,
+  RangeListPtr
+};
 
+XBT_PRIVATE
 TagClass classify_tag(int tag)
 {
   switch (tag) {
@@ -170,23 +186,6 @@ TagClass classify_tag(int tag)
   }
 }
 
-}
-}
-}
-
-#define MC_DW_CLASS_UNKNOWN 0
-#define MC_DW_CLASS_ADDRESS 1   // Location in the address space of the program
-#define MC_DW_CLASS_BLOCK 2     // Arbitrary block of bytes
-#define MC_DW_CLASS_CONSTANT 3
-#define MC_DW_CLASS_STRING 3    // String
-#define MC_DW_CLASS_FLAG 4      // Boolean
-#define MC_DW_CLASS_REFERENCE 5 // Reference to another DIE
-#define MC_DW_CLASS_EXPRLOC 6   // DWARF expression/location description
-#define MC_DW_CLASS_LINEPTR 7
-#define MC_DW_CLASS_LOCLISTPTR 8
-#define MC_DW_CLASS_MACPTR 9
-#define MC_DW_CLASS_RANGELISTPTR 10
-
 /** \brief Find the DWARF data class for a given DWARF data form
  *
  *  This mapping is defined in the DWARF spec.
@@ -194,42 +193,43 @@ TagClass classify_tag(int tag)
  *  \param form The form (values taken from the DWARF spec)
  *  \return An internal representation for the corresponding class
  * */
-static int MC_dwarf_form_get_class(int form)
+XBT_PRIVATE
+FormClass classify_form(int form)
 {
   switch (form) {
   case DW_FORM_addr:
-    return MC_DW_CLASS_ADDRESS;
+    return FormClass::Address;
   case DW_FORM_block2:
   case DW_FORM_block4:
   case DW_FORM_block:
   case DW_FORM_block1:
-    return MC_DW_CLASS_BLOCK;
+    return FormClass::Block;
   case DW_FORM_data1:
   case DW_FORM_data2:
   case DW_FORM_data4:
   case DW_FORM_data8:
   case DW_FORM_udata:
   case DW_FORM_sdata:
-    return MC_DW_CLASS_CONSTANT;
+    return FormClass::Constant;
   case DW_FORM_string:
   case DW_FORM_strp:
-    return MC_DW_CLASS_STRING;
+    return FormClass::String;
   case DW_FORM_ref_addr:
   case DW_FORM_ref1:
   case DW_FORM_ref2:
   case DW_FORM_ref4:
   case DW_FORM_ref8:
   case DW_FORM_ref_udata:
-    return MC_DW_CLASS_REFERENCE;
+    return FormClass::Reference;
   case DW_FORM_flag:
   case DW_FORM_flag_present:
-    return MC_DW_CLASS_FLAG;
+    return FormClass::Flag;
   case DW_FORM_exprloc:
-    return MC_DW_CLASS_EXPRLOC;
+    return FormClass::ExprLoc;
     // TODO sec offset
     // TODO indirect
   default:
-    return MC_DW_CLASS_UNKNOWN;
+    return FormClass::Unknown;
   }
 }
 
@@ -238,9 +238,13 @@ static int MC_dwarf_form_get_class(int form)
  *  \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
@@ -348,7 +352,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;
 }
 
@@ -404,7 +409,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))
@@ -439,7 +444,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;
@@ -499,10 +504,10 @@ static void MC_dwarf_fill_member_location(
   Dwarf_Attribute attr;
   dwarf_attr_integrate(child, DW_AT_data_member_location, &attr);
   int form = dwarf_whatform(&attr);
-  int klass = MC_dwarf_form_get_class(form);
-  switch (klass) {
-  case MC_DW_CLASS_EXPRLOC:
-  case MC_DW_CLASS_BLOCK:
+  simgrid::dwarf::FormClass form_class = simgrid::dwarf::classify_form(form);
+  switch (form_class) {
+  case simgrid::dwarf::FormClass::ExprLoc:
+  case simgrid::dwarf::FormClass::Block:
     // Location expression:
     {
       Dwarf_Op *expr;
@@ -512,10 +517,10 @@ 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 MC_DW_CLASS_CONSTANT:
+  case simgrid::dwarf::FormClass::Constant:
     // Offset from the base address of the object:
     {
       Dwarf_Word offset;
@@ -527,15 +532,15 @@ static void MC_dwarf_fill_member_location(
                 (uint64_t) type->id, type->name.c_str());
       break;
     }
-  case MC_DW_CLASS_LOCLISTPTR:
+  case simgrid::dwarf::FormClass::LocListPtr:
     // Reference to a location list:
     // TODO
-  case MC_DW_CLASS_REFERENCE:
+  case simgrid::dwarf::FormClass::Reference:
     // It's supposed to be possible in DWARF2 but I couldn't find its semantic
     // in the spec.
   default:
     xbt_die("Can't handle form class (%i) / form 0x%x as DW_AT_member_location",
-            klass, form);
+            (int) form_class, form);
   }
 
 }
@@ -722,12 +727,14 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
   variable->type_id = MC_dwarf_at_type(die);
 
   int form = dwarf_whatform(&attr_location);
-  int klass =
-      form ==
-      DW_FORM_sec_offset ? MC_DW_CLASS_CONSTANT : MC_dwarf_form_get_class(form);
-  switch (klass) {
-  case MC_DW_CLASS_EXPRLOC:
-  case MC_DW_CLASS_BLOCK:
+  simgrid::dwarf::FormClass form_class;
+  if (form == DW_FORM_sec_offset)
+    form_class = simgrid::dwarf::FormClass::Constant;
+  else
+    form_class = simgrid::dwarf::classify_form(form);
+  switch (form_class) {
+  case simgrid::dwarf::FormClass::ExprLoc:
+  case simgrid::dwarf::FormClass::Block:
     // Location expression:
     {
       Dwarf_Op *expr;
@@ -753,17 +760,19 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
 
       break;
     }
-  case MC_DW_CLASS_LOCLISTPTR:
-  case MC_DW_CLASS_CONSTANT:
+
+  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);
     break;
+
   default:
     xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location "
             "in <%" PRIx64 ">%s",
-            form, form, klass, klass,
+            form, form, (int) form_class, (int) form_class,
             (uint64_t) variable->dwarf_offset,
             variable->name.c_str());
   }
@@ -773,20 +782,21 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
     Dwarf_Attribute attr;
     dwarf_attr(die, DW_AT_start_scope, &attr);
     int form = dwarf_whatform(&attr);
-    int klass = MC_dwarf_form_get_class(form);
-    switch (klass) {
-    case MC_DW_CLASS_CONSTANT:
+    simgrid::dwarf::FormClass form_class = simgrid::dwarf::classify_form(form);
+    switch (form_class) {
+    case simgrid::dwarf::FormClass::Constant:
       {
         Dwarf_Word value;
         variable->start_scope =
             dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
         break;
       }
-    case MC_DW_CLASS_RANGELISTPTR:     // TODO
+
+    case simgrid::dwarf::FormClass::RangeListPtr:     // TODO
     default:
       xbt_die
           ("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
-           form, klass, name == NULL ? "?" : name);
+           form, (int) form_class, name == NULL ? "?" : name);
     }
   }
 
@@ -873,10 +883,10 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
     Dwarf_Sword offset;
     Dwarf_Addr high_pc;
 
-    switch (MC_dwarf_form_get_class(dwarf_whatform(&attr))) {
+    switch (simgrid::dwarf::classify_form(dwarf_whatform(&attr))) {
 
       // DW_AT_high_pc if an offset from the low_pc:
-    case MC_DW_CLASS_CONSTANT:
+    case simgrid::dwarf::FormClass::Constant:
 
       if (dwarf_formsdata(&attr, &offset) != 0)
         xbt_die("Could not read constant");
@@ -884,7 +894,7 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
       break;
 
       // DW_AT_high_pc is a relocatable address:
-    case MC_DW_CLASS_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;
@@ -978,11 +988,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);
@@ -994,6 +1018,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;
@@ -1123,12 +1152,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::mc::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());