Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Use libdw for functions and local variables
authorGabriel Corona <gabriel.corona@loria.fr>
Mon, 13 Jan 2014 10:56:17 +0000 (11:56 +0100)
committerGabriel Corona <gabriel.corona@loria.fr>
Fri, 17 Jan 2014 10:02:31 +0000 (11:02 +0100)
src/mc/mc_checkpoint.c
src/mc/mc_dwarf.c
src/mc/mc_global.c
src/mc/mc_private.h

index 69312bc..2ffc60d 100644 (file)
@@ -250,6 +250,7 @@ mc_object_info_t MC_find_object_info(memory_map_t maps, char* name) {
   result->end_got_plt = NULL;
   MC_find_object_address(maps, result);
   MC_get_plt_section(result);
+  result->location_list = MC_dwarf_get_location_list(result->file_name);
   MC_dwarf_get_variables(result);
   return result;
 }
index d547d57..1a69987 100644 (file)
@@ -33,11 +33,13 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit);
 /** \brief Checks if a given tag is a (known) type tag.
  */
 static int MC_dwarf_tag_type(int tag);
-static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
+static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
 static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
-static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
-static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
+static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
+static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr,  size_t len);
 static Dwarf_Die* MC_dwarf_resolve_die(Dwarf_Die* die, int attribute);
+static char* MC_dwarf_at_type(Dwarf_Die* die);
 
 const char* MC_dwarf_attrname(int attr) {
   switch (attr) {
@@ -72,6 +74,72 @@ static const char* MC_dwarf_attr_string(Dwarf_Die* die, int attribute) {
   }
 }
 
+/** \brief Get the linkage name (DW_AT_linkage_name or DW_AR_MIPS_linkage_name)
+ *  of a DIE. */
+static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) {
+  const char* name = MC_dwarf_attr_string(die, DW_AT_linkage_name);
+  if (!name)
+    name = MC_dwarf_attr_string(die, DW_AT_MIPS_linkage_name);
+  return name;
+}
+
+static dw_location_t MC_dwarf_resolve_location_list(mc_object_info_t info, Dwarf_Word offset) {
+  char *key = bprintf("%ld", (long) offset);
+  dw_location_t loc = xbt_new0(s_dw_location_t, 1);
+  loc->type = e_dw_loclist;
+  loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(info->location_list, key);
+  if (!loc->location.loclist)
+    XBT_INFO("Key not found in loclist");
+  xbt_free(key);
+  return loc;
+}
+
+static dw_location_t MC_dwarf_get_location(Dwarf_Die* die, Dwarf_Attribute* attr, mc_object_info_t info) {
+  int form = dwarf_whatform(attr);
+  switch (form) {
+  case DW_FORM_exprloc:
+  case DW_FORM_block1: // not in the spec
+  case DW_FORM_block2:
+  case DW_FORM_block4:
+  case DW_FORM_block:
+    {
+      Dwarf_Op* expr;
+      size_t len;
+      if (dwarf_getlocation(attr, &expr, &len))
+        xbt_die("Could not read location expression");
+      return MC_dwarf_get_expression(expr, len);
+    }
+  case DW_FORM_sec_offset:
+  case DW_FORM_data2:
+  case DW_FORM_data4:
+  case DW_FORM_data8:
+    {
+      Dwarf_Word offset;
+      if (!dwarf_formudata(attr, &offset))
+        return MC_dwarf_resolve_location_list(info, offset);
+      else
+        xbt_die("Location list not found");
+    }
+    break;
+  default:
+    xbt_die("Unexpected form %i list for location in attribute %s of <%p>%s",
+      form,
+      MC_dwarf_attrname(attr->code),
+      (void*) dwarf_dieoffset(die),
+      MC_dwarf_attr_string(die, DW_AT_name));
+    return NULL;
+  }
+}
+
+static dw_location_t MC_dwarf_at_location(Dwarf_Die* die, int attribute, mc_object_info_t info) {
+  if(!dwarf_hasattr_integrate(die, attribute))
+    return xbt_new0(s_dw_location_t, 1);
+
+  Dwarf_Attribute attr;
+  dwarf_attr_integrate(die, attribute, &attr);
+  return MC_dwarf_get_location(die, &attr, info);
+}
+
 // Return a new string for the type (NULL if none)
 static char* MC_dwarf_at_type(Dwarf_Die* die) {
   Dwarf_Attribute attr;
@@ -87,8 +155,21 @@ static char* MC_dwarf_at_type(Dwarf_Die* die) {
   else return NULL;
 }
 
+static uint64_t MC_dwarf_attr_addr(Dwarf_Die* die, int attribute) {
+  Dwarf_Attribute attr;
+  if(dwarf_attr_integrate(die, attribute, &attr)==NULL)
+    return 0;
+  Dwarf_Addr value;
+  if (dwarf_formaddr(&attr, &value) == 0)
+    return (uint64_t) value;
+  else
+    return 0;
+}
+
 static uint64_t MC_dwarf_attr_uint(Dwarf_Die* die, int attribute, uint64_t default_value) {
   Dwarf_Attribute attr;
+  if (dwarf_attr_integrate(die, attribute, &attr)==NULL)
+    return default_value;
   Dwarf_Word value;
   return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr), &value) == 0 ? (uint64_t) value : default_value;
 }
