/** \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) {
}
}
+/** \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;
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;
}
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);
}
}
break;
}
case DW_FORM_sec_offset: // type loclistptr
+ case DW_FORM_data4:
xbt_die("Do not handle loclist locations yet");
break;
default:
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:
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) {
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;
}
dwarf_end(dwarf);
close(fd);
}
+
}
}
-static void dw_variable_free_voidp(void *t){
+void dw_variable_free_voidp(void *t){
dw_variable_free((dw_variable_t) * (void **) t);
}
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;
}
* @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);
}
+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");
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;
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{
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 *));
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, "(");
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);
}
}
- }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 */
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) {
// 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);
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);
}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;
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 **********************************/
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