Logo AND Algorithmique Numérique Distribuée

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