@@ -296,6 +377,10 @@ static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Di
 
       MC_dwarf_fill_member_location(type, member, &child);
 
+      if (!member->dw_type_id) {
+        xbt_die("Missing type for member %s of <%p>%s", member->name, type->id, type->name);
+      }
+
       xbt_dynar_push(type->members, &member);
     }
   }
@@ -569,6 +654,7 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D
       break;
     }
   case DW_FORM_sec_offset: // type loclistptr
+  case DW_FORM_data4:
     xbt_die("Do not handle loclist locations yet");
     break;
   default:
@@ -579,31 +665,47 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D
   return variable;
 }
 
-static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
-  dw_variable_t variable = MC_die_to_variable(info, die, unit, NULL);
+static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
+  dw_variable_t variable = MC_die_to_variable(info, die, unit, frame);
   if(variable==NULL)
       return;
-  if(variable->global)
-    MC_dwarf_register_global_variable(info, variable);
-  else
-    xbt_die("Unexpected non global variable <%p>%s",
-      (void*) dwarf_dieoffset(die),
-      MC_dwarf_attr_string(die, DW_AT_name)
-      );
+  MC_dwarf_register_variable(info, frame, variable);
 }
 
+static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame) {
+  dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
+
+  frame->start = dwarf_dieoffset(die);
+
+  const char* name = MC_dwarf_at_linkage_name(die);
+  if (name==NULL)
+    name = MC_dwarf_attr_string(die, DW_AT_name);
+  frame->name = xbt_strdup(name);
 
-static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
+  // Variables are filled in the (recursive) call of MC_dwarf_handle_children:
+  frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+  frame->high_pc = (void*) MC_dwarf_attr_addr(die, DW_AT_high_pc);
+  frame->low_pc = (void*) MC_dwarf_attr_addr(die, DW_AT_low_pc);
+  frame->frame_base = MC_dwarf_at_location(die, DW_AT_frame_base, info);
+  frame->end = -1; // This one is now useless:
+
+  // Handle children:
+  MC_dwarf_handle_children(info, die, unit, frame);
+
+  // Register it:
+  xbt_dict_set(info->local_variables, frame->name, frame, NULL);
+}
+
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
   Dwarf_Die child;
   int res;
   for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
-    MC_dwarf_handle_die(info, &child, unit);
+    MC_dwarf_handle_die(info, &child, unit, frame);
   }
 }
 
-static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
+static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
   int tag = dwarf_tag(die);
-
   switch (tag) {
     case DW_TAG_array_type:
     case DW_TAG_class_type:
@@ -631,16 +733,16 @@ static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die
       break;
     case DW_TAG_inlined_subroutine:
     case DW_TAG_subprogram:
-      // Skip recursive processing
+      MC_dwarf_handle_subprogram_die(info, die, unit, frame);
       return;
+    // case DW_TAG_formal_parameter:
     case DW_TAG_variable:
-      if (MC_USE_LIBDW_NON_FUNCTION_VARIABLES)
-        MC_dwarf_handle_variable_die(info, die, unit);
+      MC_dwarf_handle_variable_die(info, die, unit, frame);
       break;
   }
 
   // Recursive processing of children DIE:
