+ // Skip compile time constants:
+ if(dwarf_hasattr(die, DW_AT_const_value))
+ return NULL;
+
+ Dwarf_Attribute attr_location;
+ if (dwarf_attr(die, DW_AT_location, &attr_location)==NULL) {
+ // No location: do not add it ?
+ return NULL;
+ }
+
+ dw_variable_t variable = xbt_new0(s_dw_variable_t, 1);
+ variable->dwarf_offset = dwarf_dieoffset(die);
+ variable->global = frame == NULL; // Can be override base on DW_AT_location
+
+ const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
+ variable->name = xbt_strdup(name);
+
+ variable->type_origin = 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:
+ // Location expression:
+ {
+ Dwarf_Op* expr;
+ size_t len;
+ if (dwarf_getlocation(&attr_location, &expr, &len)) {
+ xbt_die(
+ "Could not read location expression in DW_AT_location of variable <%p>%s",
+ (void*) variable->dwarf_offset, variable->name);
+ }
+
+ if (len==1 && expr[0].atom == DW_OP_addr) {
+ variable->global = 1;
+ Dwarf_Off offset = expr[0].number;
+ // TODO, Why is this different base on the object?
+ Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_exec : 0;
+ variable->address = (void*) (base + offset);
+ } else {
+ mc_dwarf_location_list_init_from_expression(&variable->locations, len, expr);
+ }
+
+ break;
+ }
+ case MC_DW_CLASS_LOCLISTPTR:
+ case MC_DW_CLASS_CONSTANT:
+ // Reference to location list:
+ mc_dwarf_location_list_init(&variable->locations, info, die, &attr_location);
+ break;
+ default:
+ xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%p>%s",
+ form, form, klass, klass, (void*) variable->dwarf_offset, variable->name);
+ }
+
+ // Handle start_scope:
+ if (dwarf_hasattr(die, DW_AT_start_scope)) {
+ 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:
+ {
+ Dwarf_Word value;
+ variable->start_scope = dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
+ break;
+ }
+ default:
+ xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
+ form, klass, name==NULL ? "?" : name);
+ }
+ }
+
+ if(namespace && variable->global) {
+ char* old_name = variable->name;
+ variable->name = bprintf("%s::%s", namespace, old_name);
+ free(old_name);
+ }
+
+ // The current code needs a variable name,
+ // generate a fake one:
+ if(!variable->name) {
+ variable->name = bprintf("@anonymous#%i", mc_anonymous_variable_index++);
+ }
+
+ return variable;
+}
+
+static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+ dw_variable_t variable = MC_die_to_variable(info, die, unit, frame, namespace);
+ if(variable==NULL)
+ return;
+ MC_dwarf_register_variable(info, frame, variable);
+}
+
+static void mc_frame_free_voipd(dw_frame_t* p) {
+ mc_frame_free(*p);
+ *p = NULL;
+}
+
+static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame, const char* namespace) {
+ // TODO, handle DW_TAG_type/DW_TAG_location for DW_TAG_with_stmt
+ int tag = dwarf_tag(die);
+ mc_tag_class klass = MC_dwarf_tag_classify(tag);
+
+ // (Template) Subprogram declaration:
+ if(klass==mc_tag_subprogram && MC_dwarf_attr_flag(die, DW_AT_declaration, false))
+ return;
+
+ if(klass==mc_tag_scope)
+ xbt_assert(parent_frame, "No parent scope for this scope");
+
+ dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
+
+ frame->tag = tag;
+ frame->start = dwarf_dieoffset(die);
+
+ const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
+ if(name)
+ frame->name = namespace ? bprintf("%s::%s", namespace, name) : xbt_strdup(name);
+
+ // This is the base address for DWARF addresses.
+ // Relocated addresses are offset from this base address.
+ // See DWARF4 spec 7.5
+ void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : 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);
+ frame->high_pc = ((char*) base) + MC_dwarf_attr_integrate_addr(die, DW_AT_high_pc);
+ frame->low_pc = ((char*) base) + MC_dwarf_attr_integrate_addr(die, DW_AT_low_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->end = -1; // This one is now useless:
+ 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->start);
+ 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: