1 /* Copyright (c) 2014-2015. The SimGrid Team.
2 * All rights reserved. */
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. */
14 #include "mc_dwarf.hpp"
15 #include "mc_private.h"
16 #include "mc_location.h"
17 #include "mc/AddressSpace.hpp"
18 #include "mc/Frame.hpp"
19 #include "mc/ObjectInformation.hpp"
21 using simgrid::mc::remote;
25 static int mc_dwarf_push_value(mc_expression_state_t state, std::uint64_t value)
27 if (state->stack_size >= MC_EXPRESSION_STACK_SIZE)
28 return MC_EXPRESSION_E_STACK_OVERFLOW;
30 state->stack[state->stack_size++] = value;
34 /** Convert a DWARF register into a libunwind register
36 * DWARF and libunwind does not use the same convention for numbering the
37 * registers on some architectures. The function makes the necessary
40 static int mc_dwarf_register_to_libunwind(int dwarf_register)
42 #if defined(__x86_64__)
43 // It seems for this arch, DWARF and libunwind agree in the numbering:
44 return dwarf_register;
45 #elif defined(__i386__)
46 // Could't find the authoritative source of information for this.
47 // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
48 switch (dwarf_register) {
68 return UNW_X86_EFLAGS;
98 xbt_die("Bad/unknown register number.");
101 #error This architecture is not supported yet for DWARF expression evaluation.
105 int mc_dwarf_execute_expression(size_t n, const simgrid::mc::DwarfInstruction* ops,
106 mc_expression_state_t state)
108 for (size_t i = 0; i != n; ++i) {
110 const simgrid::mc::DwarfInstruction *op = ops + i;
111 uint8_t atom = op->atom;
150 mc_dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
153 return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
154 unw_get_reg(state->cursor, register_id, &res);
155 error = mc_dwarf_push_value(state, res + op->number);
159 // Push the CFA (Canonical Frame Addresse):
160 case DW_OP_call_frame_cfa:
162 // UNW_X86_64_CFA does not return the CFA DWARF expects
163 // (it is a synonym for UNW_X86_64_RSP) so copy the cursor,
164 // unwind it once in order to find the parent SP:
167 return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
170 unw_cursor_t cursor = *(state->cursor);
174 unw_get_reg(&cursor, UNW_REG_SP, &res);
175 error = mc_dwarf_push_value(state, res);
183 if (!state->frame_base)
184 return MC_EXPRESSION_E_MISSING_FRAME_BASE;
185 uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
186 error = mc_dwarf_push_value(state, fb);
193 // Short constant literals:
194 // DW_OP_lit15 pushed the 15 on the stack.
227 error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
230 // Address from the base address of this ELF object.
231 // Push the address on the stack (base_address + argument).
233 if (!state->object_info)
234 return MC_EXPRESSION_E_NO_BASE_ADDRESS;
235 if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
236 return MC_EXPRESSION_E_STACK_OVERFLOW;
237 std::uint64_t addr = (std::uint64_t) (uintptr_t)
238 state->object_info->base_address() + op->number;
239 error = mc_dwarf_push_value(state, addr);
243 // General constants:
244 // Push the constant argument on the stack.
255 if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
256 return MC_EXPRESSION_E_STACK_OVERFLOW;
257 error = mc_dwarf_push_value(state, op->number);
260 // ***** Stack manipulation:
262 // Push another copy/duplicate the value at the top of the stack:
264 if (state->stack_size == 0)
265 return MC_EXPRESSION_E_STACK_UNDERFLOW;
267 error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
270 // Pop/drop the top of the stack:
272 if (state->stack_size == 0)
273 return MC_EXPRESSION_E_STACK_UNDERFLOW;
278 // Swap the two top-most value of the stack:
280 if (state->stack_size < 2)
281 return MC_EXPRESSION_E_STACK_UNDERFLOW;
283 uintptr_t temp = state->stack[state->stack_size - 2];
284 state->stack[state->stack_size - 2] =
285 state->stack[state->stack_size - 1];
286 state->stack[state->stack_size - 1] = temp;
290 // Duplicate the value under the top of the stack:
292 if (state->stack_size < 2)
293 return MC_EXPRESSION_E_STACK_UNDERFLOW;
294 error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
298 // Those usually take the top of the stack and the next value as argument
299 // and replace the top of the stack with the computed value
300 // (stack.top() += stack.before_top()).
303 if (state->stack_size < 2)
304 return MC_EXPRESSION_E_STACK_UNDERFLOW;
307 state->stack[state->stack_size - 2] +
308 state->stack[state->stack_size - 1];
309 state->stack[state->stack_size - 2] = result;
315 if (state->stack_size < 2)
316 return MC_EXPRESSION_E_STACK_UNDERFLOW;
319 state->stack[state->stack_size - 2] -
320 state->stack[state->stack_size - 1];
321 state->stack[state->stack_size - 2] = result;
326 case DW_OP_plus_uconst:
327 if (state->stack_size == 0)
328 return MC_EXPRESSION_E_STACK_UNDERFLOW;
329 state->stack[state->stack_size - 1] += op->number;
333 if (state->stack_size == 0)
334 return MC_EXPRESSION_E_STACK_UNDERFLOW;
335 state->stack[state->stack_size - 1] =
336 ~state->stack[state->stack_size - 1];
340 if (state->stack_size == 0)
341 return MC_EXPRESSION_E_STACK_UNDERFLOW;
343 intptr_t value = state->stack[state->stack_size - 1];
346 state->stack[state->stack_size - 1] = value;
351 if (state->stack_size < 2)
352 return MC_EXPRESSION_E_STACK_UNDERFLOW;
355 state->stack[state->stack_size - 2] -
356 state->stack[state->stack_size - 1];
357 state->stack[state->stack_size - 2] = result;
363 if (state->stack_size < 2)
364 return MC_EXPRESSION_E_STACK_UNDERFLOW;
367 state->stack[state->stack_size -
368 2] & state->stack[state->stack_size - 1];
369 state->stack[state->stack_size - 2] = result;
375 if (state->stack_size < 2)
376 return MC_EXPRESSION_E_STACK_UNDERFLOW;
379 state->stack[state->stack_size -
380 2] | state->stack[state->stack_size - 1];
381 state->stack[state->stack_size - 2] = result;
387 if (state->stack_size < 2)
388 return MC_EXPRESSION_E_STACK_UNDERFLOW;
391 state->stack[state->stack_size -
392 2] ^ state->stack[state->stack_size - 1];
393 state->stack[state->stack_size - 2] = result;
401 // ***** Deference (memory fetch)
403 case DW_OP_deref_size:
404 return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
407 if (state->stack_size == 0)
408 return MC_EXPRESSION_E_STACK_UNDERFLOW;
411 uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
412 if (!state->address_space)
413 xbt_die("Missing address space");
414 state->address_space->read_bytes(
415 &state->stack[state->stack_size - 1], sizeof(uintptr_t),
416 remote(address), state->process_index);
422 return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
433 /** \brief Resolve a location expression
434 * \deprecated Use mc_dwarf_resolve_expression
436 void mc_dwarf_resolve_location(mc_location_t location,
437 simgrid::mc::DwarfExpression* expression,
438 simgrid::mc::ObjectInformation* object_info,
440 void *frame_pointer_address,
441 simgrid::mc::AddressSpace* address_space, int process_index)
443 s_mc_expression_state_t state;
444 memset(&state, 0, sizeof(s_mc_expression_state_t));
445 state.frame_base = frame_pointer_address;
447 state.address_space = address_space;
448 state.object_info = object_info;
449 state.process_index = process_index;
451 if (expression->size() >= 1
452 && (*expression)[0].atom >=DW_OP_reg0
453 && (*expression)[0].atom <= DW_OP_reg31) {
454 int dwarf_register = (*expression)[0].atom - DW_OP_reg0;
456 "Missing frame context for register operation DW_OP_reg%i",
458 location->memory_location = NULL;
459 location->cursor = c;
460 location->register_id = mc_dwarf_register_to_libunwind(dwarf_register);
464 if (mc_dwarf_execute_expression(
465 expression->size(), expression->data(), &state))
466 xbt_die("Error evaluating DWARF expression");
467 if (state.stack_size == 0)
468 xbt_die("No value on the stack");
470 location->memory_location = (void*) state.stack[state.stack_size - 1];
471 location->cursor = NULL;
472 location->register_id = 0;
476 // TODO, move this in a method of LocationList
477 static simgrid::mc::DwarfExpression* mc_find_expression(
478 simgrid::mc::LocationList* locations, unw_word_t ip)
480 for (simgrid::mc::LocationListEntry& entry : *locations)
481 if (entry.valid_for_ip(ip))
482 return &entry.expression;
486 void mc_dwarf_resolve_locations(mc_location_t location,
487 simgrid::mc::LocationList* locations,
488 simgrid::mc::ObjectInformation* object_info,
490 void *frame_pointer_address,
491 simgrid::mc::AddressSpace* address_space,
497 if (unw_get_reg(c, UNW_REG_IP, &ip))
498 xbt_die("Could not resolve IP");
501 simgrid::mc::DwarfExpression* expression = mc_find_expression(locations, ip);
503 mc_dwarf_resolve_location(location,
504 expression, object_info, c,
505 frame_pointer_address, address_space, process_index);
507 xbt_die("Could not resolve location");
511 /** \brief Find the frame base of a given frame
516 void *mc_find_frame_base(simgrid::mc::Frame* frame, simgrid::mc::ObjectInformation* object_info,
517 unw_cursor_t * unw_cursor)
519 s_mc_location_t location;
520 mc_dwarf_resolve_locations(&location,
521 &frame->frame_base, object_info,
522 unw_cursor, NULL, NULL, -1);
523 switch(mc_get_location_type(&location)) {
524 case MC_LOCATION_TYPE_ADDRESS:
525 return location.memory_location;
527 case MC_LOCATION_TYPE_REGISTER: {
528 // This is a special case.
529 // The register if not the location of the frame base
530 // (a frame base cannot be located in a register)
531 // Instead, DWARF defines this to mean that the register
532 // contains the address of the frame base.
534 unw_get_reg(location.cursor, location.register_id, &word);
539 xbt_die("Cannot handle non-address frame base");
540 return NULL; // Unreachable