Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : minor fix
[simgrid.git] / src / mc / mc_dwarf.c
1 /* Copyright (c) 2008-2013. 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 #include <dwarf.h>
9 #include <elfutils/libdw.h>
10 #include <inttypes.h>
11
12 #include <simgrid_config.h>
13 #include <xbt/log.h>
14 #include <xbt/sysdep.h>
15
16 #include "mc_private.h"
17
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
19
20 /** \brief The default DW_TAG_lower_bound for a given DW_AT_language.
21  *
22  *  The default for a given language is defined in the DWARF spec.
23  *
24  *  \param language consant as defined by the DWARf spec
25  */
26 static uint64_t MC_dwarf_default_lower_bound(int lang);
27
28 /** \brief Computes the the element_count of a DW_TAG_enumeration_type DIE
29  *
30  * This is the number of elements in a given array dimension.
31  *
32  * A reference of the compilation unit (DW_TAG_compile_unit) is
33  * needed because the default lower bound (when there is no DW_AT_lower_bound)
34  * depends of the language of the compilation unit (DW_AT_language).
35  *
36  * \param die  DIE for the DW_TAG_enumeration_type or DW_TAG_subrange_type
37  * \param unit DIE of the DW_TAG_compile_unit
38  */
39 static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit);
40
41 /** \brief Computes the number of elements of a given DW_TAG_array_type.
42  *
43  * \param die DIE for the DW_TAG_array_type
44  */
45 static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit);
46
47 /** \brief Process a DIE
48  *
49  *  \param info the resulting object fot the library/binary file (output)
50  *  \param die  the current DIE
51  *  \param unit the DIE of the compile unit of the current DIE
52  *  \param frame containg frame if any
53  */
54 static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
55
56 /** \brief Process a type DIE
57  */
58 static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
59
60 /** \brief Calls MC_dwarf_handle_die on all childrend of the given die
61  *
62  *  \param info the resulting object fot the library/binary file (output)
63  *  \param die  the current DIE
64  *  \param unit the DIE of the compile unit of the current DIE
65  *  \param frame containg frame if any
66  */
67 static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
68
69 /** \brief Handle a variable (DW_TAG_variable or other)
70  *
71  *  \param info the resulting object fot the library/binary file (output)
72  *  \param die  the current DIE
73  *  \param unit the DIE of the compile unit of the current DIE
74  *  \param frame containg frame if any
75  */
76 static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
77
78 /** \brief Convert a libdw DWARF expression into a MC representation of the location
79  *
80  *  \param expr array of DWARf operations
81  *  \param len  number of elements
82  *  \return a new MC expression
83  */
84 static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr,  size_t len);
85
86 /** \brief Get the DW_TAG_type of the DIE
87  *
88  *  \param die DIE
89  *  \return DW_TAG_type attribute as a new string (NULL if none)
90  */
91 static char* MC_dwarf_at_type(Dwarf_Die* die);
92
93 /** \brief Get the name of an attribute (DW_AT_*) from its code
94  *
95  *  \param attr attribute code (see the DWARF specification)
96  *  \return name of the attribute
97  */
98 const char* MC_dwarf_attrname(int attr) {
99   switch (attr) {
100 #include "mc_dwarf_attrnames.h"
101   default:
102     return "DW_AT_unkown";
103   }
104 }
105
106 /** \brief Get the name of a dwarf tag (DW_TAG_*) from its code
107  *
108  *  \param tag tag code (see the DWARF specification)
109  *  \return name of the tag
110  */
111 const char* MC_dwarf_tagname(int tag) {
112   switch (tag) {
113 #include "mc_dwarf_tagnames.h"
114   case DW_TAG_invalid:
115     return "DW_TAG_invalid";
116   default:
117     return "DW_TAG_unkown";
118   }
119 }
120
121 /** \brief Get the name of the tag of a given DIE
122  *
123  *  \param die DIE
124  *  \return name of the tag of this DIE
125  */
126 static inline const char* MC_dwarf_die_tagname(Dwarf_Die* die) {
127   return MC_dwarf_tagname(dwarf_tag(die));
128 }
129
130 // ***** Attributes
131
132 /** \brief Get an attribute of a given DIE as a string
133  *
134  *  \param the DIE
135  *  \param attribute attribute
136  *  \return value of the given attribute of the given DIE
137  */
138 static const char* MC_dwarf_attr_string(Dwarf_Die* die, int attribute) {
139   Dwarf_Attribute attr;
140   if (!dwarf_attr_integrate(die, attribute, &attr)) {
141         return NULL;
142   } else {
143         return dwarf_formstring(&attr);
144   }
145 }
146
147 /** \brief Get the linkage name of a DIE.
148  *
149  *  Use either DW_AT_linkage_name or DW_AR_MIPS_linkage_name.
150  *
151  *  \param DIE
152  *  \return linkage name of the given DIE (or NULL)
153  * */
154 static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) {
155   const char* name = MC_dwarf_attr_string(die, DW_AT_linkage_name);
156   if (!name)
157     name = MC_dwarf_attr_string(die, DW_AT_MIPS_linkage_name);
158   return name;
159 }
160
161 /** \brief Create a location list from a given attribute
162  *
163  *  \param die the DIE
164  *  \param attr the attribute
165  *  \return MC specific representation of the location list represented by the given attribute
166  *  of the given die
167  */
168 static dw_location_t MC_dwarf_get_location_list(Dwarf_Die* die, Dwarf_Attribute* attr) {
169
170   dw_location_t location = xbt_new0(s_dw_location_t, 1);
171   location->type = e_dw_loclist;
172   xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
173   location->location.loclist = loclist;
174
175   ptrdiff_t offset = 0;
176   Dwarf_Addr base, start, end;
177   Dwarf_Op *expr;
178   size_t len;
179
180   while (1) {
181
182     offset = dwarf_getlocations(attr, offset, &base, &start, &end, &expr, &len);
183     if (offset==0)
184       return location;
185     else if (offset==-1)
186       xbt_die("Error while loading location list");
187
188     dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
189     new_entry->lowpc = start;
190     new_entry->highpc = end;
191     new_entry->location = MC_dwarf_get_expression(expr, len);
192
193     xbt_dynar_push(loclist, &new_entry);
194
195   }
196 }
197
198 /** \brief Get the location expression or location list from an attribute
199  *
200  *  Processes direct expressions as well as location lists.
201  *
202  *  \param die the DIE
203  *  \param attr the attribute
204  *  \return MC specific representation of the location represented by the given attribute
205  *  of the given die
206  */
207 static dw_location_t MC_dwarf_get_location(Dwarf_Die* die, Dwarf_Attribute* attr) {
208   int form = dwarf_whatform(attr);
209   switch (form) {
210
211   // The attribute is an DWARF location expression:
212   case DW_FORM_exprloc:
213   case DW_FORM_block1: // not in the spec
214   case DW_FORM_block2:
215   case DW_FORM_block4:
216   case DW_FORM_block:
217     {
218       Dwarf_Op* expr;
219       size_t len;
220       if (dwarf_getlocation(attr, &expr, &len))
221         xbt_die("Could not read location expression");
222       return MC_dwarf_get_expression(expr, len);
223     }
224
225   // The attribute is a reference to a location list entry:
226   case DW_FORM_sec_offset:
227   case DW_FORM_data2:
228   case DW_FORM_data4:
229   case DW_FORM_data8:
230     {
231       return MC_dwarf_get_location_list(die, attr);
232     }
233     break;
234
235   default:
236     xbt_die("Unexpected form %i list for location in attribute %s of <%p>%s",
237       form,
238       MC_dwarf_attrname(attr->code),
239       (void*) dwarf_dieoffset(die),
240       MC_dwarf_attr_string(die, DW_AT_name));
241     return NULL;
242   }
243 }
244
245 /** \brief Get the location expression or location list from an attribute
246  *
247  *  Processes direct expressions as well as location lists.
248  *
249  *  \param die the DIE
250  *  \param attribute the attribute code
251  *  \return MC specific representation of the location represented by the given attribute
252  *  of the given die
253  */
254 static dw_location_t MC_dwarf_at_location(Dwarf_Die* die, int attribute) {
255   if(!dwarf_hasattr_integrate(die, attribute))
256     return xbt_new0(s_dw_location_t, 1);
257
258   Dwarf_Attribute attr;
259   dwarf_attr_integrate(die, attribute, &attr);
260   return MC_dwarf_get_location(die, &attr);
261 }
262
263 static char* MC_dwarf_at_type(Dwarf_Die* die) {
264   Dwarf_Attribute attr;
265   if (dwarf_hasattr_integrate(die, DW_AT_type)) {
266         dwarf_attr_integrate(die, DW_AT_type, &attr);
267         Dwarf_Die subtype_die;
268         if (dwarf_formref_die(&attr, &subtype_die)==NULL) {
269           xbt_die("Could not find DIE for type");
270         }
271         Dwarf_Off subtype_global_offset = dwarf_dieoffset(&subtype_die);
272     return bprintf("%" PRIx64 , subtype_global_offset);
273   }
274   else return NULL;
275 }
276
277 static uint64_t MC_dwarf_attr_addr(Dwarf_Die* die, int attribute) {
278   Dwarf_Attribute attr;
279   if(dwarf_attr_integrate(die, attribute, &attr)==NULL)
280     return 0;
281   Dwarf_Addr value;
282   if (dwarf_formaddr(&attr, &value) == 0)
283     return (uint64_t) value;
284   else
285     return 0;
286 }
287
288 static uint64_t MC_dwarf_attr_uint(Dwarf_Die* die, int attribute, uint64_t default_value) {
289   Dwarf_Attribute attr;
290   if (dwarf_attr_integrate(die, attribute, &attr)==NULL)
291     return default_value;
292   Dwarf_Word value;
293   return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr), &value) == 0 ? (uint64_t) value : default_value;
294 }
295
296 static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, int integrate) {
297   Dwarf_Attribute attr;
298   if ((integrate ? dwarf_attr_integrate(die, attribute, &attr)
299                     : dwarf_attr(die, attribute, &attr))==0)
300     return false;
301
302   bool result;
303   if (dwarf_formflag(&attr, &result))
304     xbt_die("Unexpected form for attribute %s",
305       MC_dwarf_attrname(attribute));
306   return result;
307 }
308
309 static uint64_t MC_dwarf_default_lower_bound(int lang) {
310   switch(lang) {
311   case DW_LANG_C:
312   case DW_LANG_C89:
313   case DW_LANG_C99:
314   case DW_LANG_C_plus_plus:
315   case DW_LANG_D:
316   case DW_LANG_Java:
317   case DW_LANG_ObjC:
318   case DW_LANG_ObjC_plus_plus:
319   case DW_LANG_Python:
320   case DW_LANG_UPC:
321     return 0;
322   case DW_LANG_Ada83:
323   case DW_LANG_Ada95:
324   case DW_LANG_Fortran77:
325   case DW_LANG_Fortran90:
326   case DW_LANG_Fortran95:
327   case DW_LANG_Modula2:
328   case DW_LANG_Pascal83:
329   case DW_LANG_PL1:
330   case DW_LANG_Cobol74:
331   case DW_LANG_Cobol85:
332     return 1;
333   default:
334     xbt_die("No default MT_TAG_lower_bound for language %i and none given", lang);
335     return 0;
336   }
337 }
338
339 static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit) {
340   xbt_assert(dwarf_tag(die)==DW_TAG_enumeration_type ||dwarf_tag(die)==DW_TAG_subrange_type,
341       "MC_dwarf_subrange_element_count called with DIE of type %s", MC_dwarf_die_tagname(die));
342
343   // Use DW_TAG_count if present:
344   if (dwarf_hasattr_integrate(die, DW_AT_count)) {
345     return MC_dwarf_attr_uint(die, DW_AT_count, 0);
346   }
347
348   // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound:
349
350   if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound)) {
351         // This is not really 0, but the code expects this (we do not know):
352     return 0;
353   }
354   uint64_t upper_bound = MC_dwarf_attr_uint(die, DW_AT_upper_bound, -1);
355
356   uint64_t lower_bound = 0;
357   if (dwarf_hasattr_integrate(die, DW_AT_lower_bound)) {
358     lower_bound = MC_dwarf_attr_uint(die, DW_AT_lower_bound, -1);
359   } else {
360         lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit));
361   }
362   return upper_bound - lower_bound;
363 }
364
365 static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit) {
366   xbt_assert(dwarf_tag(die)==DW_TAG_array_type,
367     "MC_dwarf_array_element_count called with DIE of type %s", MC_dwarf_die_tagname(die));
368
369   int result = 1;
370   Dwarf_Die child;
371   int res;
372   for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
373         int child_tag = dwarf_tag(&child);
374     if (child_tag==DW_TAG_subrange_type ||child_tag==DW_TAG_enumeration_type) {
375       result *= MC_dwarf_subrange_element_count(&child, unit);
376     }
377   }
378   return result;
379 }
380
381 // ***** Location
382
383 Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address) {
384   unw_word_t res;
385   switch (location->type){
386   case e_dw_compose:
387     if (xbt_dynar_length(location->location.compose) > 1){
388       return 0; /* TODO : location list with optimizations enabled */
389     }
390     dw_location_t location_entry = xbt_dynar_get_as(location->location.compose, 0, dw_location_t);
391     switch (location_entry->type){
392     case e_dw_register:
393       unw_get_reg(c, location_entry->location.reg, &res);
394       return res;
395     case e_dw_bregister_op:
396       unw_get_reg(c, location_entry->location.breg_op.reg, &res);
397       return (Dwarf_Off) ((long)res + location_entry->location.breg_op.offset);
398       break;
399     case e_dw_fbregister_op:
400       if (frame_pointer_address != NULL)
401         return (Dwarf_Off)((char *)frame_pointer_address + location_entry->location.fbreg_op);
402       else
403         return 0;
404     default:
405       return 0; /* FIXME : implement other cases (with optimizations enabled) */
406     }
407     break;
408     default:
409       return 0;
410   }
411 }
412
413 // ***** dw_type_t
414
415 static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwarf_Die* child) {
416   if (dwarf_hasattr(child, DW_AT_data_bit_offset)) {
417     xbt_die("Can't groke DW_AT_data_bit_offset.");
418   }
419
420   if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
421     if (type->type != DW_TAG_union_type) {
422         xbt_die(
423           "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%p>%s",
424           member->name, type->id, type->name);
425     } else {
426       return;
427     }
428   }
429
430   Dwarf_Attribute attr;
431   dwarf_attr_integrate(child, DW_AT_data_member_location, &attr);
432   switch (dwarf_whatform(&attr)) {
433
434   case DW_FORM_exprloc:
435     {
436       Dwarf_Op* expr;
437       size_t len;
438       if (dwarf_getlocation(&attr, &expr, &len)) {
439         xbt_die(
440           "Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%p>%s",
441           MC_dwarf_attr_string(child, DW_AT_name),
442           type->id, type->name);
443       }
444       if (len==1 && expr[0].atom == DW_OP_plus_uconst) {
445         member->offset =  expr[0].number;
446       } else {
447         xbt_die("Can't groke this location expression yet. %i %i",
448           len==1 , expr[0].atom == DW_OP_plus_uconst);
449       }
450       break;
451     }
452   case DW_FORM_data1:
453   case DW_FORM_data2:
454   case DW_FORM_data4:
455   case DW_FORM_data8:
456   case DW_FORM_sdata:
457   case DW_FORM_udata:
458     {
459       Dwarf_Word offset;
460       if (!dwarf_formudata(&attr, &offset))
461         member->offset = offset;
462       else
463         xbt_die("Cannot get DW_AT_data_member_%s location <%p>%s",
464           MC_dwarf_attr_string(child, DW_AT_name),
465           type->id, type->name);
466       break;
467     }
468   }
469 }
470
471 static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_type_t type) {
472   int res;
473   Dwarf_Die child;
474   xbt_assert(!type->members);
475   type->members = xbt_dynar_new(sizeof(dw_type_t), (void(*)(void*))dw_type_free);
476   for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
477     if (dwarf_tag(&child)==DW_TAG_member) {
478       // TODO, we should use another type (because is is not a type but a member)
479       dw_type_t member = xbt_new0(s_dw_type_t, 1);
480       member->type = -1;
481       member->id = NULL;
482
483       const char* name = MC_dwarf_attr_string(&child, DW_AT_name);
484       if(name)
485         member->name = xbt_strdup(name);
486       else
487         member->name = NULL;
488
489       member->byte_size = MC_dwarf_attr_uint(&child, DW_AT_byte_size, 0);
490       member->element_count = -1;
491       member->dw_type_id = MC_dwarf_at_type(&child);
492       member->members = NULL;
493       member->is_pointer_type = 0;
494       member->offset = 0;
495
496       if(dwarf_hasattr(&child, DW_AT_data_bit_offset)) {
497         xbt_die("Can't groke DW_AT_data_bit_offset.");
498       }
499
500       MC_dwarf_fill_member_location(type, member, &child);
501
502       if (!member->dw_type_id) {
503         xbt_die("Missing type for member %s of <%p>%s", member->name, type->id, type->name);
504       }
505
506       xbt_dynar_push(type->members, &member);
507     }
508   }
509 }
510
511 /** \brief Create a MC type object from a DIE
512  *
513  *  \param info current object info object
514  *  \param DIE (for a given type);
515  *  \param unit compilation unit of the current DIE
516  *  \return MC representation of the type
517  */
518 static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
519
520   dw_type_t type = xbt_new0(s_dw_type_t, 1);
521   type->type = -1;
522   type->id = NULL;
523   type->name = NULL;
524   type->byte_size = 0;
525   type->element_count = -1;
526   type->dw_type_id = NULL;
527   type->members = NULL;
528   type->is_pointer_type = 0;
529   type->offset = 0;
530
531   type->type = dwarf_tag(die);
532
533   // Global Offset
534   type->id = (void *) dwarf_dieoffset(die);
535
536   const char* name = MC_dwarf_attr_string(die, DW_AT_name);
537   if (name!=NULL) {
538         type->name = xbt_strdup(name);
539   }
540
541   XBT_DEBUG("Processing type <%p>%s", type->id, type->name);
542
543   type->dw_type_id = MC_dwarf_at_type(die);
544
545   // Computation of the byte_size;
546   if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
547     type->byte_size = MC_dwarf_attr_uint(die, DW_AT_byte_size, 0);
548   else if (type->type == DW_TAG_array_type || type->type==DW_TAG_structure_type || type->type==DW_TAG_class_type) {
549     Dwarf_Word size;
550     if (dwarf_aggregate_size(die, &size)==0) {
551       type->byte_size = size;
552     }
553   }
554
555   switch (type->type) {
556   case DW_TAG_array_type:
557         type->element_count = MC_dwarf_array_element_count(die, unit);
558         // TODO, handle DW_byte_stride and (not) DW_bit_stride
559         break;
560
561   case DW_TAG_pointer_type:
562   case DW_TAG_reference_type:
563   case DW_TAG_rvalue_reference_type:
564     type->is_pointer_type = 1;
565     break;
566
567   case DW_TAG_structure_type:
568   case DW_TAG_union_type:
569   case DW_TAG_class_type:
570           MC_dwarf_add_members(info, die, unit, type);
571   }
572
573   return type;
574 }
575
576 static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
577   dw_type_t type = MC_dwarf_die_to_type(info, die, unit);
578
579   char* key = bprintf("%" PRIx64, (uint64_t) type->id);
580   xbt_dict_set(info->types, key, type, NULL);
581 }
582
583 /** \brief Convert libdw location expresion elment into native one (or NULL in some cases) */
584 static dw_location_t MC_dwarf_get_expression_element(Dwarf_Op* op) {
585   dw_location_t element = xbt_new0(s_dw_location_t, 1);
586   uint8_t atom = op->atom;
587   if (atom >= DW_OP_reg0 && atom<= DW_OP_reg31) {
588     element->type = e_dw_register;
589     element->location.reg = atom - DW_OP_reg0;
590   }
591   else if (atom >= DW_OP_breg0 && atom<= DW_OP_breg31) {
592     element->type = e_dw_bregister_op;
593     element->location.reg = atom - DW_OP_breg0;
594     element->location.breg_op.offset = op->number;
595   }
596   else if (atom >= DW_OP_lit0 && atom<= DW_OP_lit31) {
597     element->type = e_dw_lit;
598     element->location.reg = atom - DW_OP_lit0;
599   }
600   else switch (atom) {
601   case DW_OP_fbreg:
602     element->type = e_dw_fbregister_op;
603     element->location.fbreg_op = op->number;
604     break;
605   case DW_OP_piece:
606     element->type = e_dw_piece;
607     element->location.piece = op->number;
608     break;
609   case DW_OP_plus_uconst:
610     element->type = e_dw_plus_uconst;
611     element->location.plus_uconst = op->number;
612     break;
613   case DW_OP_abs:
614     element->type = e_dw_arithmetic;
615     element->location.arithmetic = xbt_strdup("abs");
616     break;
617   case DW_OP_and:
618     element->type = e_dw_arithmetic;
619     element->location.arithmetic = xbt_strdup("and");
620     break;
621   case DW_OP_div:
622     element->type = e_dw_arithmetic;
623     element->location.arithmetic = xbt_strdup("div");
624     break;
625   case DW_OP_minus:
626     element->type = e_dw_arithmetic;
627     element->location.arithmetic = xbt_strdup("minus");
628     break;
629   case DW_OP_mod:
630     element->type = e_dw_arithmetic;
631     element->location.arithmetic = xbt_strdup("mod");
632     break;
633   case DW_OP_mul:
634     element->type = e_dw_arithmetic;
635     element->location.arithmetic = xbt_strdup("mul");
636     break;
637   case DW_OP_neg:
638     element->type = e_dw_arithmetic;
639     element->location.arithmetic = xbt_strdup("neg");
640     break;
641   case DW_OP_not:
642     element->type = e_dw_arithmetic;
643     element->location.arithmetic = xbt_strdup("not");
644     break;
645   case DW_OP_or:
646     element->type = e_dw_arithmetic;
647     element->location.arithmetic = xbt_strdup("or");
648     break;
649   case DW_OP_plus:
650     element->type = e_dw_arithmetic;
651     element->location.arithmetic = xbt_strdup("plus");
652     break;
653
654   case DW_OP_stack_value:
655     // Why nothing here?
656     xbt_free(element);
657     return NULL;
658
659   case DW_OP_deref_size:
660     element->type = e_dw_deref;
661     element->location.deref_size =  (unsigned int short) op->number;
662     break;
663   case DW_OP_deref:
664     element->type = e_dw_deref;
665     element->location.deref_size = sizeof(void *);
666     break;
667   case DW_OP_constu:
668     element->type = e_dw_uconstant;
669     element->location.uconstant.bytes = 1;
670     element->location.uconstant.value = (unsigned long int) op->number;
671     break;
672   case DW_OP_consts:
673     element->type = e_dw_sconstant;
674     element->location.uconstant.bytes = 1;
675     element->location.uconstant.value = (unsigned long int) op->number;
676     break;
677
678   case DW_OP_const1u:
679     element->type = e_dw_uconstant;
680     element->location.uconstant.bytes = 1;
681     element->location.uconstant.value = (unsigned long int) op->number;
682     break;
683   case DW_OP_const2u:
684     element->type = e_dw_uconstant;
685     element->location.uconstant.bytes = 2;
686     element->location.uconstant.value = (unsigned long int) op->number;
687     break;
688   case DW_OP_const4u:
689     element->type = e_dw_uconstant;
690     element->location.uconstant.bytes = 4;
691     element->location.uconstant.value = (unsigned long int) op->number;
692     break;
693   case DW_OP_const8u:
694     element->type = e_dw_uconstant;
695     element->location.uconstant.bytes = 8;
696     element->location.uconstant.value = (unsigned long int) op->number;
697     break;
698
699   case DW_OP_const1s:
700     element->type = e_dw_sconstant;
701     element->location.uconstant.bytes = 1;
702     element->location.uconstant.value = (unsigned long int) op->number;
703     break;
704   case DW_OP_const2s:
705     element->type = e_dw_sconstant;
706     element->location.uconstant.bytes = 2;
707     element->location.uconstant.value = (unsigned long int) op->number;
708     break;
709   case DW_OP_const4s:
710     element->type = e_dw_sconstant;
711     element->location.uconstant.bytes = 4;
712     element->location.uconstant.value = (unsigned long int) op->number;
713     break;
714   case DW_OP_const8s:
715     element->type = e_dw_sconstant;
716     element->location.uconstant.bytes = 8;
717     element->location.uconstant.value = (unsigned long int) op->number;
718     break;
719   default:
720     element->type = e_dw_unsupported;
721     break;
722   }
723   return element;
724 }
725
726 /** \brief Convert libdw location expresion into native one */
727 static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr,  size_t len) {
728   dw_location_t loc = xbt_new0(s_dw_location_t, 1);
729   loc->type = e_dw_compose;
730   loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
731
732   int i;
733   for (i=0; i!=len; ++i) {
734     dw_location_t element =  MC_dwarf_get_expression_element(expr+i);
735     if (element)
736       xbt_dynar_push(loc->location.compose, &element);
737   }
738
739   return loc;
740 }
741
742 static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
743   // Drop declaration:
744   if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
745     return NULL;
746
747   Dwarf_Attribute attr_location;
748   if (dwarf_attr(die, DW_AT_location, &attr_location)==NULL) {
749     // No location: do not add it ?
750     return NULL;
751   }
752
753   dw_variable_t variable = xbt_new0(s_dw_variable_t, 1);
754   variable->dwarf_offset = dwarf_dieoffset(die);
755   variable->global = frame == NULL; // Can be override base on DW_AT_location
756   variable->name = xbt_strdup(MC_dwarf_attr_string(die, DW_AT_name));
757   variable->type_origin = MC_dwarf_at_type(die);
758   variable->address.address = NULL;
759
760   int form;
761   switch (form = dwarf_whatform(&attr_location)) {
762   case DW_FORM_exprloc:
763   case DW_FORM_block1: // Not in the spec but found in the wild.
764     {
765       Dwarf_Op* expr;
766       size_t len;
767       if (dwarf_getlocation(&attr_location, &expr, &len)) {
768         xbt_die(
769           "Could not read location expression in DW_AT_location of variable <%p>%s",
770           (void*) variable->dwarf_offset, variable->name);
771       }
772
773       if (len==1 && expr[0].atom == DW_OP_addr) {
774         variable->global = 1;
775         Dwarf_Off offset = expr[0].number;
776         // TODO, Why is this different base on the object?
777         Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_text : 0;
778         variable->address.address = (void*) (base + offset);
779       } else {
780         variable->address.location = MC_dwarf_get_expression(expr, len);
781       }
782
783       break;
784     }
785   case DW_FORM_sec_offset: // type loclistptr
786   case DW_FORM_data2:
787   case DW_FORM_data4:
788   case DW_FORM_data8:
789     variable->address.location = MC_dwarf_get_location_list(die, &attr_location);
790     break;
791   default:
792     xbt_die("Unexpected form %i list for location in <%p>%s",
793       form, (void*) variable->dwarf_offset, variable->name);
794   }
795
796   return variable;
797 }
798
799 static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
800   dw_variable_t variable = MC_die_to_variable(info, die, unit, frame);
801   if(variable==NULL)
802       return;
803   MC_dwarf_register_variable(info, frame, variable);
804 }
805
806 static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame) {
807   dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
808
809   frame->start = dwarf_dieoffset(die);
810
811   const char* name = MC_dwarf_at_linkage_name(die);
812   if (name==NULL)
813     name = MC_dwarf_attr_string(die, DW_AT_name);
814   frame->name = xbt_strdup(name);
815
816   // Variables are filled in the (recursive) call of MC_dwarf_handle_children:
817   frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
818   frame->high_pc = (void*) MC_dwarf_attr_addr(die, DW_AT_high_pc);
819   frame->low_pc = (void*) MC_dwarf_attr_addr(die, DW_AT_low_pc);
820   frame->frame_base = MC_dwarf_at_location(die, DW_AT_frame_base);
821   frame->end = -1; // This one is now useless:
822
823   // Handle children:
824   MC_dwarf_handle_children(info, die, unit, frame);
825
826   // Register it:
827   xbt_dict_set(info->local_variables, frame->name, frame, NULL);
828 }
829
830 static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
831   Dwarf_Die child;
832   int res;
833   for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
834     MC_dwarf_handle_die(info, &child, unit, frame);
835   }
836 }
837
838 static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
839   int tag = dwarf_tag(die);
840   switch (tag) {
841     case DW_TAG_array_type:
842     case DW_TAG_class_type:
843     case DW_TAG_enumeration_type:
844     case DW_TAG_typedef:
845     case DW_TAG_pointer_type:
846     case DW_TAG_string_type:
847     case DW_TAG_structure_type:
848     case DW_TAG_subroutine_type:
849     case DW_TAG_union_type:
850     case DW_TAG_ptr_to_member_type:
851     case DW_TAG_set_type:
852     case DW_TAG_subrange_type:
853     case DW_TAG_base_type:
854     case DW_TAG_const_type:
855     case DW_TAG_file_type:
856     case DW_TAG_packed_type:
857     case DW_TAG_volatile_type:
858     case DW_TAG_restrict_type:
859     case DW_TAG_interface_type:
860     case DW_TAG_unspecified_type:
861     case DW_TAG_mutable_type:
862     case DW_TAG_shared_type:
863       MC_dwarf_handle_type_die(info, die, unit);
864       break;
865     case DW_TAG_inlined_subroutine:
866     case DW_TAG_subprogram:
867       MC_dwarf_handle_subprogram_die(info, die, unit, frame);
868       return;
869     // case DW_TAG_formal_parameter:
870     case DW_TAG_variable:
871     case DW_TAG_formal_parameter:
872       MC_dwarf_handle_variable_die(info, die, unit, frame);
873       break;
874   }
875
876   // Recursive processing of children DIE:
877   MC_dwarf_handle_children(info, die, unit, frame);
878 }
879
880 void MC_dwarf_get_variables(mc_object_info_t info) {
881   int fd = open(info->file_name, O_RDONLY);
882   if (fd<0) {
883     xbt_die("Could not open file %s", info->file_name);
884   }
885   Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
886   if (dwarf==NULL) {
887     xbt_die("Your program must be compiled with -g");
888   }
889
890   Dwarf_Off offset = 0;
891   Dwarf_Off next_offset = 0;
892   size_t length;
893   while (dwarf_nextcu (dwarf, offset, &next_offset, &length, NULL, NULL, NULL) == 0) {
894     Dwarf_Die die;
895     if(dwarf_offdie(dwarf, offset+length, &die)!=NULL) {
896       MC_dwarf_handle_die(info, &die, &die, NULL);
897     }
898     offset = next_offset;
899   }
900
901   dwarf_end(dwarf);
902   close(fd);
903 }