Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
eabe5afd9831faff23271a1876dde84638fab711
[simgrid.git] / src / mc / mc_dwarf.c
1 /* Copyright (c) 2008-2014. 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 <stdlib.h>
8 #define DW_LANG_Objc DW_LANG_ObjC       /* fix spelling error in older dwarf.h */
9 #include <dwarf.h>
10 #include <elfutils/libdw.h>
11 #include <inttypes.h>
12
13 #include <simgrid_config.h>
14 #include <xbt/log.h>
15 #include <xbt/sysdep.h>
16
17 #include "mc_private.h"
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
20
21 /** \brief The default DW_TAG_lower_bound for a given DW_AT_language.
22  *
23  *  The default for a given language is defined in the DWARF spec.
24  *
25  *  \param language consant as defined by the DWARf spec
26  */
27 static uint64_t MC_dwarf_default_lower_bound(int lang);
28
29 /** \brief Computes the the element_count of a DW_TAG_enumeration_type DIE
30  *
31  * This is the number of elements in a given array dimension.
32  *
33  * A reference of the compilation unit (DW_TAG_compile_unit) is
34  * needed because the default lower bound (when there is no DW_AT_lower_bound)
35  * depends of the language of the compilation unit (DW_AT_language).
36  *
37  * \param die  DIE for the DW_TAG_enumeration_type or DW_TAG_subrange_type
38  * \param unit DIE of the DW_TAG_compile_unit
39  */
40 static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die,
41                                                 Dwarf_Die * unit);
42
43 /** \brief Computes the number of elements of a given DW_TAG_array_type.
44  *
45  * \param die DIE for the DW_TAG_array_type
46  */
47 static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit);
48
49 /** \brief Process a DIE
50  *
51  *  \param info the resulting object fot the library/binary file (output)
52  *  \param die  the current DIE
53  *  \param unit the DIE of the compile unit of the current DIE
54  *  \param frame containg frame if any
55  */
56 static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
57                                 Dwarf_Die * unit, dw_frame_t frame,
58                                 const char *namespace);
59
60 /** \brief Process a type DIE
61  */
62 static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die * die,
63                                      Dwarf_Die * unit, dw_frame_t frame,
64                                      const char *namespace);
65
66 /** \brief Calls MC_dwarf_handle_die on all childrend of the given die
67  *
68  *  \param info the resulting object fot the library/binary file (output)
69  *  \param die  the current DIE
70  *  \param unit the DIE of the compile unit of the current DIE
71  *  \param frame containg frame if any
72  */
73 static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
74                                      Dwarf_Die * unit, dw_frame_t frame,
75                                      const char *namespace);
76
77 /** \brief Handle a variable (DW_TAG_variable or other)
78  *
79  *  \param info the resulting object fot the library/binary file (output)
80  *  \param die  the current DIE
81  *  \param unit the DIE of the compile unit of the current DIE
82  *  \param frame containg frame if any
83  */
84 static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die * die,
85                                          Dwarf_Die * unit, dw_frame_t frame,
86                                          const char *namespace);
87
88 /** \brief Get the DW_TAG_type of the DIE
89  *
90  *  \param die DIE
91  *  \return DW_TAG_type attribute as a new string (NULL if none)
92  */
93 static char *MC_dwarf_at_type(Dwarf_Die * die);
94
95 /** \brief Get the name of an attribute (DW_AT_*) from its code
96  *
97  *  \param attr attribute code (see the DWARF specification)
98  *  \return name of the attribute
99  */
100 const char *MC_dwarf_attrname(int attr)
101 {
102   switch (attr) {
103 #include "mc_dwarf_attrnames.h"
104   default:
105     return "DW_AT_unknown";
106   }
107 }
108
109 /** \brief Get the name of a dwarf tag (DW_TAG_*) from its code
110  *
111  *  \param tag tag code (see the DWARF specification)
112  *  \return name of the tag
113  */
114 const char *MC_dwarf_tagname(int tag)
115 {
116   switch (tag) {
117 #include "mc_dwarf_tagnames.h"
118   case DW_TAG_invalid:
119     return "DW_TAG_invalid";
120   default:
121     return "DW_TAG_unknown";
122   }
123 }
124
125 /** \brief A class of DWARF tags (DW_TAG_*)
126  */
127 typedef enum mc_tag_class {
128   mc_tag_unknown,
129   mc_tag_type,
130   mc_tag_subprogram,
131   mc_tag_variable,
132   mc_tag_scope,
133   mc_tag_namespace
134 } mc_tag_class;
135
136 static mc_tag_class MC_dwarf_tag_classify(int tag)
137 {
138   switch (tag) {
139
140   case DW_TAG_array_type:
141   case DW_TAG_class_type:
142   case DW_TAG_enumeration_type:
143   case DW_TAG_typedef:
144   case DW_TAG_pointer_type:
145   case DW_TAG_reference_type:
146   case DW_TAG_rvalue_reference_type:
147   case DW_TAG_string_type:
148   case DW_TAG_structure_type:
149   case DW_TAG_subroutine_type:
150   case DW_TAG_union_type:
151   case DW_TAG_ptr_to_member_type:
152   case DW_TAG_set_type:
153   case DW_TAG_subrange_type:
154   case DW_TAG_base_type:
155   case DW_TAG_const_type:
156   case DW_TAG_file_type:
157   case DW_TAG_packed_type:
158   case DW_TAG_volatile_type:
159   case DW_TAG_restrict_type:
160   case DW_TAG_interface_type:
161   case DW_TAG_unspecified_type:
162   case DW_TAG_shared_type:
163     return mc_tag_type;
164
165   case DW_TAG_subprogram:
166     return mc_tag_subprogram;
167
168   case DW_TAG_variable:
169   case DW_TAG_formal_parameter:
170     return mc_tag_variable;
171
172   case DW_TAG_lexical_block:
173   case DW_TAG_try_block:
174   case DW_TAG_catch_block:
175   case DW_TAG_inlined_subroutine:
176   case DW_TAG_with_stmt:
177     return mc_tag_scope;
178
179   case DW_TAG_namespace:
180     return mc_tag_namespace;
181
182   default:
183     return mc_tag_unknown;
184
185   }
186 }
187
188 #define MC_DW_CLASS_UNKNOWN 0
189 #define MC_DW_CLASS_ADDRESS 1   // Location in the address space of the program
190 #define MC_DW_CLASS_BLOCK 2     // Arbitrary block of bytes
191 #define MC_DW_CLASS_CONSTANT 3
192 #define MC_DW_CLASS_STRING 3    // String
193 #define MC_DW_CLASS_FLAG 4      // Boolean
194 #define MC_DW_CLASS_REFERENCE 5 // Reference to another DIE
195 #define MC_DW_CLASS_EXPRLOC 6   // DWARF expression/location description
196 #define MC_DW_CLASS_LINEPTR 7
197 #define MC_DW_CLASS_LOCLISTPTR 8
198 #define MC_DW_CLASS_MACPTR 9
199 #define MC_DW_CLASS_RANGELISTPTR 10
200
201 /** \brief Find the DWARF data class for a given DWARF data form
202  *
203  *  This mapping is defined in the DWARF spec.
204  *
205  *  \param form The form (values taken from the DWARF spec)
206  *  \return An internal representation for the corresponding class
207  * */
208 static int MC_dwarf_form_get_class(int form)
209 {
210   switch (form) {
211   case DW_FORM_addr:
212     return MC_DW_CLASS_ADDRESS;
213   case DW_FORM_block2:
214   case DW_FORM_block4:
215   case DW_FORM_block:
216   case DW_FORM_block1:
217     return MC_DW_CLASS_BLOCK;
218   case DW_FORM_data1:
219   case DW_FORM_data2:
220   case DW_FORM_data4:
221   case DW_FORM_data8:
222   case DW_FORM_udata:
223   case DW_FORM_sdata:
224     return MC_DW_CLASS_CONSTANT;
225   case DW_FORM_string:
226   case DW_FORM_strp:
227     return MC_DW_CLASS_STRING;
228   case DW_FORM_ref_addr:
229   case DW_FORM_ref1:
230   case DW_FORM_ref2:
231   case DW_FORM_ref4:
232   case DW_FORM_ref8:
233   case DW_FORM_ref_udata:
234     return MC_DW_CLASS_REFERENCE;
235   case DW_FORM_flag:
236   case DW_FORM_flag_present:
237     return MC_DW_CLASS_FLAG;
238   case DW_FORM_exprloc:
239     return MC_DW_CLASS_EXPRLOC;
240     // TODO sec offset
241     // TODO indirect
242   default:
243     return MC_DW_CLASS_UNKNOWN;
244   }
245 }
246
247 /** \brief Get the name of the tag of a given DIE
248  *
249  *  \param die DIE
250  *  \return name of the tag of this DIE
251  */
252 static inline const char *MC_dwarf_die_tagname(Dwarf_Die * die)
253 {
254   return MC_dwarf_tagname(dwarf_tag(die));
255 }
256
257 // ***** Attributes
258
259 /** \brief Get an attribute of a given DIE as a string
260  *
261  *  \param die       the DIE
262  *  \param attribute attribute
263  *  \return value of the given attribute of the given DIE
264  */
265 static const char *MC_dwarf_attr_integrate_string(Dwarf_Die * die,
266                                                   int attribute)
267 {
268   Dwarf_Attribute attr;
269   if (!dwarf_attr_integrate(die, attribute, &attr)) {
270     return NULL;
271   } else {
272     return dwarf_formstring(&attr);
273   }
274 }
275
276 /** \brief Get the linkage name of a DIE.
277  *
278  *  Use either DW_AT_linkage_name or DW_AT_MIPS_linkage_name.
279  *  DW_AT_linkage_name is standardized since DWARF 4.
280  *  Before this version of DWARF, the MIPS extensions
281  *  DW_AT_MIPS_linkage_name is used (at least by GCC).
282  *
283  *  \param  the DIE
284  *  \return linkage name of the given DIE (or NULL)
285  * */
286 static const char *MC_dwarf_at_linkage_name(Dwarf_Die * die)
287 {
288   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_linkage_name);
289   if (!name)
290     name = MC_dwarf_attr_integrate_string(die, DW_AT_MIPS_linkage_name);
291   return name;
292 }
293
294 static Dwarf_Off MC_dwarf_attr_dieoffset(Dwarf_Die * die, int attribute)
295 {
296   Dwarf_Attribute attr;
297   if (dwarf_hasattr_integrate(die, attribute)) {
298     dwarf_attr_integrate(die, attribute, &attr);
299     Dwarf_Die subtype_die;
300     if (dwarf_formref_die(&attr, &subtype_die) == NULL) {
301       xbt_die("Could not find DIE");
302     }
303     return dwarf_dieoffset(&subtype_die);
304   } else
305     return 0;
306 }
307
308 static Dwarf_Off MC_dwarf_attr_integrate_dieoffset(Dwarf_Die * die,
309                                                    int attribute)
310 {
311   Dwarf_Attribute attr;
312   if (dwarf_hasattr_integrate(die, attribute)) {
313     dwarf_attr_integrate(die, DW_AT_type, &attr);
314     Dwarf_Die subtype_die;
315     if (dwarf_formref_die(&attr, &subtype_die) == NULL) {
316       xbt_die("Could not find DIE");
317     }
318     return dwarf_dieoffset(&subtype_die);
319   } else
320     return 0;
321 }
322
323 /** \brief Find the type/subtype (DW_AT_type) for a DIE
324  *
325  *  \param dit the DIE
326  *  \return DW_AT_type reference as a global offset in hexadecimal (or NULL)
327  */
328 static char *MC_dwarf_at_type(Dwarf_Die * die)
329 {
330   Dwarf_Off offset = MC_dwarf_attr_integrate_dieoffset(die, DW_AT_type);
331   return offset == 0 ? NULL : bprintf("%" PRIx64, offset);
332 }
333
334 static uint64_t MC_dwarf_attr_integrate_addr(Dwarf_Die * die, int attribute)
335 {
336   Dwarf_Attribute attr;
337   if (dwarf_attr_integrate(die, attribute, &attr) == NULL)
338     return 0;
339   Dwarf_Addr value;
340   if (dwarf_formaddr(&attr, &value) == 0)
341     return (uint64_t) value;
342   else
343     return 0;
344 }
345
346 static uint64_t MC_dwarf_attr_integrate_uint(Dwarf_Die * die, int attribute,
347                                              uint64_t default_value)
348 {
349   Dwarf_Attribute attr;
350   if (dwarf_attr_integrate(die, attribute, &attr) == NULL)
351     return default_value;
352   Dwarf_Word value;
353   return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr),
354                          &value) == 0 ? (uint64_t) value : default_value;
355 }
356
357 static bool MC_dwarf_attr_flag(Dwarf_Die * die, int attribute, bool integrate)
358 {
359   Dwarf_Attribute attr;
360   if ((integrate ? dwarf_attr_integrate(die, attribute, &attr)
361        : dwarf_attr(die, attribute, &attr)) == 0)
362     return false;
363
364   bool result;
365   if (dwarf_formflag(&attr, &result))
366     xbt_die("Unexpected form for attribute %s", MC_dwarf_attrname(attribute));
367   return result;
368 }
369
370 /** \brief Find the default lower bound for a given language
371  *
372  *  The default lower bound of an array (when DW_TAG_lower_bound
373  *  is missing) depends on the language of the compilation unit.
374  *
375  *  \param lang Language of the compilation unit (values defined in the DWARF spec)
376  *  \return     Default lower bound of an array in this compilation unit
377  * */
378 static uint64_t MC_dwarf_default_lower_bound(int lang)
379 {
380   switch (lang) {
381   case DW_LANG_C:
382   case DW_LANG_C89:
383   case DW_LANG_C99:
384   case DW_LANG_C_plus_plus:
385   case DW_LANG_D:
386   case DW_LANG_Java:
387   case DW_LANG_ObjC:
388   case DW_LANG_ObjC_plus_plus:
389   case DW_LANG_Python:
390   case DW_LANG_UPC:
391     return 0;
392   case DW_LANG_Ada83:
393   case DW_LANG_Ada95:
394   case DW_LANG_Fortran77:
395   case DW_LANG_Fortran90:
396   case DW_LANG_Fortran95:
397   case DW_LANG_Modula2:
398   case DW_LANG_Pascal83:
399   case DW_LANG_PL1:
400   case DW_LANG_Cobol74:
401   case DW_LANG_Cobol85:
402     return 1;
403   default:
404     xbt_die("No default DW_TAG_lower_bound for language %i and none given",
405             lang);
406     return 0;
407   }
408 }
409
410 /** \brief Finds the number of elements in a DW_TAG_subrange_type or DW_TAG_enumeration_type DIE
411  *
412  *  \param die  the DIE
413  *  \param unit DIE of the compilation unit
414  *  \return     number of elements in the range
415  * */
416 static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die,
417                                                 Dwarf_Die * unit)
418 {
419   xbt_assert(dwarf_tag(die) == DW_TAG_enumeration_type
420              || dwarf_tag(die) == DW_TAG_subrange_type,
421              "MC_dwarf_subrange_element_count called with DIE of type %s",
422              MC_dwarf_die_tagname(die));
423
424   // Use DW_TAG_count if present:
425   if (dwarf_hasattr_integrate(die, DW_AT_count)) {
426     return MC_dwarf_attr_integrate_uint(die, DW_AT_count, 0);
427   }
428   // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1:
429
430   if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound)) {
431     // This is not really 0, but the code expects this (we do not know):
432     return 0;
433   }
434   uint64_t upper_bound =
435       MC_dwarf_attr_integrate_uint(die, DW_AT_upper_bound, -1);
436
437   uint64_t lower_bound = 0;
438   if (dwarf_hasattr_integrate(die, DW_AT_lower_bound)) {
439     lower_bound = MC_dwarf_attr_integrate_uint(die, DW_AT_lower_bound, -1);
440   } else {
441     lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit));
442   }
443   return upper_bound - lower_bound + 1;
444 }
445
446 /** \brief Finds the number of elements in a array type (DW_TAG_array_type)
447  *
448  *  The compilation unit might be needed because the default lower
449  *  bound depends on the language of the compilation unit.
450  *
451  *  \param die the DIE of the DW_TAG_array_type
452  *  \param unit the DIE of the compilation unit
453  *  \return number of elements in this array type
454  * */
455 static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit)
456 {
457   xbt_assert(dwarf_tag(die) == DW_TAG_array_type,
458              "MC_dwarf_array_element_count called with DIE of type %s",
459              MC_dwarf_die_tagname(die));
460
461   int result = 1;
462   Dwarf_Die child;
463   int res;
464   for (res = dwarf_child(die, &child); res == 0;
465        res = dwarf_siblingof(&child, &child)) {
466     int child_tag = dwarf_tag(&child);
467     if (child_tag == DW_TAG_subrange_type
468         || child_tag == DW_TAG_enumeration_type) {
469       result *= MC_dwarf_subrange_element_count(&child, unit);
470     }
471   }
472   return result;
473 }
474
475 // ***** dw_type_t
476
477 /** \brief Initialize the location of a member of a type
478  * (DW_AT_data_member_location of a DW_TAG_member).
479  *
480  *  \param  type   a type (struct, class)
481  *  \param  member the member of the type
482  *  \param  child  DIE of the member (DW_TAG_member)
483  */
484 static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member,
485                                           Dwarf_Die * child)
486 {
487   if (dwarf_hasattr(child, DW_AT_data_bit_offset)) {
488     xbt_die("Can't groke DW_AT_data_bit_offset.");
489   }
490
491   if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
492     if (type->type != DW_TAG_union_type) {
493       xbt_die
494           ("Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%"
495            PRIx64 ">%s", member->name, (uint64_t) type->id, type->name);
496     } else {
497       return;
498     }
499   }
500
501   Dwarf_Attribute attr;
502   dwarf_attr_integrate(child, DW_AT_data_member_location, &attr);
503   int form = dwarf_whatform(&attr);
504   int klass = MC_dwarf_form_get_class(form);
505   switch (klass) {
506   case MC_DW_CLASS_EXPRLOC:
507   case MC_DW_CLASS_BLOCK:
508     // Location expression:
509     {
510       Dwarf_Op *expr;
511       size_t len;
512       if (dwarf_getlocation(&attr, &expr, &len)) {
513         xbt_die
514             ("Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%"
515              PRIx64 ">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name),
516              (uint64_t) type->id, type->name);
517       }
518       if (len == 1 && expr[0].atom == DW_OP_plus_uconst) {
519         member->offset = expr[0].number;
520       } else {
521         mc_dwarf_expression_init(&member->location, len, expr);
522       }
523       break;
524     }
525   case MC_DW_CLASS_CONSTANT:
526     // Offset from the base address of the object:
527     {
528       Dwarf_Word offset;
529       if (!dwarf_formudata(&attr, &offset))
530         member->offset = offset;
531       else
532         xbt_die("Cannot get %s location <%" PRIx64 ">%s",
533                 MC_dwarf_attr_integrate_string(child, DW_AT_name),
534                 (uint64_t) type->id, type->name);
535       break;
536     }
537   case MC_DW_CLASS_LOCLISTPTR:
538     // Reference to a location list:
539     // TODO
540   case MC_DW_CLASS_REFERENCE:
541     // It's supposed to be possible in DWARF2 but I couldn't find its semantic
542     // in the spec.
543   default:
544     xbt_die("Can't handle form class (%i) / form 0x%x as DW_AT_member_location",
545             klass, form);
546   }
547
548 }
549
550 static void dw_type_free_voidp(void *t)
551 {
552   dw_type_free((dw_type_t) * (void **) t);
553 }
554
555 /** \brief Populate the list of members of a type
556  *
557  *  \param info ELF object containing the type DIE
558  *  \param die  DIE of the type
559  *  \param unit DIE of the compilation unit containing the type DIE
560  *  \param type the type
561  */
562 static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die * die,
563                                  Dwarf_Die * unit, dw_type_t type)
564 {
565   int res;
566   Dwarf_Die child;
567   xbt_assert(!type->members);
568   type->members =
569       xbt_dynar_new(sizeof(dw_type_t), (void (*)(void *)) dw_type_free_voidp);
570   for (res = dwarf_child(die, &child); res == 0;
571        res = dwarf_siblingof(&child, &child)) {
572     int tag = dwarf_tag(&child);
573     if (tag == DW_TAG_member || tag == DW_TAG_inheritance) {
574
575       // Skip declarations:
576       if (MC_dwarf_attr_flag(&child, DW_AT_declaration, false))
577         continue;
578
579       // Skip compile time constants:
580       if (dwarf_hasattr(&child, DW_AT_const_value))
581         continue;
582
583       // TODO, we should use another type (because is is not a type but a member)
584       dw_type_t member = xbt_new0(s_dw_type_t, 1);
585       member->type = tag;
586
587       // Global Offset:
588       member->id = dwarf_dieoffset(&child);
589
590       const char *name = MC_dwarf_attr_integrate_string(&child, DW_AT_name);
591       if (name)
592         member->name = xbt_strdup(name);
593       else
594         member->name = NULL;
595
596       member->byte_size =
597           MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0);
598       member->element_count = -1;
599       member->dw_type_id = MC_dwarf_at_type(&child);
600       member->members = NULL;
601       member->is_pointer_type = 0;
602       member->offset = 0;
603
604       if (dwarf_hasattr(&child, DW_AT_data_bit_offset)) {
605         xbt_die("Can't groke DW_AT_data_bit_offset.");
606       }
607
608       MC_dwarf_fill_member_location(type, member, &child);
609
610       if (!member->dw_type_id) {
611         xbt_die("Missing type for member %s of <%" PRIx64 ">%s", member->name,
612                 (uint64_t) type->id, type->name);
613       }
614
615       xbt_dynar_push(type->members, &member);
616     }
617   }
618 }
619
620 /** \brief Create a MC type object from a DIE
621  *
622  *  \param info current object info object
623  *  \param DIE (for a given type);
624  *  \param unit compilation unit of the current DIE
625  *  \return MC representation of the type
626  */
627 static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die * die,
628                                       Dwarf_Die * unit, dw_frame_t frame,
629                                       const char *namespace)
630 {
631
632   dw_type_t type = xbt_new0(s_dw_type_t, 1);
633   type->type = -1;
634   type->id = 0;
635   type->name = NULL;
636   type->byte_size = 0;
637   type->element_count = -1;
638   type->dw_type_id = NULL;
639   type->members = NULL;
640   type->is_pointer_type = 0;
641   type->offset = 0;
642
643   type->type = dwarf_tag(die);
644
645   // Global Offset
646   type->id = dwarf_dieoffset(die);
647
648   const char *prefix = "";
649   switch (type->type) {
650   case DW_TAG_structure_type:
651     prefix = "struct ";
652     break;
653   case DW_TAG_union_type:
654     prefix = "union ";
655     break;
656   case DW_TAG_class_type:
657     prefix = "class ";
658     break;
659   default:
660     prefix = "";
661   }
662
663   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
664   if (name != NULL) {
665     type->name =
666         namespace ? bprintf("%s%s::%s", prefix, namespace,
667                             name) : bprintf("%s%s", prefix, name);
668   }
669
670   type->dw_type_id = MC_dwarf_at_type(die);
671
672   // Computation of the byte_size;
673   if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
674     type->byte_size = MC_dwarf_attr_integrate_uint(die, DW_AT_byte_size, 0);
675   else if (type->type == DW_TAG_array_type
676            || type->type == DW_TAG_structure_type
677            || type->type == DW_TAG_class_type) {
678     Dwarf_Word size;
679     if (dwarf_aggregate_size(die, &size) == 0) {
680       type->byte_size = size;
681     }
682   }
683
684   switch (type->type) {
685   case DW_TAG_array_type:
686     type->element_count = MC_dwarf_array_element_count(die, unit);
687     // TODO, handle DW_byte_stride and (not) DW_bit_stride
688     break;
689
690   case DW_TAG_pointer_type:
691   case DW_TAG_reference_type:
692   case DW_TAG_rvalue_reference_type:
693     type->is_pointer_type = 1;
694     break;
695
696   case DW_TAG_structure_type:
697   case DW_TAG_union_type:
698   case DW_TAG_class_type:
699     MC_dwarf_add_members(info, die, unit, type);
700     char *new_namespace = namespace == NULL ? xbt_strdup(type->name)
701         : bprintf("%s::%s", namespace, name);
702     MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
703     free(new_namespace);
704     break;
705   }
706
707   return type;
708 }
709
710 static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die * die,
711                                      Dwarf_Die * unit, dw_frame_t frame,
712                                      const char *namespace)
713 {
714   dw_type_t type = MC_dwarf_die_to_type(info, die, unit, frame, namespace);
715
716   char *key = bprintf("%" PRIx64, (uint64_t) type->id);
717   xbt_dict_set(info->types, key, type, NULL);
718   xbt_free(key);
719
720   if (type->name && type->byte_size != 0) {
721     xbt_dict_set(info->full_types_by_name, type->name, type, NULL);
722   }
723 }
724
725 static int mc_anonymous_variable_index = 0;
726
727 static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die * die,
728                                         Dwarf_Die * unit, dw_frame_t frame,
729                                         const char *namespace)
730 {
731   // Skip declarations:
732   if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
733     return NULL;
734
735   // Skip compile time constants:
736   if (dwarf_hasattr(die, DW_AT_const_value))
737     return NULL;
738
739   Dwarf_Attribute attr_location;
740   if (dwarf_attr(die, DW_AT_location, &attr_location) == NULL) {
741     // No location: do not add it ?
742     return NULL;
743   }
744
745   dw_variable_t variable = xbt_new0(s_dw_variable_t, 1);
746   variable->dwarf_offset = dwarf_dieoffset(die);
747   variable->global = frame == NULL;     // Can be override base on DW_AT_location
748   variable->object_info = info;
749
750   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
751   variable->name = xbt_strdup(name);
752
753   variable->type_origin = MC_dwarf_at_type(die);
754
755   int form = dwarf_whatform(&attr_location);
756   int klass =
757       form ==
758       DW_FORM_sec_offset ? MC_DW_CLASS_CONSTANT : MC_dwarf_form_get_class(form);
759   switch (klass) {
760   case MC_DW_CLASS_EXPRLOC:
761   case MC_DW_CLASS_BLOCK:
762     // Location expression:
763     {
764       Dwarf_Op *expr;
765       size_t len;
766       if (dwarf_getlocation(&attr_location, &expr, &len)) {
767         xbt_die
768             ("Could not read location expression in DW_AT_location of variable <%"
769              PRIx64 ">%s", (uint64_t) variable->dwarf_offset, variable->name);
770       }
771
772       if (len == 1 && expr[0].atom == DW_OP_addr) {
773         variable->global = 1;
774         uintptr_t offset = (uintptr_t) expr[0].number;
775         uintptr_t base = (uintptr_t) MC_object_base_address(info);
776         variable->address = (void *) (base + offset);
777       } else {
778         mc_dwarf_location_list_init_from_expression(&variable->locations, len,
779                                                     expr);
780       }
781
782       break;
783     }
784   case MC_DW_CLASS_LOCLISTPTR:
785   case MC_DW_CLASS_CONSTANT:
786     // Reference to location list:
787     mc_dwarf_location_list_init(&variable->locations, info, die,
788                                 &attr_location);
789     break;
790   default:
791     xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%"
792             PRIx64 ">%s", form, form, klass, klass,
793             (uint64_t) variable->dwarf_offset, variable->name);
794   }
795
796   // Handle start_scope:
797   if (dwarf_hasattr(die, DW_AT_start_scope)) {
798     Dwarf_Attribute attr;
799     dwarf_attr(die, DW_AT_start_scope, &attr);
800     int form = dwarf_whatform(&attr);
801     int klass = MC_dwarf_form_get_class(form);
802     switch (klass) {
803     case MC_DW_CLASS_CONSTANT:
804       {
805         Dwarf_Word value;
806         variable->start_scope =
807             dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
808         break;
809       }
810     case MC_DW_CLASS_RANGELISTPTR:     // TODO
811     default:
812       xbt_die
813           ("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
814            form, klass, name == NULL ? "?" : name);
815     }
816   }
817
818   if (namespace && variable->global) {
819     char *old_name = variable->name;
820     variable->name = bprintf("%s::%s", namespace, old_name);
821     free(old_name);
822   }
823   // The current code needs a variable name,
824   // generate a fake one:
825   if (!variable->name) {
826     variable->name = bprintf("@anonymous#%i", mc_anonymous_variable_index++);
827   }
828
829   return variable;
830 }
831
832 static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die * die,
833                                          Dwarf_Die * unit, dw_frame_t frame,
834                                          const char *namespace)
835 {
836   dw_variable_t variable =
837       MC_die_to_variable(info, die, unit, frame, namespace);
838   if (variable == NULL)
839     return;
840   MC_dwarf_register_variable(info, frame, variable);
841 }
842
843 static void mc_frame_free_voipd(dw_frame_t * p)
844 {
845   mc_frame_free(*p);
846   *p = NULL;
847 }
848
849 static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die * die,
850                                       Dwarf_Die * unit, dw_frame_t parent_frame,
851                                       const char *namespace)
852 {
853   // TODO, handle DW_TAG_type/DW_TAG_location for DW_TAG_with_stmt
854   int tag = dwarf_tag(die);
855   mc_tag_class klass = MC_dwarf_tag_classify(tag);
856
857   // (Template) Subprogram declaration:
858   if (klass == mc_tag_subprogram
859       && MC_dwarf_attr_flag(die, DW_AT_declaration, false))
860     return;
861
862   if (klass == mc_tag_scope)
863     xbt_assert(parent_frame, "No parent scope for this scope");
864
865   dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
866
867   frame->tag = tag;
868   frame->id = dwarf_dieoffset(die);
869   frame->object_info = info;
870
871   if (klass == mc_tag_subprogram) {
872     const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
873     frame->name =
874         namespace ? bprintf("%s::%s", namespace, name) : xbt_strdup(name);
875   }
876
877   frame->abstract_origin_id =
878       MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin);
879
880   // This is the base address for DWARF addresses.
881   // Relocated addresses are offset from this base address.
882   // See DWARF4 spec 7.5
883   void *base = MC_object_base_address(info);
884
885   // Variables are filled in the (recursive) call of MC_dwarf_handle_children:
886   frame->variables =
887       xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
888
889   // TODO, support DW_AT_ranges
890   uint64_t low_pc = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc);
891   frame->low_pc = low_pc ? ((char *) base) + low_pc : 0;
892   if (low_pc) {
893     // DW_AT_high_pc:
894     Dwarf_Attribute attr;
895     if (!dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) {
896       xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc");
897     }
898
899     Dwarf_Sword offset;
900     Dwarf_Addr high_pc;
901
902     switch (MC_dwarf_form_get_class(dwarf_whatform(&attr))) {
903
904       // DW_AT_high_pc if an offset from the low_pc:
905     case MC_DW_CLASS_CONSTANT:
906
907       if (dwarf_formsdata(&attr, &offset) != 0)
908         xbt_die("Could not read constant");
909       frame->high_pc = (void *) ((char *) frame->low_pc + offset);
910       break;
911
912       // DW_AT_high_pc is a relocatable address:
913     case MC_DW_CLASS_ADDRESS:
914       if (dwarf_formaddr(&attr, &high_pc) != 0)
915         xbt_die("Could not read address");
916       frame->high_pc = ((char *) base) + high_pc;
917       break;
918
919     default:
920       xbt_die("Unexpected class for DW_AT_high_pc");
921
922     }
923   }
924
925   if (klass == mc_tag_subprogram) {
926     Dwarf_Attribute attr_frame_base;
927     if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base))
928       mc_dwarf_location_list_init(&frame->frame_base, info, die,
929                                   &attr_frame_base);
930   }
931
932   frame->scopes =
933       xbt_dynar_new(sizeof(dw_frame_t), (void_f_pvoid_t) mc_frame_free_voipd);
934
935   // Register it:
936   if (klass == mc_tag_subprogram) {
937     char *key = bprintf("%" PRIx64, (uint64_t) frame->id);
938     xbt_dict_set(info->subprograms, key, frame, NULL);
939     xbt_free(key);
940   } else if (klass == mc_tag_scope) {
941     xbt_dynar_push(parent_frame->scopes, &frame);
942   }
943   // Handle children:
944   MC_dwarf_handle_children(info, die, unit, frame, namespace);
945 }
946
947 static void mc_dwarf_handle_namespace_die(mc_object_info_t info,
948                                           Dwarf_Die * die, Dwarf_Die * unit,
949                                           dw_frame_t frame,
950                                           const char *namespace)
951 {
952   const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
953   if (frame)
954     xbt_die("Unexpected namespace in a subprogram");
955   char *new_namespace = namespace == NULL ? xbt_strdup(name)
956       : bprintf("%s::%s", namespace, name);
957   MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
958   xbt_free(new_namespace);
959 }
960
961 static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
962                                      Dwarf_Die * unit, dw_frame_t frame,
963                                      const char *namespace)
964 {
965   // For each child DIE:
966   Dwarf_Die child;
967   int res;
968   for (res = dwarf_child(die, &child); res == 0;
969        res = dwarf_siblingof(&child, &child)) {
970     MC_dwarf_handle_die(info, &child, unit, frame, namespace);
971   }
972 }
973
974 static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
975                                 Dwarf_Die * unit, dw_frame_t frame,
976                                 const char *namespace)
977 {
978   int tag = dwarf_tag(die);
979   mc_tag_class klass = MC_dwarf_tag_classify(tag);
980   switch (klass) {
981
982     // Type:
983   case mc_tag_type:
984     MC_dwarf_handle_type_die(info, die, unit, frame, namespace);
985     break;
986
987     // Subprogram or scope:
988   case mc_tag_subprogram:
989   case mc_tag_scope:
990     MC_dwarf_handle_scope_die(info, die, unit, frame, namespace);
991     return;
992
993     // Variable:
994   case mc_tag_variable:
995     MC_dwarf_handle_variable_die(info, die, unit, frame, namespace);
996     break;
997
998   case mc_tag_namespace:
999     mc_dwarf_handle_namespace_die(info, die, unit, frame, namespace);
1000     break;
1001
1002   default:
1003     break;
1004
1005   }
1006 }
1007
1008 /** \brief Populate the debugging informations of the given ELF object
1009  *
1010  *  Read the DWARf information of the EFFL object and populate the
1011  *  lists of types, variables, functions.
1012  */
1013 void MC_dwarf_get_variables(mc_object_info_t info)
1014 {
1015   int fd = open(info->file_name, O_RDONLY);
1016   if (fd < 0) {
1017     xbt_die("Could not open file %s", info->file_name);
1018   }
1019   Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
1020   if (dwarf == NULL) {
1021     xbt_die("Your program must be compiled with -g");
1022   }
1023   // For each compilation unit:
1024   Dwarf_Off offset = 0;
1025   Dwarf_Off next_offset = 0;
1026   size_t length;
1027   while (dwarf_nextcu(dwarf, offset, &next_offset, &length, NULL, NULL, NULL) ==
1028          0) {
1029     Dwarf_Die unit_die;
1030     if (dwarf_offdie(dwarf, offset + length, &unit_die) != NULL) {
1031
1032       // For each child DIE:
1033       Dwarf_Die child;
1034       int res;
1035       for (res = dwarf_child(&unit_die, &child); res == 0;
1036            res = dwarf_siblingof(&child, &child)) {
1037         MC_dwarf_handle_die(info, &child, &unit_die, NULL, NULL);
1038       }
1039
1040     }
1041     offset = next_offset;
1042   }
1043
1044   dwarf_end(dwarf);
1045   close(fd);
1046 }
1047
1048 /************************** Free functions *************************/
1049
1050 void mc_frame_free(dw_frame_t frame)
1051 {
1052   xbt_free(frame->name);
1053   mc_dwarf_location_list_clear(&(frame->frame_base));
1054   xbt_dynar_free(&(frame->variables));
1055   xbt_dynar_free(&(frame->scopes));
1056   xbt_free(frame);
1057 }
1058
1059 void dw_type_free(dw_type_t t)
1060 {
1061   xbt_free(t->name);
1062   xbt_free(t->dw_type_id);
1063   xbt_dynar_free(&(t->members));
1064   mc_dwarf_expression_clear(&t->location);
1065   xbt_free(t);
1066 }
1067
1068 void dw_variable_free(dw_variable_t v)
1069 {
1070   if (v) {
1071     xbt_free(v->name);
1072     xbt_free(v->type_origin);
1073
1074     if (v->locations.locations)
1075       mc_dwarf_location_list_clear(&v->locations);
1076     xbt_free(v);
1077   }
1078 }
1079
1080 void dw_variable_free_voidp(void *t)
1081 {
1082   dw_variable_free((dw_variable_t) * (void **) t);
1083 }
1084
1085 // ***** object_info
1086
1087
1088
1089 mc_object_info_t MC_new_object_info(void)
1090 {
1091   mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
1092   res->subprograms = xbt_dict_new_homogeneous((void (*)(void *)) mc_frame_free);
1093   res->global_variables =
1094       xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
1095   res->types = xbt_dict_new_homogeneous((void (*)(void *)) dw_type_free);
1096   res->full_types_by_name = xbt_dict_new_homogeneous(NULL);
1097   return res;
1098 }
1099
1100 void MC_free_object_info(mc_object_info_t * info)
1101 {
1102   xbt_free(&(*info)->file_name);
1103   xbt_dict_free(&(*info)->subprograms);
1104   xbt_dynar_free(&(*info)->global_variables);
1105   xbt_dict_free(&(*info)->types);
1106   xbt_dict_free(&(*info)->full_types_by_name);
1107   xbt_free(info);
1108   xbt_dynar_free(&(*info)->functions_index);
1109   *info = NULL;
1110 }
1111
1112 // ***** Helpers
1113
1114 void *MC_object_base_address(mc_object_info_t info)
1115 {
1116   if (info->flags & MC_OBJECT_INFO_EXECUTABLE)
1117     return 0;
1118   void *result = info->start_exec;
1119   if (info->start_rw != NULL && result > (void *) info->start_rw)
1120     result = info->start_rw;
1121   if (info->start_ro != NULL && result > (void *) info->start_ro)
1122     result = info->start_ro;
1123   return result;
1124 }
1125
1126 // ***** Functions index
1127
1128 static int MC_compare_frame_index_items(mc_function_index_item_t a,
1129                                         mc_function_index_item_t b)
1130 {
1131   if (a->low_pc < b->low_pc)
1132     return -1;
1133   else if (a->low_pc == b->low_pc)
1134     return 0;
1135   else
1136     return 1;
1137 }
1138
1139 static void MC_make_functions_index(mc_object_info_t info)
1140 {
1141   xbt_dynar_t index = xbt_dynar_new(sizeof(s_mc_function_index_item_t), NULL);
1142
1143   // Populate the array:
1144   dw_frame_t frame = NULL;
1145   xbt_dict_cursor_t cursor;
1146   char *key;
1147   xbt_dict_foreach(info->subprograms, cursor, key, frame) {
1148     if (frame->low_pc == NULL)
1149       continue;
1150     s_mc_function_index_item_t entry;
1151     entry.low_pc = frame->low_pc;
1152     entry.high_pc = frame->high_pc;
1153     entry.function = frame;
1154     xbt_dynar_push(index, &entry);
1155   }
1156
1157   mc_function_index_item_t base =
1158       (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
1159
1160   // Sort the array by low_pc:
1161   qsort(base,
1162         xbt_dynar_length(index),
1163         sizeof(s_mc_function_index_item_t),
1164         (int (*)(const void *, const void *)) MC_compare_frame_index_items);
1165
1166   info->functions_index = index;
1167 }
1168
1169 mc_object_info_t MC_ip_find_object_info(void *ip)
1170 {
1171   size_t i;
1172   for (i = 0; i != mc_object_infos_size; ++i) {
1173     if (ip >= (void *) mc_object_infos[i]->start_exec
1174         && ip <= (void *) mc_object_infos[i]->end_exec) {
1175       return mc_object_infos[i];
1176     }
1177   }
1178   return NULL;
1179 }
1180
1181 static dw_frame_t MC_find_function_by_ip_and_object(void *ip,
1182                                                     mc_object_info_t info)
1183 {
1184   xbt_dynar_t dynar = info->functions_index;
1185   mc_function_index_item_t base =
1186       (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
1187   int i = 0;
1188   int j = xbt_dynar_length(dynar) - 1;
1189   while (j >= i) {
1190     int k = i + ((j - i) / 2);
1191     if (ip < base[k].low_pc) {
1192       j = k - 1;
1193     } else if (ip >= base[k].high_pc) {
1194       i = k + 1;
1195     } else {
1196       return base[k].function;
1197     }
1198   }
1199   return NULL;
1200 }
1201
1202 dw_frame_t MC_find_function_by_ip(void *ip)
1203 {
1204   mc_object_info_t info = MC_ip_find_object_info(ip);
1205   if (info == NULL)
1206     return NULL;
1207   else
1208     return MC_find_function_by_ip_and_object(ip, info);
1209 }
1210
1211 static void MC_post_process_variables(mc_object_info_t info)
1212 {
1213   unsigned cursor = 0;
1214   dw_variable_t variable = NULL;
1215   xbt_dynar_foreach(info->global_variables, cursor, variable) {
1216     if (variable->type_origin) {
1217       variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
1218     }
1219   }
1220 }
1221
1222 static void mc_post_process_scope(mc_object_info_t info, dw_frame_t scope)
1223 {
1224
1225   if (scope->tag == DW_TAG_inlined_subroutine) {
1226
1227     // Attach correct namespaced name in inlined subroutine:
1228     char *key = bprintf("%" PRIx64, (uint64_t) scope->abstract_origin_id);
1229     dw_frame_t abstract_origin = xbt_dict_get_or_null(info->subprograms, key);
1230     xbt_assert(abstract_origin, "Could not lookup abstract origin %s", key);
1231     xbt_free(key);
1232     scope->name = xbt_strdup(abstract_origin->name);
1233
1234   }
1235   // Direct:
1236   unsigned cursor = 0;
1237   dw_variable_t variable = NULL;
1238   xbt_dynar_foreach(scope->variables, cursor, variable) {
1239     if (variable->type_origin) {
1240       variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
1241     }
1242   }
1243
1244   // Recursive post-processing of nested-scopes:
1245   dw_frame_t nested_scope = NULL;
1246   xbt_dynar_foreach(scope->scopes, cursor, nested_scope)
1247       mc_post_process_scope(info, nested_scope);
1248
1249 }
1250
1251 static void MC_post_process_functions(mc_object_info_t info)
1252 {
1253   xbt_dict_cursor_t cursor;
1254   char *key;
1255   dw_frame_t subprogram = NULL;
1256   xbt_dict_foreach(info->subprograms, cursor, key, subprogram) {
1257     mc_post_process_scope(info, subprogram);
1258   }
1259 }
1260
1261
1262 /** \brief Fill/lookup the "subtype" field.
1263  */
1264 static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type)
1265 {
1266
1267   if (type->dw_type_id == NULL)
1268     return;
1269   type->subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
1270   if (type->subtype == NULL)
1271     return;
1272   if (type->subtype->byte_size != 0)
1273     return;
1274   if (type->subtype->name == NULL)
1275     return;
1276   // Try to find a more complete description of the type:
1277   // We need to fix in order to support C++.
1278
1279   dw_type_t subtype =
1280       xbt_dict_get_or_null(info->full_types_by_name, type->subtype->name);
1281   if (subtype != NULL) {
1282     type->subtype = subtype;
1283   }
1284
1285 }
1286
1287 static void MC_post_process_types(mc_object_info_t info)
1288 {
1289   xbt_dict_cursor_t cursor = NULL;
1290   char *origin;
1291   dw_type_t type;
1292
1293   // Lookup "subtype" field:
1294   xbt_dict_foreach(info->types, cursor, origin, type) {
1295     MC_resolve_subtype(info, type);
1296
1297     dw_type_t member;
1298     unsigned int i = 0;
1299     if (type->members != NULL)
1300       xbt_dynar_foreach(type->members, i, member) {
1301       MC_resolve_subtype(info, member);
1302       }
1303   }
1304 }
1305
1306 /** \brief Finds informations about a given shared object/executable */
1307 mc_object_info_t MC_find_object_info(memory_map_t maps, char *name,
1308                                      int executable)
1309 {
1310   mc_object_info_t result = MC_new_object_info();
1311   if (executable)
1312     result->flags |= MC_OBJECT_INFO_EXECUTABLE;
1313   result->file_name = xbt_strdup(name);
1314   MC_find_object_address(maps, result);
1315   MC_dwarf_get_variables(result);
1316   MC_post_process_types(result);
1317   MC_post_process_variables(result);
1318   MC_post_process_functions(result);
1319   MC_make_functions_index(result);
1320   return result;
1321 }
1322
1323 /*************************************************************************/
1324
1325 static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char *var,
1326                                        void *address)
1327 {
1328
1329   if (xbt_dynar_is_empty(variables))
1330     return 0;
1331
1332   unsigned int cursor = 0;
1333   int start = 0;
1334   int end = xbt_dynar_length(variables) - 1;
1335   dw_variable_t var_test = NULL;
1336
1337   while (start <= end) {
1338     cursor = (start + end) / 2;
1339     var_test =
1340         (dw_variable_t) xbt_dynar_get_as(variables, cursor, dw_variable_t);
1341     if (strcmp(var_test->name, var) < 0) {
1342       start = cursor + 1;
1343     } else if (strcmp(var_test->name, var) > 0) {
1344       end = cursor - 1;
1345     } else {
1346       if (address) {            /* global variable */
1347         if (var_test->address == address)
1348           return -1;
1349         if (var_test->address > address)
1350           end = cursor - 1;
1351         else
1352           start = cursor + 1;
1353       } else {                  /* local variable */
1354         return -1;
1355       }
1356     }
1357   }
1358
1359   if (strcmp(var_test->name, var) == 0) {
1360     if (address && var_test->address < address)
1361       return cursor + 1;
1362     else
1363       return cursor;
1364   } else if (strcmp(var_test->name, var) < 0)
1365     return cursor + 1;
1366   else
1367     return cursor;
1368
1369 }
1370
1371 void MC_dwarf_register_global_variable(mc_object_info_t info,
1372                                        dw_variable_t variable)
1373 {
1374   int index =
1375       MC_dwarf_get_variable_index(info->global_variables, variable->name,
1376                                   variable->address);
1377   if (index != -1)
1378     xbt_dynar_insert_at(info->global_variables, index, &variable);
1379   // TODO, else ?
1380 }
1381
1382 void MC_dwarf_register_non_global_variable(mc_object_info_t info,
1383                                            dw_frame_t frame,
1384                                            dw_variable_t variable)
1385 {
1386   xbt_assert(frame, "Frame is NULL");
1387   int index =
1388       MC_dwarf_get_variable_index(frame->variables, variable->name, NULL);
1389   if (index != -1)
1390     xbt_dynar_insert_at(frame->variables, index, &variable);
1391   // TODO, else ?
1392 }
1393
1394 void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame,
1395                                 dw_variable_t variable)
1396 {
1397   if (variable->global)
1398     MC_dwarf_register_global_variable(info, variable);
1399   else if (frame == NULL)
1400     xbt_die("No frame for this local variable");
1401   else
1402     MC_dwarf_register_non_global_variable(info, frame, variable);
1403 }
1404
1405 void MC_post_process_object_info(mc_object_info_t info)
1406 {
1407   xbt_dict_cursor_t cursor = NULL;
1408   char *key = NULL;
1409   dw_type_t type = NULL;
1410   xbt_dict_foreach(info->types, cursor, key, type) {
1411
1412     // Resolve full_type:
1413     if (type->name && type->byte_size == 0) {
1414       for (size_t i = 0; i != mc_object_infos_size; ++i) {
1415         dw_type_t same_type =
1416             xbt_dict_get_or_null(mc_object_infos[i]->full_types_by_name,
1417                                  type->name);
1418         if (same_type && same_type->name && same_type->byte_size) {
1419           type->full_type = same_type;
1420           break;
1421         }
1422       }
1423     }
1424
1425   }
1426 }