+ dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
+
+ frame->tag = tag;
+ frame->id = dwarf_dieoffset(die);
+ frame->object_info = info;
+
+ if(klass==mc_tag_subprogram) {
+ const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
+ frame->name = namespace ? bprintf("%s::%s", namespace, name) : xbt_strdup(name);
+ }
+
+ frame->abstract_origin_id = MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin);
+
+ // This is the base address for DWARF addresses.
+ // Relocated addresses are offset from this base address.
+ // See DWARF4 spec 7.5
+ void* base = MC_object_base_address(info);
+
+ // 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);
+
+ // 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;
+ if(low_pc) {
+ // DW_AT_high_pc:
+ Dwarf_Attribute attr;
+ if(!dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) {
+ xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc");
+ }
+
+ Dwarf_Sword offset;
+ Dwarf_Addr high_pc;
+
+ switch(MC_dwarf_form_get_class(dwarf_whatform(&attr))) {
+
+ // DW_AT_high_pc if an offset from the low_pc:
+ case MC_DW_CLASS_CONSTANT:
+
+ if (dwarf_formsdata(&attr, &offset) !=0)
+ xbt_die("Could not read constant");
+ frame->high_pc = (void*) ((char*)frame->low_pc + offset);
+ break;
+
+ // DW_AT_high_pc is a relocatable address:
+ case MC_DW_CLASS_ADDRESS:
+ if (dwarf_formaddr(&attr, &high_pc) != 0)
+ xbt_die("Could not read address");
+ frame->high_pc = ((char*) base) + high_pc;
+ break;
+
+ default:
+ xbt_die("Unexpected class for DW_AT_high_pc");
+
+ }
+ }
+
+ if(klass==mc_tag_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->scopes = xbt_dynar_new(sizeof(dw_frame_t), (void_f_pvoid_t) mc_frame_free_voipd);
+
+ // Register it:
+ if(klass==mc_tag_subprogram) {
+ char* key = bprintf("%" PRIx64, (uint64_t) frame->id);
+ xbt_dict_set(info->subprograms, key, frame, NULL);
+ xbt_free(key);
+ } else if(klass==mc_tag_scope) {
+ xbt_dynar_push(parent_frame->scopes, &frame);
+ }
+
+ // Handle children:
+ MC_dwarf_handle_children(info, die, unit, frame, namespace);
+}
+
+static void mc_dwarf_handle_namespace_die(
+ mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+ const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
+ if(frame)
+ xbt_die("Unexpected namespace in a subprogram");
+ char* new_namespace = namespace == NULL ? xbt_strdup(name)
+ : bprintf("%s::%s", namespace, name);
+ MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
+ xbt_free(new_namespace);
+}
+
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+ // For each child DIE: