- 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
- variable->object_info = info;
-
- 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 <%"
- PRIx64 ">%s", (uint64_t) variable->dwarf_offset, variable->name);
- }
-
- if (len == 1 && expr[0].atom == DW_OP_addr) {
- variable->global = 1;
- uintptr_t offset = (uintptr_t) expr[0].number;
- uintptr_t base = (uintptr_t) info->base_address();
- 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 <%"
- PRIx64 ">%s", form, form, klass, klass,
- (uint64_t) 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;
- }
- case MC_DW_CLASS_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);
- }
- }
-
- if (ns && variable->global) {
- char *old_name = variable->name;
- variable->name = bprintf("%s::%s", ns, 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 *ns)
-{
- dw_variable_t variable =
- MC_die_to_variable(info, die, unit, frame, ns);
- 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 *ns)
-{
- // 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->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 =
- ns ? bprintf("%s::%s", ns, 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 = info->base_address();
-
- // 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, ns);
-}
-
-static void mc_dwarf_handle_namespace_die(mc_object_info_t info,
- Dwarf_Die * die, Dwarf_Die * unit,
- dw_frame_t frame,
- const char *ns)
-{
- const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
- if (frame)
- xbt_die("Unexpected namespace in a subprogram");
- char *new_ns = ns == NULL ? xbt_strdup(name)
- : bprintf("%s::%s", ns, name);
- MC_dwarf_handle_children(info, die, unit, frame, new_ns);
- xbt_free(new_ns);
-}
-
-static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
- Dwarf_Die * unit, dw_frame_t frame,
- const char *ns)
-{
- // For each child DIE:
- 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, frame, ns);
- }
-}
-
-static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
- Dwarf_Die * unit, dw_frame_t frame,
- const char *ns)
-{
- int tag = dwarf_tag(die);
- mc_tag_class klass = MC_dwarf_tag_classify(tag);
- switch (klass) {
-
- // Type:
- case mc_tag_type:
- MC_dwarf_handle_type_die(info, die, unit, frame, ns);
- break;
-
- // Subprogram or scope:
- case mc_tag_subprogram:
- case mc_tag_scope:
- MC_dwarf_handle_scope_die(info, die, unit, frame, ns);
- return;
-
- // Variable:
- case mc_tag_variable:
- MC_dwarf_handle_variable_die(info, die, unit, frame, ns);
- break;
-
- case mc_tag_namespace:
- mc_dwarf_handle_namespace_die(info, die, unit, frame, ns);
- break;
-
- default:
- break;
-
- }
-}
-
-/** \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.
- */
-void MC_dwarf_get_variables(mc_object_info_t info)
-{
- int fd = open(info->file_name, O_RDONLY);
- if (fd < 0) {
- xbt_die("Could not open file %s", info->file_name);
- }
- Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
- if (dwarf == NULL) {
- xbt_die("Your program must be compiled with -g (%s)", info->file_name);
- }
- // For each compilation unit:
- Dwarf_Off offset = 0;
- Dwarf_Off next_offset = 0;
- size_t length;
- while (dwarf_nextcu(dwarf, offset, &next_offset, &length, NULL, NULL, NULL) ==
- 0) {
- Dwarf_Die unit_die;
- if (dwarf_offdie(dwarf, offset + length, &unit_die) != NULL) {
-
- // For each child DIE:
- Dwarf_Die child;
- int res;
- for (res = dwarf_child(&unit_die, &child); res == 0;
- res = dwarf_siblingof(&child, &child)) {
- MC_dwarf_handle_die(info, &child, &unit_die, NULL, NULL);
- }
-
- }
- offset = next_offset;
- }
-
- dwarf_end(dwarf);
- close(fd);
-}
-
-/************************** Free functions *************************/
-
-void mc_frame_free(dw_frame_t frame)
-{
- xbt_free(frame->name);
- mc_dwarf_location_list_clear(&(frame->frame_base));
- xbt_dynar_free(&(frame->variables));
- xbt_dynar_free(&(frame->scopes));
- xbt_free(frame);
-}
-
-s_dw_type::s_dw_type()
-{
- this->type = 0;
- this->id = 0;
- this->name = nullptr;
- this->byte_size = 0;
- this->element_count = 0;
- this->dw_type_id = nullptr;
- this->members = nullptr;
- this->is_pointer_type = 0;
- this->location = { 0, 0, 0, 0};
- this->offset = 0;
- this->subtype = nullptr;
- this->full_type = nullptr;
-}
-
-s_dw_type::~s_dw_type()
-{
- xbt_free(this->name);
- xbt_free(this->dw_type_id);
- xbt_dynar_free(&this->members);
- mc_dwarf_expression_clear(&this->location);
-}
-
-static void dw_type_free(dw_type_t t)
-{
- delete t;
-}
-
-void dw_variable_free(dw_variable_t v)
-{
- if (v) {
- xbt_free(v->name);
- xbt_free(v->type_origin);
-
- if (v->locations.locations)
- mc_dwarf_location_list_clear(&v->locations);
- xbt_free(v);
- }
-}
-
-void dw_variable_free_voidp(void *t)
-{
- dw_variable_free((dw_variable_t) * (void **) t);
-}
-
-// ***** object_info
-
-namespace simgrid {
-namespace mc {
-
-ObjectInformation::ObjectInformation()
-{
- this->flags = 0;
- this->file_name = nullptr;
- this->start = nullptr;
- this->end = nullptr;
- this->start_exec = nullptr;
- this->end_exec = nullptr;
- this->start_rw = nullptr;
- this->end_rw = nullptr;
- this->start_ro = nullptr;
- this->end_ro = nullptr;
- this->subprograms = xbt_dict_new_homogeneous((void (*)(void *)) mc_frame_free);
- this->global_variables =
- xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
- this->types = xbt_dict_new_homogeneous((void (*)(void *)) dw_type_free);
- this->full_types_by_name = xbt_dict_new_homogeneous(NULL);
- this->functions_index = nullptr;
-}
-
-ObjectInformation::~ObjectInformation()
-{
- xbt_free(this->file_name);
- xbt_dict_free(&this->subprograms);
- xbt_dynar_free(&this->global_variables);
- xbt_dict_free(&this->types);
- xbt_dict_free(&this->full_types_by_name);
- xbt_dynar_free(&this->functions_index);
-}
-
-/** Find the DWARF offset for this ELF object
- *
- * An offset is applied to address found in DWARF:
- *
- * <ul>
- * <li>for an executable obejct, addresses are virtual address
- * (there is no offset) i.e. \f$\text{virtual address} = \{dwarf address}\f$;</li>
- * <li>for a shared object, the addreses are offset from the begining
- * of the shared object (the base address of the mapped shared
- * object must be used as offset
- * i.e. \f$\text{virtual address} = \text{shared object base address}
- * + \text{dwarf address}\f$.</li>
- *
- */
-void *ObjectInformation::base_address() const
-{
- if (this->executable())
- return nullptr;
-
- void *result = this->start_exec;
- if (this->start_rw != NULL && result > (void *) this->start_rw)
- result = this->start_rw;
- if (this->start_ro != NULL && result > (void *) this->start_ro)
- result = this->start_ro;
- return result;
-}
-
-}
-}
-
-// ***** Helpers