Logo AND Algorithmique Numérique Distribuée

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