Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] OOPify/C++ify ObjectInformation
[simgrid.git] / src / mc / mc_dwarf_expression.cpp
1 /* Copyright (c) 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 <stdint.h>
8 #include <stdarg.h>
9
10 #include <dwarf.h>
11 #include <elfutils/libdw.h>
12
13 #include "mc_object_info.h"
14 #include "mc_private.h"
15
16 using simgrid::mc::remote;
17
18 extern "C" {
19
20 static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
21 {
22   if (state->stack_size >= MC_EXPRESSION_STACK_SIZE)
23     return MC_EXPRESSION_E_STACK_OVERFLOW;
24
25   state->stack[state->stack_size++] = value;
26   return 0;
27 }
28
29 /** Convert a DWARF register into a libunwind register
30  *
31  *  DWARF and libunwind does not use the same convention for numbering the
32  *  registers on some architectures. The function makes the necessary
33  *  convertion.
34  */
35 static int mc_dwarf_register_to_libunwind(int dwarf_register)
36 {
37 #if defined(UNW_TARGET_X86_64)
38   // It seems for this arch, DWARF and libunwind agree in the numbering:
39   return dwarf_register;
40 #elif defined(UNW_TARGET_X86)
41   // Could't find the authoritative source of information for this.
42   // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
43   switch (dwarf_register) {
44   case 0:
45     return UNW_X86_EAX;
46   case 1:
47     return UNW_X86_ECX;
48   case 2:
49     return UNW_X86_EDX;
50   case 3:
51     return UNW_X86_EBX;
52   case 4:
53     return UNW_X86_ESP;
54   case 5:
55     return UNW_X86_EBP;
56   case 6:
57     return UNW_X86_ESI;
58   case 7:
59     return UNW_X86_EDI;
60   case 8:
61     return UNW_X86_EIP;
62   case 9:
63     return UNW_X86_EFLAGS;
64   case 10:
65     return UNW_X86_CS;
66   case 11:
67     return UNW_X86_SS;
68   case 12:
69     return UNW_X86_DS;
70   case 13:
71     return UNW_X86_ES;
72   case 14:
73     return UNW_X86_FS;
74   case 15:
75     return UNW_X86_GS;
76   case 16:
77     return UNW_X86_ST0;
78   case 17:
79     return UNW_X86_ST1;
80   case 18:
81     return UNW_X86_ST2;
82   case 19:
83     return UNW_X86_ST3;
84   case 20:
85     return UNW_X86_ST4;
86   case 21:
87     return UNW_X86_ST5;
88   case 22:
89     return UNW_X86_ST6;
90   case 23:
91     return UNW_X86_ST7;
92   default:
93     xbt_die("Bad/unknown register number.");
94   }
95 #else
96 #error This architecture is not supported yet for DWARF expression evaluation.
97 #endif
98 }
99
100 int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
101                                 mc_expression_state_t state)
102 {
103   for (size_t i = 0; i != n; ++i) {
104     int error = 0;
105     const Dwarf_Op *op = ops + i;
106     uint8_t atom = op->atom;
107
108     switch (atom) {
109
110       // Registers:
111
112     case DW_OP_breg0:
113     case DW_OP_breg1:
114     case DW_OP_breg2:
115     case DW_OP_breg3:
116     case DW_OP_breg4:
117     case DW_OP_breg5:
118     case DW_OP_breg6:
119     case DW_OP_breg7:
120     case DW_OP_breg8:
121     case DW_OP_breg9:
122     case DW_OP_breg10:
123     case DW_OP_breg11:
124     case DW_OP_breg12:
125     case DW_OP_breg13:
126     case DW_OP_breg14:
127     case DW_OP_breg15:
128     case DW_OP_breg16:
129     case DW_OP_breg17:
130     case DW_OP_breg18:
131     case DW_OP_breg19:
132     case DW_OP_breg20:
133     case DW_OP_breg21:
134     case DW_OP_breg22:
135     case DW_OP_breg23:
136     case DW_OP_breg24:
137     case DW_OP_breg25:
138     case DW_OP_breg26:
139     case DW_OP_breg27:
140     case DW_OP_breg28:
141     case DW_OP_breg29:
142     case DW_OP_breg30:
143     case DW_OP_breg31:{
144         int register_id =
145             mc_dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
146         unw_word_t res;
147         if (!state->cursor)
148           return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
149         unw_get_reg(state->cursor, register_id, &res);
150         error = mc_dwarf_push_value(state, res + op->number);
151         break;
152       }
153
154       // Push the CFA (Canonical Frame Addresse):
155     case DW_OP_call_frame_cfa:
156       {
157         // UNW_X86_64_CFA does not return the CFA DWARF expects
158         // (it is a synonym for UNW_X86_64_RSP) so copy the cursor,
159         // unwind it once in order to find the parent SP:
160
161         if (!state->cursor)
162           return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
163
164         // Get frame:
165         unw_cursor_t cursor = *(state->cursor);
166         unw_step(&cursor);
167
168         unw_word_t res;
169         unw_get_reg(&cursor, UNW_TDEP_SP, &res);
170         error = mc_dwarf_push_value(state, res);
171         break;
172       }
173
174       // Frame base:
175
176     case DW_OP_fbreg:
177       {
178         if (!state->frame_base)
179           return MC_EXPRESSION_E_MISSING_FRAME_BASE;
180         uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
181         error = mc_dwarf_push_value(state, fb);
182         break;
183       }
184
185
186       // ***** Constants:
187
188       // Short constant literals:
189       // DW_OP_lit15 pushed the 15 on the stack.
190     case DW_OP_lit0:
191     case DW_OP_lit1:
192     case DW_OP_lit2:
193     case DW_OP_lit3:
194     case DW_OP_lit4:
195     case DW_OP_lit5:
196     case DW_OP_lit6:
197     case DW_OP_lit7:
198     case DW_OP_lit8:
199     case DW_OP_lit9:
200     case DW_OP_lit10:
201     case DW_OP_lit11:
202     case DW_OP_lit12:
203     case DW_OP_lit13:
204     case DW_OP_lit14:
205     case DW_OP_lit15:
206     case DW_OP_lit16:
207     case DW_OP_lit17:
208     case DW_OP_lit18:
209     case DW_OP_lit19:
210     case DW_OP_lit20:
211     case DW_OP_lit21:
212     case DW_OP_lit22:
213     case DW_OP_lit23:
214     case DW_OP_lit24:
215     case DW_OP_lit25:
216     case DW_OP_lit26:
217     case DW_OP_lit27:
218     case DW_OP_lit28:
219     case DW_OP_lit29:
220     case DW_OP_lit30:
221     case DW_OP_lit31:
222       error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
223       break;
224
225       // Address from the base address of this ELF object.
226       // Push the address on the stack (base_address + argument).
227     case DW_OP_addr: {
228       if (!state->object_info)
229         return MC_EXPRESSION_E_NO_BASE_ADDRESS;
230       if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
231         return MC_EXPRESSION_E_STACK_OVERFLOW;
232       Dwarf_Off addr = (Dwarf_Off) (uintptr_t)
233         state->object_info->base_address() + op->number;
234       error = mc_dwarf_push_value(state, addr);
235       break;
236     }
237
238       // General constants:
239       // Push the constant argument on the stack.
240     case DW_OP_const1u:
241     case DW_OP_const2u:
242     case DW_OP_const4u:
243     case DW_OP_const8u:
244     case DW_OP_const1s:
245     case DW_OP_const2s:
246     case DW_OP_const4s:
247     case DW_OP_const8s:
248     case DW_OP_constu:
249     case DW_OP_consts:
250       if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
251         return MC_EXPRESSION_E_STACK_OVERFLOW;
252       error = mc_dwarf_push_value(state, op->number);
253       break;
254
255       // ***** Stack manipulation:
256
257       // Push another copy/duplicate the value at the top of the stack:
258     case DW_OP_dup:
259       if (state->stack_size == 0)
260         return MC_EXPRESSION_E_STACK_UNDERFLOW;
261       else
262         error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
263       break;
264
265       // Pop/drop the top of the stack:
266     case DW_OP_drop:
267       if (state->stack_size == 0)
268         return MC_EXPRESSION_E_STACK_UNDERFLOW;
269       else
270         state->stack_size--;
271       break;
272
273       // Swap the two top-most value of the stack:
274     case DW_OP_swap:
275       if (state->stack_size < 2)
276         return MC_EXPRESSION_E_STACK_UNDERFLOW;
277       {
278         uintptr_t temp = state->stack[state->stack_size - 2];
279         state->stack[state->stack_size - 2] =
280             state->stack[state->stack_size - 1];
281         state->stack[state->stack_size - 1] = temp;
282       }
283       break;
284
285       // Duplicate the value under the top of the stack:
286     case DW_OP_over:
287       if (state->stack_size < 2)
288         return MC_EXPRESSION_E_STACK_UNDERFLOW;
289       error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
290       break;
291
292       // ***** Operations:
293       // Those usually take the top of the stack and the next value as argument
294       // and replace the top of the stack with the computed value
295       // (stack.top() += stack.before_top()).
296
297     case DW_OP_plus:
298       if (state->stack_size < 2)
299         return MC_EXPRESSION_E_STACK_UNDERFLOW;
300       {
301         uintptr_t result =
302             state->stack[state->stack_size - 2] +
303             state->stack[state->stack_size - 1];
304         state->stack[state->stack_size - 2] = result;
305         state->stack_size--;
306       }
307       break;
308
309     case DW_OP_mul:
310       if (state->stack_size < 2)
311         return MC_EXPRESSION_E_STACK_UNDERFLOW;
312       {
313         uintptr_t result =
314             state->stack[state->stack_size - 2] -
315             state->stack[state->stack_size - 1];
316         state->stack[state->stack_size - 2] = result;
317         state->stack_size--;
318       }
319       break;
320
321     case DW_OP_plus_uconst:
322       if (state->stack_size == 0)
323         return MC_EXPRESSION_E_STACK_UNDERFLOW;
324       state->stack[state->stack_size - 1] += op->number;
325       break;
326
327     case DW_OP_not:
328       if (state->stack_size == 0)
329         return MC_EXPRESSION_E_STACK_UNDERFLOW;
330       state->stack[state->stack_size - 1] =
331           ~state->stack[state->stack_size - 1];
332       break;
333
334     case DW_OP_neg:
335       if (state->stack_size == 0)
336         return MC_EXPRESSION_E_STACK_UNDERFLOW;
337       {
338         intptr_t value = state->stack[state->stack_size - 1];
339         if (value < 0)
340           value = -value;
341         state->stack[state->stack_size - 1] = value;
342       }
343       break;
344
345     case DW_OP_minus:
346       if (state->stack_size < 2)
347         return MC_EXPRESSION_E_STACK_UNDERFLOW;
348       {
349         uintptr_t result =
350             state->stack[state->stack_size - 2] -
351             state->stack[state->stack_size - 1];
352         state->stack[state->stack_size - 2] = result;
353         state->stack_size--;
354       }
355       break;
356
357     case DW_OP_and:
358       if (state->stack_size < 2)
359         return MC_EXPRESSION_E_STACK_UNDERFLOW;
360       {
361         uintptr_t result =
362             state->stack[state->stack_size -
363                          2] & state->stack[state->stack_size - 1];
364         state->stack[state->stack_size - 2] = result;
365         state->stack_size--;
366       }
367       break;
368
369     case DW_OP_or:
370       if (state->stack_size < 2)
371         return MC_EXPRESSION_E_STACK_UNDERFLOW;
372       {
373         uintptr_t result =
374             state->stack[state->stack_size -
375                          2] | state->stack[state->stack_size - 1];
376         state->stack[state->stack_size - 2] = result;
377         state->stack_size--;
378       }
379       break;
380
381     case DW_OP_xor:
382       if (state->stack_size < 2)
383         return MC_EXPRESSION_E_STACK_UNDERFLOW;
384       {
385         uintptr_t result =
386             state->stack[state->stack_size -
387                          2] ^ state->stack[state->stack_size - 1];
388         state->stack[state->stack_size - 2] = result;
389         state->stack_size--;
390       }
391       break;
392
393     case DW_OP_nop:
394       break;
395
396       // ***** Deference (memory fetch)
397
398     case DW_OP_deref_size:
399       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
400
401     case DW_OP_deref:
402       if (state->stack_size == 0)
403         return MC_EXPRESSION_E_STACK_UNDERFLOW;
404       {
405         // Computed address:
406         uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
407         if (!state->address_space)
408           xbt_die("Missing address space");
409         state->address_space->read_bytes(
410           &state->stack[state->stack_size - 1], sizeof(uintptr_t),
411           remote(address), state->process_index);
412       }
413       break;
414
415       // Not handled:
416     default:
417       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
418     }
419
420     if (error)
421       return error;
422   }
423   return 0;
424 }
425
426 // ***** Location
427
428 /** \brief Resolve a location expression
429  *  \deprecated Use mc_dwarf_resolve_expression
430  */
431 void mc_dwarf_resolve_location(mc_location_t location,
432                                mc_expression_t expression,
433                                mc_object_info_t object_info,
434                                unw_cursor_t * c,
435                                void *frame_pointer_address,
436                                mc_address_space_t address_space, int process_index)
437 {
438   s_mc_expression_state_t state;
439   memset(&state, 0, sizeof(s_mc_expression_state_t));
440   state.frame_base = frame_pointer_address;
441   state.cursor = c;
442   state.address_space = address_space;
443   state.object_info = object_info;
444   state.process_index = process_index;
445
446   if (expression->size >= 1
447     && expression->ops[0].atom >=DW_OP_reg0 && expression->ops[0].atom <= DW_OP_reg31) {
448     int dwarf_register = expression->ops[0].atom - DW_OP_reg0;
449     xbt_assert(c, "Missing frame context for register operation DW_OP_reg%i",
450       dwarf_register);
451     location->memory_location = NULL;
452     location->cursor = c;
453     location->register_id = mc_dwarf_register_to_libunwind(dwarf_register);
454     return;
455   }
456
457   if (mc_dwarf_execute_expression(expression->size, expression->ops, &state))
458     xbt_die("Error evaluating DWARF expression");
459   if (state.stack_size == 0)
460     xbt_die("No value on the stack");
461   else {
462     location->memory_location = (void*) state.stack[state.stack_size - 1];
463     location->cursor = NULL;
464     location->register_id = 0;
465   }
466 }
467
468 static mc_expression_t mc_find_expression(mc_location_list_t locations, unw_word_t ip) {
469   for (size_t i = 0; i != locations->size; ++i) {
470     mc_expression_t expression = locations->locations + i;
471     if ((expression->lowpc == NULL && expression->highpc == NULL)
472         || (ip && ip >= (unw_word_t) expression->lowpc
473             && ip < (unw_word_t) expression->highpc)) {
474       return expression;
475     }
476   }
477   return NULL;
478 }
479
480 void mc_dwarf_resolve_locations(mc_location_t location,
481                                      mc_location_list_t locations,
482                                      mc_object_info_t object_info,
483                                      unw_cursor_t * c,
484                                      void *frame_pointer_address,
485                                      mc_address_space_t address_space, int process_index)
486 {
487
488   unw_word_t ip = 0;
489   if (c) {
490     if (unw_get_reg(c, UNW_REG_IP, &ip))
491       xbt_die("Could not resolve IP");
492   }
493
494   mc_expression_t expression = mc_find_expression(locations, ip);
495   if (expression) {
496     mc_dwarf_resolve_location(location,
497                               expression, object_info, c,
498                               frame_pointer_address, address_space, process_index);
499   } else {
500     xbt_die("Could not resolve location");
501   }
502 }
503
504 /** \brief Find the frame base of a given frame
505  *
506  *  \param frame
507  *  \param unw_cursor
508  */
509 void *mc_find_frame_base(dw_frame_t frame, mc_object_info_t object_info,
510                          unw_cursor_t * unw_cursor)
511 {
512   s_mc_location_t location;
513   mc_dwarf_resolve_locations(&location,
514                              &frame->frame_base, object_info,
515                              unw_cursor, NULL, NULL, -1);
516   switch(mc_get_location_type(&location)) {
517   case MC_LOCATION_TYPE_ADDRESS:
518     return location.memory_location;
519
520   case MC_LOCATION_TYPE_REGISTER: {
521       // This is a special case.
522       // The register if not the location of the frame base
523       // (a frame base cannot be located in a register)
524       // Instead, DWARF defines this to mean that the register
525       // contains the address of the frame base.
526       unw_word_t word;
527       unw_get_reg(location.cursor, location.register_id, &word);
528       return (void*) word;
529     }
530
531   default:
532     xbt_die("Cannot handle non-address frame base");
533     return NULL; // Unreachable
534   }
535 }
536
537 void mc_dwarf_expression_clear(mc_expression_t expression)
538 {
539   free(expression->ops);
540   expression->ops = NULL;
541   expression->size = 0;
542   expression->lowpc = NULL;
543   expression->highpc = NULL;
544 }
545
546 void mc_dwarf_location_list_clear(mc_location_list_t list)
547 {
548   for (size_t i = 0; i != list->size; ++i) {
549     mc_dwarf_expression_clear(list->locations + i);
550   }
551   free(list->locations);
552   list->locations = NULL;
553   list->size = 0;
554 }
555
556 void mc_dwarf_expression_init(mc_expression_t expression, size_t len,
557                               Dwarf_Op * ops)
558 {
559   expression->lowpc = NULL;
560   expression->highpc = NULL;
561   expression->size = len;
562   expression->ops = (Dwarf_Op*) xbt_malloc(len * sizeof(Dwarf_Op));
563   memcpy(expression->ops, ops, len * sizeof(Dwarf_Op));
564 }
565
566 void mc_dwarf_location_list_init_from_expression(mc_location_list_t target,
567                                                  size_t len, Dwarf_Op * ops)
568 {
569   target->size = 1;
570   target->locations = (mc_expression_t) xbt_malloc(sizeof(s_mc_expression_t));
571   mc_dwarf_expression_init(target->locations, len, ops);
572 }
573
574 void mc_dwarf_location_list_init(mc_location_list_t list, mc_object_info_t info,
575                                  Dwarf_Die * die, Dwarf_Attribute * attr)
576 {
577   if (list->locations) {
578     mc_dwarf_location_list_clear(list);
579   }
580   list->size = 0;
581
582   ptrdiff_t offset = 0;
583   Dwarf_Addr base, start, end;
584   Dwarf_Op *ops;
585   size_t len;
586
587   while (1) {
588
589     offset = dwarf_getlocations(attr, offset, &base, &start, &end, &ops, &len);
590     if (offset == 0)
591       return;
592     else if (offset == -1)
593       xbt_die("Error while loading location list");
594
595     int i = list->size;
596     list->size++;
597     list->locations =
598         (mc_expression_t) realloc(list->locations,
599                                   list->size * sizeof(s_mc_expression_t));
600     mc_expression_t expression = list->locations + i;
601     expression->ops = NULL;
602     mc_dwarf_expression_init(expression, len, ops);
603
604     void *base = info->base_address();
605     // If start == 0, this is not a location list:
606     expression->lowpc = start == 0 ? NULL : (char *) base + start;
607     expression->highpc = start == 0 ? NULL : (char *) base + end;
608   }
609
610 }
611
612 }