Logo AND Algorithmique Numérique Distribuée

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