Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
7c589bd6f85dbe25b08c754ba5e34668f106e546
[simgrid.git] / src / mc / mc_libdw.cpp
1 /* Copyright (c) 2008-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <cstdint>
8
9 #include <algorithm>
10 #include <memory>
11 #include <string>
12 #include <utility>
13
14 #include <dwarf.h>
15 #include <elfutils/libdw.h>
16
17 #include <xbt/log.h>
18
19 #include "mc/Frame.hpp"
20 #include "mc/ObjectInformation.hpp"
21 #include "mc/Variable.hpp"
22
23 #include "mc/mc_dwarf.hpp"
24 #include "mc/mc_libdw.hpp"
25
26 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_libdw, mc, "DWARF processing");
27
28 /** \brief Get the name of the tag of a given DIE
29  *
30  *  \param die DIE
31  *  \return name of the tag of this DIE
32  */
33 static inline const char *MC_dwarf_die_tagname(Dwarf_Die * die)
34 {
35   return MC_dwarf_tagname(dwarf_tag(die));
36 }
37
38 static
39 simgrid::mc::DwarfExpression MC_dwarf_expression(Dwarf_Op* ops, std::size_t len)
40 {
41   simgrid::mc::DwarfExpression expression(len);
42   for (std::size_t i = 0; i != len; ++i) {
43     expression[i].atom = ops[i].atom;
44     expression[i].number = ops[i].number;
45     expression[i].number2 = ops[i].number2;
46     expression[i].offset = ops[i].offset;
47   }
48   return std::move(expression);
49 }
50
51 static void mc_dwarf_location_list_init_libdw(
52   simgrid::mc::LocationList* list, simgrid::mc::ObjectInformation* info,
53   Dwarf_Die * die, Dwarf_Attribute * attr)
54 {
55   list->clear();
56
57   ptrdiff_t offset = 0;
58   Dwarf_Addr base, start, end;
59   Dwarf_Op *ops;
60   size_t len;
61
62   while (1) {
63
64     offset = dwarf_getlocations(attr, offset, &base, &start, &end, &ops, &len);
65     if (offset == 0)
66       return;
67     else if (offset == -1)
68       xbt_die("Error while loading location list");
69
70     simgrid::mc::LocationListEntry entry;
71     entry.expression = MC_dwarf_expression(ops, len);
72
73     void *base = info->base_address();
74     // If start == 0, this is not a location list:
75     entry.lowpc = start == 0 ? NULL : (char *) base + start;
76     entry.highpc = start == 0 ? NULL : (char *) base + end;
77
78     list->push_back(std::move(entry));
79   }
80
81 }
82
83 // ***** Attributes
84
85 /** \brief Get an attribute of a given DIE as a string
86  *
87  *  \param die       the DIE
88  *  \param attribute attribute
89  *  \return value of the given attribute of the given DIE
90  */
91 static const char *MC_dwarf_attr_integrate_string(Dwarf_Die * die,
92                                                   int attribute)
93 {
94   Dwarf_Attribute attr;
95   if (!dwarf_attr_integrate(die, attribute, &attr)) {
96     return NULL;
97   } else {
98     return dwarf_formstring(&attr);
99   }
100 }
101
102 /** \brief Get the linkage name of a DIE.
103  *
104  *  Use either DW_AT_linkage_name or DW_AT_MIPS_linkage_name.
105  *  DW_AT_linkage_name is standardized since DWARF 4.
106  *  Before this version of DWARF, the MIPS extensions
107  *  DW_AT_MIPS_linkage_name is used (at least by GCC).
108  *
109  *  \param  the DIE
110  *  \return linkage name of the given DIE (or NULL)
111  * */
112 static const char *MC_dwarf_at_linkage_name(Dwarf_Die * die)
113 {
114   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_linkage_name);
115   if (!name)
116     name = MC_dwarf_attr_integrate_string(die, DW_AT_MIPS_linkage_name);
117   return name;
118 }
119
120 static Dwarf_Off MC_dwarf_attr_dieoffset(Dwarf_Die * die, int attribute)
121 {
122   Dwarf_Attribute attr;
123   if (dwarf_hasattr_integrate(die, attribute) == 0)
124     return 0;
125   dwarf_attr_integrate(die, attribute, &attr);
126   Dwarf_Die subtype_die;
127   if (dwarf_formref_die(&attr, &subtype_die) == NULL)
128     xbt_die("Could not find DIE");
129   return dwarf_dieoffset(&subtype_die);
130 }
131
132 static Dwarf_Off MC_dwarf_attr_integrate_dieoffset(Dwarf_Die * die,
133                                                    int attribute)
134 {
135   Dwarf_Attribute attr;
136   if (dwarf_hasattr_integrate(die, attribute) == 0)
137     return 0;
138   dwarf_attr_integrate(die, DW_AT_type, &attr);
139   Dwarf_Die subtype_die;
140   if (dwarf_formref_die(&attr, &subtype_die) == NULL)
141     xbt_die("Could not find DIE");
142   return dwarf_dieoffset(&subtype_die);
143 }
144
145 /** \brief Find the type/subtype (DW_AT_type) for a DIE
146  *
147  *  \param dit the DIE
148  *  \return DW_AT_type reference as a global offset in hexadecimal (or NULL)
149  */
150 static
151 std::uint64_t MC_dwarf_at_type(Dwarf_Die * die)
152 {
153   return MC_dwarf_attr_integrate_dieoffset(die, DW_AT_type);
154 }
155
156 static std::uint64_t MC_dwarf_attr_integrate_addr(Dwarf_Die * die, int attribute)
157 {
158   Dwarf_Attribute attr;
159   if (dwarf_attr_integrate(die, attribute, &attr) == NULL)
160     return 0;
161   Dwarf_Addr value;
162   if (dwarf_formaddr(&attr, &value) == 0)
163     return (std::uint64_t) value;
164   else
165     return 0;
166 }
167
168 static std::uint64_t MC_dwarf_attr_integrate_uint(Dwarf_Die * die, int attribute,
169                                                   std::uint64_t default_value)
170 {
171   Dwarf_Attribute attr;
172   if (dwarf_attr_integrate(die, attribute, &attr) == NULL)
173     return default_value;
174   Dwarf_Word value;
175   return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr),
176                          &value) == 0 ? (std::uint64_t) value : default_value;
177 }
178
179 static bool MC_dwarf_attr_flag(Dwarf_Die * die, int attribute, bool integrate)
180 {
181   Dwarf_Attribute attr;
182   if ((integrate ? dwarf_attr_integrate(die, attribute, &attr)
183        : dwarf_attr(die, attribute, &attr)) == 0)
184     return false;
185
186   bool result;
187   if (dwarf_formflag(&attr, &result))
188     xbt_die("Unexpected form for attribute %s", MC_dwarf_attrname(attribute));
189   return result;
190 }
191
192 /** \brief Finds the number of elements in a DW_TAG_subrange_type or DW_TAG_enumeration_type DIE
193  *
194  *  \param die  the DIE
195  *  \param unit DIE of the compilation unit
196  *  \return     number of elements in the range
197  * */
198 static std::uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die,
199                                                      Dwarf_Die * unit)
200 {
201   xbt_assert(dwarf_tag(die) == DW_TAG_enumeration_type
202              || dwarf_tag(die) == DW_TAG_subrange_type,
203              "MC_dwarf_subrange_element_count called with DIE of type %s",
204              MC_dwarf_die_tagname(die));
205
206   // Use DW_TAG_count if present:
207   if (dwarf_hasattr_integrate(die, DW_AT_count))
208     return MC_dwarf_attr_integrate_uint(die, DW_AT_count, 0);
209   // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1:
210
211   if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound))
212     // This is not really 0, but the code expects this (we do not know):
213     return 0;
214
215   std::uint64_t upper_bound =
216       MC_dwarf_attr_integrate_uint(die, DW_AT_upper_bound, -1);
217
218   std::uint64_t lower_bound = 0;
219   if (dwarf_hasattr_integrate(die, DW_AT_lower_bound))
220     lower_bound = MC_dwarf_attr_integrate_uint(die, DW_AT_lower_bound, -1);
221   else
222     lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit));
223   return upper_bound - lower_bound + 1;
224 }
225
226 /** \brief Finds the number of elements in a array type (DW_TAG_array_type)
227  *
228  *  The compilation unit might be needed because the default lower
229  *  bound depends on the language of the compilation unit.
230  *
231  *  \param die the DIE of the DW_TAG_array_type
232  *  \param unit the DIE of the compilation unit
233  *  \return number of elements in this array type
234  * */
235 static
236 std::uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit)
237 {
238   xbt_assert(dwarf_tag(die) == DW_TAG_array_type,
239              "MC_dwarf_array_element_count called with DIE of type %s",
240              MC_dwarf_die_tagname(die));
241
242   int result = 1;
243   Dwarf_Die child;
244   int res;
245   for (res = dwarf_child(die, &child); res == 0;
246        res = dwarf_siblingof(&child, &child)) {
247     int child_tag = dwarf_tag(&child);
248     if (child_tag == DW_TAG_subrange_type
249         || child_tag == DW_TAG_enumeration_type)
250       result *= MC_dwarf_subrange_element_count(&child, unit);
251   }
252   return result;
253 }
254
255 // ***** simgrid::mc::Type*
256
257 /** \brief Initialize the location of a member of a type
258  * (DW_AT_data_member_location of a DW_TAG_member).
259  *
260  *  \param  type   a type (struct, class)
261  *  \param  member the member of the type
262  *  \param  child  DIE of the member (DW_TAG_member)
263  */
264 static void MC_dwarf_fill_member_location(simgrid::mc::Type* type, simgrid::mc::Type* member,
265                                           Dwarf_Die * child)
266 {
267   if (dwarf_hasattr(child, DW_AT_data_bit_offset))
268     xbt_die("Can't groke DW_AT_data_bit_offset.");
269
270   if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
271     if (type->type == DW_TAG_union_type)
272       return;
273     xbt_die
274         ("Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%"
275          PRIx64 ">%s", member->name.c_str(),
276          (std::uint64_t) type->id, type->name.c_str());
277   }
278
279   Dwarf_Attribute attr;
280   dwarf_attr_integrate(child, DW_AT_data_member_location, &attr);
281   int form = dwarf_whatform(&attr);
282   int klass = MC_dwarf_form_get_class(form);
283   switch (klass) {
284   case MC_DW_CLASS_EXPRLOC:
285   case MC_DW_CLASS_BLOCK:
286     // Location expression:
287     {
288       Dwarf_Op *expr;
289       size_t len;
290       if (dwarf_getlocation(&attr, &expr, &len))
291         xbt_die
292             ("Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%"
293              PRIx64 ">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name),
294              (std::uint64_t) type->id, type->name.c_str());
295       member->location_expression = MC_dwarf_expression(expr, len);
296       break;
297     }
298   case MC_DW_CLASS_CONSTANT:
299     // Offset from the base address of the object:
300     {
301       Dwarf_Word offset;
302       if (!dwarf_formudata(&attr, &offset))
303         member->offset(offset);
304       else
305         xbt_die("Cannot get %s location <%" PRIx64 ">%s",
306                 MC_dwarf_attr_integrate_string(child, DW_AT_name),
307                 (std::uint64_t) type->id, type->name.c_str());
308       break;
309     }
310   case MC_DW_CLASS_LOCLISTPTR:
311     // Reference to a location list:
312     // TODO
313   case MC_DW_CLASS_REFERENCE:
314     // It's supposed to be possible in DWARF2 but I couldn't find its semantic
315     // in the spec.
316   default:
317     xbt_die("Can't handle form class (%i) / form 0x%x as DW_AT_member_location",
318             klass, form);
319   }
320
321 }
322
323 /** \brief Populate the list of members of a type
324  *
325  *  \param info ELF object containing the type DIE
326  *  \param die  DIE of the type
327  *  \param unit DIE of the compilation unit containing the type DIE
328  *  \param type the type
329  */
330 static void MC_dwarf_add_members(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
331                                  Dwarf_Die * unit, simgrid::mc::Type* type)
332 {
333   int res;
334   Dwarf_Die child;
335   xbt_assert(type->members.empty());
336   for (res = dwarf_child(die, &child); res == 0;
337        res = dwarf_siblingof(&child, &child)) {
338     int tag = dwarf_tag(&child);
339     if (tag == DW_TAG_member || tag == DW_TAG_inheritance) {
340
341       // Skip declarations:
342       if (MC_dwarf_attr_flag(&child, DW_AT_declaration, false))
343         continue;
344
345       // Skip compile time constants:
346       if (dwarf_hasattr(&child, DW_AT_const_value))
347         continue;
348
349       // TODO, we should use another type (because is is not a type but a member)
350       simgrid::mc::Type member;
351       member.type = tag;
352
353       // Global Offset:
354       member.id = dwarf_dieoffset(&child);
355
356       const char *name = MC_dwarf_attr_integrate_string(&child, DW_AT_name);
357       if (name)
358         member.name = name;
359       member.byte_size =
360           MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0);
361       member.element_count = -1;
362       member.type_id = MC_dwarf_at_type(&child);
363
364       if (dwarf_hasattr(&child, DW_AT_data_bit_offset))
365         xbt_die("Can't groke DW_AT_data_bit_offset.");
366
367       MC_dwarf_fill_member_location(type, &member, &child);
368
369       if (!member.type_id)
370         xbt_die("Missing type for member %s of <%" PRIx64 ">%s",
371                 member.name.c_str(),
372                 (std::uint64_t) type->id, type->name.c_str());
373
374       type->members.push_back(std::move(member));
375     }
376   }
377 }
378
379 /** \brief Create a MC type object from a DIE
380  *
381  *  \param info current object info object
382  *  \param DIE (for a given type);
383  *  \param unit compilation unit of the current DIE
384  *  \return MC representation of the type
385  */
386 static simgrid::mc::Type MC_dwarf_die_to_type(
387   simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
388   Dwarf_Die * unit, simgrid::mc::Frame* frame,
389   const char *ns)
390 {
391   simgrid::mc::Type type;
392   type.type = dwarf_tag(die);
393   type.name = std::string();
394   type.element_count = -1;
395
396   // Global Offset
397   type.id = dwarf_dieoffset(die);
398
399   const char *prefix = "";
400   switch (type.type) {
401   case DW_TAG_structure_type:
402     prefix = "struct ";
403     break;
404   case DW_TAG_union_type:
405     prefix = "union ";
406     break;
407   case DW_TAG_class_type:
408     prefix = "class ";
409     break;
410   default:
411     prefix = "";
412   }
413
414   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
415   if (name != NULL) {
416     char* full_name = ns ? bprintf("%s%s::%s", prefix, ns, name) :
417       bprintf("%s%s", prefix, name);
418     type.name = std::string(full_name);
419     free(full_name);
420   }
421
422   type.type_id = MC_dwarf_at_type(die);
423
424   // Some compilers do not emit DW_AT_byte_size for pointer_type,
425   // so we fill this. We currently assume that the model-checked process is in
426   // the same architecture..
427   if (type.type == DW_TAG_pointer_type)
428     type.byte_size = sizeof(void*);
429
430   // Computation of the byte_size;
431   if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
432     type.byte_size = MC_dwarf_attr_integrate_uint(die, DW_AT_byte_size, 0);
433   else if (type.type == DW_TAG_array_type
434            || type.type == DW_TAG_structure_type
435            || type.type == DW_TAG_class_type) {
436     Dwarf_Word size;
437     if (dwarf_aggregate_size(die, &size) == 0)
438       type.byte_size = size;
439   }
440
441   switch (type.type) {
442   case DW_TAG_array_type:
443     type.element_count = MC_dwarf_array_element_count(die, unit);
444     // TODO, handle DW_byte_stride and (not) DW_bit_stride
445     break;
446
447   case DW_TAG_pointer_type:
448   case DW_TAG_reference_type:
449   case DW_TAG_rvalue_reference_type:
450     type.is_pointer_type = 1;
451     break;
452
453   case DW_TAG_structure_type:
454   case DW_TAG_union_type:
455   case DW_TAG_class_type:
456     MC_dwarf_add_members(info, die, unit, &type);
457     char *new_ns = ns == NULL ? xbt_strdup(type.name.c_str())
458         : bprintf("%s::%s", ns, name);
459     MC_dwarf_handle_children(info, die, unit, frame, new_ns);
460     free(new_ns);
461     break;
462   }
463
464   return std::move(type);
465 }
466
467 static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
468                                      Dwarf_Die * unit, simgrid::mc::Frame* frame,
469                                      const char *ns)
470 {
471   simgrid::mc::Type type = MC_dwarf_die_to_type(info, die, unit, frame, ns);
472   auto& t = (info->types[type.id] = std::move(type));
473   if (!t.name.empty() && type.byte_size != 0)
474     info->full_types_by_name[t.name] = &t;
475 }
476
477 static int mc_anonymous_variable_index = 0;
478
479 static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
480   simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
481   Dwarf_Die * unit, simgrid::mc::Frame* frame,
482   const char *ns)
483 {
484   // Skip declarations:
485   if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
486     return nullptr;
487
488   // Skip compile time constants:
489   if (dwarf_hasattr(die, DW_AT_const_value))
490     return nullptr;
491
492   Dwarf_Attribute attr_location;
493   if (dwarf_attr(die, DW_AT_location, &attr_location) == NULL)
494     // No location: do not add it ?
495     return nullptr;
496
497   std::unique_ptr<simgrid::mc::Variable> variable =
498     std::unique_ptr<simgrid::mc::Variable>(new simgrid::mc::Variable());
499   variable->dwarf_offset = dwarf_dieoffset(die);
500   variable->global = frame == NULL;     // Can be override base on DW_AT_location
501   variable->object_info = info;
502
503   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
504   if (name)
505     variable->name = name;
506   variable->type_id = MC_dwarf_at_type(die);
507
508   int form = dwarf_whatform(&attr_location);
509   int klass =
510       form ==
511       DW_FORM_sec_offset ? MC_DW_CLASS_CONSTANT : MC_dwarf_form_get_class(form);
512   switch (klass) {
513   case MC_DW_CLASS_EXPRLOC:
514   case MC_DW_CLASS_BLOCK:
515     // Location expression:
516     {
517       Dwarf_Op *expr;
518       size_t len;
519       if (dwarf_getlocation(&attr_location, &expr, &len)) {
520         xbt_die(
521           "Could not read location expression in DW_AT_location "
522           "of variable <%" PRIx64 ">%s",
523           (std::uint64_t) variable->dwarf_offset,
524           variable->name.c_str());
525       }
526
527       if (len == 1 && expr[0].atom == DW_OP_addr) {
528         variable->global = 1;
529         uintptr_t offset = (uintptr_t) expr[0].number;
530         uintptr_t base = (uintptr_t) info->base_address();
531         variable->address = (void *) (base + offset);
532       } else {
533         simgrid::mc::LocationListEntry entry;
534         entry.expression = MC_dwarf_expression(expr, len);
535         variable->location_list = { std::move(entry) };
536       }
537
538       break;
539     }
540   case MC_DW_CLASS_LOCLISTPTR:
541   case MC_DW_CLASS_CONSTANT:
542     // Reference to location list:
543     mc_dwarf_location_list_init_libdw(
544       &variable->location_list, info, die,
545       &attr_location);
546     break;
547   default:
548     xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location "
549             "in <%" PRIx64 ">%s",
550             form, form, klass, klass,
551             (std::uint64_t) variable->dwarf_offset,
552             variable->name.c_str());
553   }
554
555   // Handle start_scope:
556   if (dwarf_hasattr(die, DW_AT_start_scope)) {
557     Dwarf_Attribute attr;
558     dwarf_attr(die, DW_AT_start_scope, &attr);
559     int form = dwarf_whatform(&attr);
560     int klass = MC_dwarf_form_get_class(form);
561     switch (klass) {
562     case MC_DW_CLASS_CONSTANT:
563       {
564         Dwarf_Word value;
565         variable->start_scope =
566             dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
567         break;
568       }
569     case MC_DW_CLASS_RANGELISTPTR:     // TODO
570     default:
571       xbt_die
572           ("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
573            form, klass, name == NULL ? "?" : name);
574     }
575   }
576
577   if (ns && variable->global)
578     variable->name =
579       std::string(ns) + "::" + variable->name;
580
581   // The current code needs a variable name,
582   // generate a fake one:
583   if (variable->name.empty())
584     variable->name =
585       "@anonymous#" + std::to_string(mc_anonymous_variable_index++);
586
587   return std::move(variable);
588 }
589
590 static void MC_dwarf_handle_variable_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
591                                          Dwarf_Die * unit, simgrid::mc::Frame* frame,
592                                          const char *ns)
593 {
594   std::unique_ptr<simgrid::mc::Variable> variable =
595     MC_die_to_variable(info, die, unit, frame, ns);
596   if (!variable)
597     return;
598   // Those arrays are sorted later:
599   else if (variable->global)
600     info->global_variables.push_back(std::move(*variable));
601   else if (frame != nullptr)
602     frame->variables.push_back(std::move(*variable));
603   else
604     xbt_die("No frame for this local variable");
605 }
606
607 static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
608                                       Dwarf_Die * unit, simgrid::mc::Frame* parent_frame,
609                                       const char *ns)
610 {
611   // TODO, handle DW_TAG_type/DW_TAG_location for DW_TAG_with_stmt
612   int tag = dwarf_tag(die);
613   mc_tag_class klass = MC_dwarf_tag_classify(tag);
614
615   // (Template) Subprogram declaration:
616   if (klass == mc_tag_subprogram
617       && MC_dwarf_attr_flag(die, DW_AT_declaration, false))
618     return;
619
620   if (klass == mc_tag_scope)
621     xbt_assert(parent_frame, "No parent scope for this scope");
622
623   simgrid::mc::Frame frame;
624
625   frame.tag = tag;
626   frame.id = dwarf_dieoffset(die);
627   frame.object_info = info;
628
629   if (klass == mc_tag_subprogram) {
630     const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
631     if(ns)
632       frame.name  = std::string(ns) + "::" + name;
633     else if (name)
634       frame.name = name;
635     else
636       frame.name.clear();
637   }
638
639   frame.abstract_origin_id =
640     MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin);
641
642   // This is the base address for DWARF addresses.
643   // Relocated addresses are offset from this base address.
644   // See DWARF4 spec 7.5
645   void *base = info->base_address();
646
647   // TODO, support DW_AT_ranges
648   std::uint64_t low_pc = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc);
649   frame.low_pc = low_pc ? ((char *) base) + low_pc : 0;
650   if (low_pc) {
651     // DW_AT_high_pc:
652     Dwarf_Attribute attr;
653     if (!dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) {
654       xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc");
655     }
656
657     Dwarf_Sword offset;
658     Dwarf_Addr high_pc;
659
660     switch (MC_dwarf_form_get_class(dwarf_whatform(&attr))) {
661
662       // DW_AT_high_pc if an offset from the low_pc:
663     case MC_DW_CLASS_CONSTANT:
664
665       if (dwarf_formsdata(&attr, &offset) != 0)
666         xbt_die("Could not read constant");
667       frame.high_pc = (void *) ((char *) frame.low_pc + offset);
668       break;
669
670       // DW_AT_high_pc is a relocatable address:
671     case MC_DW_CLASS_ADDRESS:
672       if (dwarf_formaddr(&attr, &high_pc) != 0)
673         xbt_die("Could not read address");
674       frame.high_pc = ((char *) base) + high_pc;
675       break;
676
677     default:
678       xbt_die("Unexpected class for DW_AT_high_pc");
679
680     }
681   }
682
683   if (klass == mc_tag_subprogram) {
684     Dwarf_Attribute attr_frame_base;
685     if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base))
686       mc_dwarf_location_list_init_libdw(&frame.frame_base, info, die,
687                                   &attr_frame_base);
688   }
689
690   // Handle children:
691   MC_dwarf_handle_children(info, die, unit, &frame, ns);
692
693   // Someone needs this to be sorted but who?
694   std::sort(frame.variables.begin(), frame.variables.end(),
695     MC_compare_variable);
696
697   // Register it:
698   if (klass == mc_tag_subprogram)
699     info->subprograms[frame.id] = frame;
700   else if (klass == mc_tag_scope)
701     parent_frame->scopes.push_back(std::move(frame));
702 }
703
704 static void mc_dwarf_handle_namespace_die(simgrid::mc::ObjectInformation* info,
705                                           Dwarf_Die * die, Dwarf_Die * unit,
706                                           simgrid::mc::Frame* frame,
707                                           const char *ns)
708 {
709   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
710   if (frame)
711     xbt_die("Unexpected namespace in a subprogram");
712   char *new_ns = ns == NULL ? xbt_strdup(name)
713       : bprintf("%s::%s", ns, name);
714   MC_dwarf_handle_children(info, die, unit, frame, new_ns);
715   xbt_free(new_ns);
716 }
717
718 static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
719                                      Dwarf_Die * unit, simgrid::mc::Frame* frame,
720                                      const char *ns)
721 {
722   // For each child DIE:
723   Dwarf_Die child;
724   int res;
725   for (res = dwarf_child(die, &child); res == 0;
726        res = dwarf_siblingof(&child, &child)) {
727     MC_dwarf_handle_die(info, &child, unit, frame, ns);
728   }
729 }
730
731 static void MC_dwarf_handle_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die,
732                                 Dwarf_Die * unit, simgrid::mc::Frame* frame,
733                                 const char *ns)
734 {
735   int tag = dwarf_tag(die);
736   mc_tag_class klass = MC_dwarf_tag_classify(tag);
737   switch (klass) {
738
739     // Type:
740   case mc_tag_type:
741     MC_dwarf_handle_type_die(info, die, unit, frame, ns);
742     break;
743
744     // Subprogram or scope:
745   case mc_tag_subprogram:
746   case mc_tag_scope:
747     MC_dwarf_handle_scope_die(info, die, unit, frame, ns);
748     return;
749
750     // Variable:
751   case mc_tag_variable:
752     MC_dwarf_handle_variable_die(info, die, unit, frame, ns);
753     break;
754
755   case mc_tag_namespace:
756     mc_dwarf_handle_namespace_die(info, die, unit, frame, ns);
757     break;
758
759   default:
760     break;
761
762   }
763 }
764
765 /** \brief Populate the debugging informations of the given ELF object
766  *
767  *  Read the DWARf information of the EFFL object and populate the
768  *  lists of types, variables, functions.
769  */
770 void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
771 {
772   int fd = open(info->file_name.c_str(), O_RDONLY);
773   if (fd < 0)
774     xbt_die("Could not open file %s", info->file_name.c_str());
775   Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
776   if (dwarf == NULL)
777     xbt_die("Missing debugging information in %s\n"
778       "Your program and its dependencies must have debugging information.\n"
779       "You might want to recompile with -g or install the suitable debugging package.\n",
780       info->file_name.c_str());
781   // For each compilation unit:
782   Dwarf_Off offset = 0;
783   Dwarf_Off next_offset = 0;
784   size_t length;
785
786   while (dwarf_nextcu(dwarf, offset, &next_offset, &length, NULL, NULL, NULL) ==
787          0) {
788     Dwarf_Die unit_die;
789     if (dwarf_offdie(dwarf, offset + length, &unit_die) != NULL)
790       MC_dwarf_handle_children(info, &unit_die, &unit_die, NULL, NULL);
791     offset = next_offset;
792   }
793
794   dwarf_end(dwarf);
795   close(fd);
796 }