+/** \brief Get the linkage name of a DIE.
+ *
+ * Use either DW_AT_linkage_name or DW_AR_MIPS_linkage_name.
+ *
+ * \param DIE
+ * \return linkage name of the given DIE (or NULL)
+ * */
+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;
+}
+
+/** \brief Create a location list from a given attribute
+ *
+ * \param die the DIE
+ * \param attr the attribute
+ * \return MC specific representation of the location list represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_get_location_list(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) {
+
+ dw_location_t location = xbt_new0(s_dw_location_t, 1);
+ location->type = e_dw_loclist;
+ xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
+ location->location.loclist = loclist;
+
+ ptrdiff_t offset = 0;
+ Dwarf_Addr base, start, end;
+ Dwarf_Op *expr;
+ size_t len;
+
+ while (1) {
+
+ offset = dwarf_getlocations(attr, offset, &base, &start, &end, &expr, &len);
+ if (offset==0)
+ return location;
+ else if (offset==-1)
+ xbt_die("Error while loading location list");
+
+ dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
+
+ void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
+
+ new_entry->lowpc = (char*) base + start;
+ new_entry->highpc = (char*) base + end;
+ new_entry->location = MC_dwarf_get_expression(expr, len);
+
+ xbt_dynar_push(loclist, &new_entry);
+
+ }
+}
+
+/** \brief Find the frame base of a given frame
+ *
+ * \param ip Instruction pointer
+ * \param frame
+ * \param unw_cursor
+ */
+void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor) {
+ switch(frame->frame_base->type) {
+ case e_dw_loclist:
+ {
+ int loclist_cursor;
+ for(loclist_cursor=0; loclist_cursor < xbt_dynar_length(frame->frame_base->location.loclist); loclist_cursor++){
+ dw_location_entry_t entry = xbt_dynar_get_as(frame->frame_base->location.loclist, loclist_cursor, dw_location_entry_t);
+ if((ip >= entry->lowpc) && (ip < entry->highpc)){
+ return (void*) MC_dwarf_resolve_location(unw_cursor, entry->location, NULL);
+ }
+ }
+ return NULL;
+ }
+ // Not handled:
+ default:
+ return NULL;
+ }
+}
+
+/** \brief Get the location expression or location list from an attribute
+ *
+ * Processes direct expressions as well as location lists.
+ *
+ * \param die the DIE
+ * \param attr the attribute
+ * \return MC specific representation of the location represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_get_location(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) {
+ int form = dwarf_whatform(attr);
+ switch (form) {
+
+ // The attribute is an DWARF location expression:
+ 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);
+ }
+
+ // The attribute is a reference to a location list entry:
+ case DW_FORM_sec_offset:
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ {
+ return MC_dwarf_get_location_list(info, die, attr);
+ }
+ 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;
+ }
+}
+
+/** \brief Get the location expression or location list from an attribute
+ *
+ * Processes direct expressions as well as location lists.
+ *
+ * \param die the DIE
+ * \param attribute the attribute code
+ * \return MC specific representation of the location represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_at_location(mc_object_info_t info, Dwarf_Die* die, int attribute) {
+ 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(info, die, &attr);
+}
+