-  MC_dwarf_handle_children(info, die, unit);
+  MC_dwarf_handle_children(info, die, unit, frame);
 }
 
 void MC_dwarf_get_variables_libdw(mc_object_info_t info) {
@@ -659,7 +761,7 @@ void MC_dwarf_get_variables_libdw(mc_object_info_t info) {
   while (dwarf_nextcu (dwarf, offset, &next_offset, &length, NULL, NULL, NULL) == 0) {
     Dwarf_Die die;
     if(dwarf_offdie(dwarf, offset+length, &die)!=NULL) {
-      MC_dwarf_handle_die(info, &die, &die);
+      MC_dwarf_handle_die(info, &die, &die, NULL);
     }
     offset = next_offset;
   }
@@ -667,3 +769,4 @@ void MC_dwarf_get_variables_libdw(mc_object_info_t info) {
   dwarf_end(dwarf);
   close(fd);
 }
+
index 92766b3..e6cd34b 100644 (file)
@@ -171,7 +171,7 @@ void dw_variable_free(dw_variable_t v){
   }
 }
 
-static void dw_variable_free_voidp(void *t){
+void dw_variable_free_voidp(void *t){
   dw_variable_free((dw_variable_t) * (void **) t);
 }
 
@@ -198,6 +198,7 @@ void MC_free_object_info(mc_object_info_t* info) {
   xbt_dict_free(&(*info)->local_variables);
   xbt_dynar_free(&(*info)->global_variables);
   xbt_dict_free(&(*info)->types);
+  xbt_dict_free(&((*info)->location_list));
   xbt_free(info);
   info = NULL;
 }
@@ -345,7 +346,7 @@ static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr)
  *  @return A map from the offset in the list (in hexadecimal string)
  *          into a location list (dynar of dw_location_entry_t).
  */
-static xbt_dict_t MC_dwarf_get_location_list(const char *elf_file){
+xbt_dict_t MC_dwarf_get_location_list(const char *elf_file){
 
   char *command = bprintf("LANG=C objdump -Wo %s", elf_file);
 
@@ -532,15 +533,23 @@ static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *a
 
 }
 
+void MC_dwarf_get_variables_legacy(mc_object_info_t info);
+
 /** \brief Fill DWARf debug infomations (types, frames, variables ...). */
 void MC_dwarf_get_variables(mc_object_info_t info) {
-  if(MC_USE_LIBDW_TYPES)
+  if (MC_USE_LIBDW) {
     MC_dwarf_get_variables_libdw(info);
+    MC_post_process_types(info);
+  } else {
+    MC_dwarf_get_variables_legacy(info);
+  }
+}
+
+void MC_dwarf_get_variables_legacy(mc_object_info_t info) {
+
   mc_object_info_t result = info;
   const char *elf_file = info->file_name;
 
-  xbt_dict_t location_list = MC_dwarf_get_location_list(elf_file);
-
   char *command = bprintf("LANG=C objdump -Wi %s", elf_file);
   
   FILE *fp = popen(command, "r");
@@ -561,7 +570,7 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
   size_t n = 0;
   int global_variable = 0, parent = 0, new_frame = 0, new_variable = 1, size = 0, 
     is_pointer = 0, struct_decl = 0, member_end = 0,
-    enumeration_size = 0, subrange = 0, union_decl = 0, offset = 0, index = 0;
+    enumeration_size = 0, subrange = 0, union_decl = 0, offset = 0;
   
   xbt_dynar_t split = NULL, split2 = NULL;
 
@@ -664,7 +673,7 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
 
           if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
 
-            frame->frame_base = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *));
+            frame->frame_base = MC_dwarf_get_location(info->location_list, xbt_dynar_get_as(split, 3, char *));
              
           }else{
                 
@@ -720,11 +729,6 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
          the list of variables of the frame (local variable)
          or to the list of global variables (global variables). */
 
-      if (MC_USE_LIBDW_NON_FUNCTION_VARIABLES && parent==1) {
-        read = xbt_getline(&line, &n, fp);
-        continue;
-      }
-
       dw_variable_t var = NULL;
       
       parent_value = strdup(xbt_dynar_get_as(split, 0, char *));
@@ -790,7 +794,7 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
               location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
 
               if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
-                var->address.location = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *));
+                var->address.location = MC_dwarf_get_location(info->location_list, xbt_dynar_get_as(split, 3, char *));
               }else{
                 xbt_str_strip_spaces(line);
                 split2 = xbt_str_split(line, "(");
@@ -856,16 +860,12 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
 
       if(new_variable == 1){
         
+        var->global = global_variable;
+        var->type_origin = strdup(type_origin);
         if(!global_variable){
           variable_frame = xbt_dict_get_or_null(*local_variables, current_frame);
-          var->type_origin = strdup(type_origin);
-          var->global = 0;
-          index = MC_dwarf_get_variable_index(variable_frame->variables, var->name, NULL);
-          if(index != -1)
-            xbt_dynar_insert_at(variable_frame->variables, index, &var);
+          MC_dwarf_register_non_global_variable(info, variable_frame, var);
         }else{
-          var->type_origin = strdup(type_origin);
-          var->global = 1;
           MC_dwarf_register_global_variable(info, var);
         }
 
@@ -923,13 +923,13 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
       
       }
 
-    }else if(!MC_USE_LIBDW_TYPES&&(strcmp(node_type, "(DW_TAG_base_type)") == 0
+    }else if(strcmp(node_type, "(DW_TAG_base_type)") == 0
              || strcmp(node_type, "(DW_TAG_enumeration_type)") == 0
              || strcmp(node_type, "(DW_TAG_typedef)") == 0
              || strcmp(node_type, "(DW_TAG_const_type)") == 0
              || strcmp(node_type, "(DW_TAG_subroutine_type)") == 0
              || strcmp(node_type, "(DW_TAG_volatile_type)") == 0
-             || (is_pointer = !strcmp(node_type, "(DW_TAG_pointer_type)")))){
+             || (is_pointer = !strcmp(node_type, "(DW_TAG_pointer_type)"))){
 
       /* Create the and add it to the types dictionnary */
 
@@ -1282,11 +1282,8 @@ void MC_dwarf_get_variables(mc_object_info_t info) {
   xbt_dict_free(&subprograms_origin);
   xbt_free(line);
   xbt_free(command);
-  xbt_dict_free(&location_list);
 
   pclose(fp);
-
-  MC_post_process_types(info);
 }
 
 void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable) {
@@ -1296,6 +1293,23 @@ void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t vari
   // TODO, else ?
 }
 
