Logo AND Algorithmique Numérique Distribuée

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