+/* Copyright (c) 2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
#include <stdint.h>
#include <stdarg.h>
return 0;
}
+static int mc_dwarf_register_to_libunwind(int dwarf_register) {
+ #if defined(UNW_TARGET_X86_64)
+ // It seems for this arch, DWARF and libunwind agree in the numbering:
+ return dwarf_register;
+ #elif defined(UNW_TARGET_X86)
+ // Could't find the authoritative source of information for this.
+ // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
+ switch(dwarf_register) {
+ case 0: return UNW_X86_EAX;
+ case 1: return UNW_X86_ECX;
+ case 2: return UNW_X86_EDX;
+ case 3: return UNW_X86_EBX;
+ case 4: return UNW_X86_ESP;
+ case 5: return UNW_X86_EBP;
+ case 6: return UNW_X86_ESI;
+ case 7: return UNW_X86_EDI;
+ case 8: return UNW_X86_EIP;
+ case 9: return UNW_X86_EFLAGS;
+ case 10: return UNW_X86_CS;
+ case 11: return UNW_X86_SS;
+ case 12: return UNW_X86_DS;
+ case 13: return UNW_X86_ES;
+ case 14: return UNW_X86_FS;
+ case 15: return UNW_X86_GS;
+ case 16: return UNW_X86_ST0;
+ case 17: return UNW_X86_ST1;
+ case 18: return UNW_X86_ST2;
+ case 19: return UNW_X86_ST3;
+ case 20: return UNW_X86_ST4;
+ case 21: return UNW_X86_ST5;
+ case 22: return UNW_X86_ST6;
+ case 23: return UNW_X86_ST7;
+ default: xbt_die("Bad/unknown register number.");
+ }
+ #else
+ #error This architecture is not supported yet.
+ #endif
+}
+
int mc_dwarf_execute_expression(
size_t n, const Dwarf_Op* ops, mc_expression_state_t state) {
for(int i=0; i!=n; ++i) {
case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:{
- int register_id = op->atom - DW_OP_breg0;
+ int register_id = mc_dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
unw_word_t res;
if(!state->cursor)
return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
break;
}
- // Push the CFA (Call Frame Addresse):
+ // Push the CFA (Canonical Frame Addresse):
case DW_OP_call_frame_cfa:
{
- unw_word_t res;
-
- int register_id =
-#if defined(UNW_TARGET_X86_64)
- UNW_X86_64_CFA
-#elif defined(UNW_TARGET_X86)
- UNW_X86_CFA
-#else
- -1;
-#endif
- ;
- if(register_id<0)
- xbt_die("Support for CFA not implemented for this achitecture.");
+ // UNW_X86_64_CFA does not return the CFA DWARF expects
+ // (it is a synonym for UNW_X86_64_RSP) so copy the cursor,
+ // unwind it once in order to find the parent SP:
if(!state->cursor)
return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
- unw_get_reg(state->cursor, register_id, &res);
- error = mc_dwarf_push_value(state, res + op->number);
+ // Get frame:
+ unw_cursor_t cursor = *(state->cursor);
+ unw_step(&cursor);
+
+ unw_word_t res;
+ unw_get_reg(&cursor, UNW_TDEP_SP, &res);
+ error = mc_dwarf_push_value(state, res);
break;
}
break;
}
+
// Constants:
case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3:
break;
case DW_OP_addr:
+ if(!state->object_info)
+ return MC_EXPRESSION_E_NO_BASE_ADDRESS;
+ if(state->stack_size==MC_EXPRESSION_STACK_SIZE)
+ return MC_EXPRESSION_E_STACK_OVERFLOW;
+ error = mc_dwarf_push_value(state,
+ (Dwarf_Off)(uintptr_t)MC_object_base_address(state->object_info) + op->number);
+ break;
+
case DW_OP_const1u:
case DW_OP_const2u:
case DW_OP_const4u:
// Dereference:
case DW_OP_deref_size:
- case DW_OP_deref:
return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
+ case DW_OP_deref:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ // Computed address:
+ uintptr_t address = (uintptr_t) state->stack[state->stack_size-1];
+ uintptr_t* p = (uintptr_t*)mc_translate_address(address, state->snapshot);
+ state->stack[state->stack_size-1] = *p;
+ }
+ break;
+
// Not handled:
default:
return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
/** \brief Resolve a location expression
* \deprecated Use mc_dwarf_resolve_expression
*/
-Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, void* frame_pointer_address) {
+uintptr_t mc_dwarf_resolve_location(mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot) {
s_mc_expression_state_t state;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = frame_pointer_address;
state.cursor = c;
+ state.snapshot = snapshot;
+ state.object_info = object_info;
if(mc_dwarf_execute_expression(expression->size, expression->ops, &state))
xbt_die("Error evaluating DWARF expression");
if(state.stack_size==0)
xbt_die("No value on the stack");
else
- return (Dwarf_Off) state.stack[state.stack_size-1];
+ return state.stack[state.stack_size-1];
}
-Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address) {
+uintptr_t mc_dwarf_resolve_locations(mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot) {
unw_word_t ip;
if(c) {
mc_expression_t expression = locations->locations + i;
if( (expression->lowpc==NULL && expression->highpc==NULL)
|| (c && ip >= (unw_word_t) expression->lowpc && ip < (unw_word_t) expression->highpc)) {
- return mc_dwarf_resolve_location(expression, c, frame_pointer_address);
+ return mc_dwarf_resolve_location(expression, object_info, c, frame_pointer_address, snapshot);
}
}
xbt_die("Could not resolve location");
}
-static
+/** \brief Find the frame base of a given frame
+ *
+ * \param frame
+ * \param unw_cursor
+ */
+void* mc_find_frame_base(dw_frame_t frame, mc_object_info_t object_info, unw_cursor_t* unw_cursor) {
+ return (void*) mc_dwarf_resolve_locations(&frame->frame_base, object_info, unw_cursor, NULL, NULL);
+}
+
void mc_dwarf_expression_clear(mc_expression_t expression) {
free(expression->ops);
expression->ops = NULL;
list->size = 0;
}
-static
void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops) {
if(expression->ops) {
free(expression->ops);
list->size++;
list->locations = (mc_expression_t) realloc(list->locations, list->size*sizeof(s_mc_expression_t));
mc_expression_t expression = list->locations + i;
+ expression->ops = NULL;
+ mc_dwarf_expression_init(expression, len, ops);
void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
- mc_dwarf_expression_init(expression, len, ops);
- expression->lowpc = (char*) base + start;
- expression->highpc = (char*) base + end;
+ // If start == 0, this is not a location list:
+ expression->lowpc = start == 0 ? NULL : (char*) base + start;
+ expression->highpc = start == 0 ? NULL : (char*) base + end;
}
}