+void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
+  xbt_assert(frame, "Frame is NULL");
+  int index = MC_dwarf_get_variable_index(frame->variables, variable->name, NULL);
+  if (index != -1)
+    xbt_dynar_insert_at(frame->variables, index, &variable);
+  // TODO, else ?
+}
+
+void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
+  if(variable->global)
+    MC_dwarf_register_global_variable(info, variable);
+  else if(frame==NULL)
+    xbt_die("No frame for this local variable");
+  else
+    MC_dwarf_register_non_global_variable(info, frame, variable);
+}
+
 static void MC_post_process_array_size(mc_object_info_t info, dw_type_t type) {
   xbt_assert(type->dw_type_id, "No base type for array <%p>%s", type->id, type->name);
   dw_type_t subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
index 5984272..0498fbb 100644 (file)
@@ -330,12 +330,14 @@ typedef struct s_mc_object_info {
   xbt_dict_t local_variables; // xbt_dict_t<frame_name, dw_frame_t>
   xbt_dynar_t global_variables; // xbt_dynar_t<dw_variable_t>
   xbt_dict_t types; // xbt_dict_t<origin as hexadecimal string, dw_type_t>
+  xbt_dict_t location_list; // Location list (probably temporary)
 } s_mc_object_info_t, *mc_object_info_t;
 
 mc_object_info_t MC_new_object_info(void);
 mc_object_info_t MC_find_object_info(memory_map_t maps, char* name);
 void MC_free_object_info(mc_object_info_t* p);
 
+xbt_dict_t MC_dwarf_get_location_list(const char *elf_file);
 void MC_dwarf_get_variables(mc_object_info_t info);
 void MC_dwarf_get_variables_libdw(mc_object_info_t info);
 const char* MC_dwarf_attrname(int attr);
@@ -417,8 +419,6 @@ typedef struct s_dw_variable{
   }address;
 }s_dw_variable_t, *dw_variable_t;
 
-void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable);
-
 typedef struct s_dw_frame{
   char *name;
   void *low_pc;
@@ -431,6 +431,12 @@ typedef struct s_dw_frame{
 
 void dw_type_free(dw_type_t t);
 void dw_variable_free(dw_variable_t v);
+void dw_variable_free_voidp(void *t);
+
+void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable);
+void MC_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
 
 /********************************** DWARF **********************************/
 
@@ -447,8 +453,7 @@ typedef struct s_local_variable{
   int region;
 }s_local_variable_t, *local_variable_t;
 
-#define MC_USE_LIBDW_TYPES 1
-#define MC_USE_LIBDW_NON_FUNCTION_VARIABLES 1
+#define MC_USE_LIBDW (getenv("MC_USE_OBJDUMP") == NULL)
 
 #endif