Logo AND Algorithmique Numérique Distribuée

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