add_test(test-surf-usage2 ${CMAKE_BINARY_DIR}/testsuite/surf/surf_usage2 --cfg=path:${CMAKE_HOME_DIRECTORY}/testsuite/surf/ platform.xml)
add_test(test-surf-trace ${CMAKE_BINARY_DIR}/testsuite/surf/trace_usage --cfg=path:${CMAKE_HOME_DIRECTORY}/testsuite/surf/)
+if(HAVE_MC)
+ add_test(mc-dwarf ${CMAKE_BINARY_DIR}/testsuite/mc/dwarf)
+ add_test(mc-dwarf-expression ${CMAKE_BINARY_DIR}/testsuite/mc/dwarf-expression)
+endif()
+
add_test(testall ${CMAKE_BINARY_DIR}/src/testall)
if(enable_auto_install)
src/mc/mc_dpor.c
src/mc/mc_global.c
src/mc/mc_dwarf.c
+ src/mc/mc_dwarf_expression.c
src/mc/mc_liveness.c
src/mc/mc_memory.c
src/mc/mc_private.h
set(TESTSUITE_CMAKEFILES_TXT
testsuite/surf/CMakeLists.txt
testsuite/xbt/CMakeLists.txt
+ testsuite/mc/CMakeLists.txt
)
set(CMAKE_SOURCE_FILES
add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/xbt)
+add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/mc)
add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/surf)
add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/xbt)
--- /dev/null
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+
+#include "mc_private.h"
+
+static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value) {
+ if(state->stack_size>=MC_EXPRESSION_STACK_SIZE)
+ return MC_EXPRESSION_E_STACK_OVERFLOW;
+
+ state->stack[state->stack_size++] = value;
+ return 0;
+}
+
+int mc_dwarf_execute_expression(
+ size_t n, const Dwarf_Op* ops, mc_expression_state_t state) {
+ for(int i=0; i!=n; ++i) {
+ int error = 0;
+ const Dwarf_Op* op = ops + i;
+ uint8_t atom = op->atom;
+
+ switch (atom) {
+
+ // Registers:
+
+ case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3:
+ case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7:
+ case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
+ case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
+ case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
+ 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;
+ unw_word_t res;
+ 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);
+ break;
+ }
+
+ // Frame base:
+
+ case DW_OP_fbreg:
+ {
+ if(!state->frame_base)
+ return MC_EXPRESSION_E_MISSING_FRAME_BASE;
+ error = mc_dwarf_push_value(state, ((uintptr_t)state->frame_base) + op->number);
+ break;
+ }
+
+ // Constants:
+
+ case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3:
+ case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7:
+ case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11:
+ case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15:
+ case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19:
+ case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23:
+ case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27:
+ case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31:
+ error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
+ break;
+
+ case DW_OP_addr:
+ case DW_OP_const1u:
+ case DW_OP_const2u:
+ case DW_OP_const4u:
+ case DW_OP_const8u:
+ case DW_OP_const1s:
+ case DW_OP_const2s:
+ case DW_OP_const4s:
+ case DW_OP_const8s:
+ case DW_OP_constu:
+ case DW_OP_consts:
+ if(state->stack_size==MC_EXPRESSION_STACK_SIZE)
+ return MC_EXPRESSION_E_STACK_OVERFLOW;
+ error = mc_dwarf_push_value(state, op->number);
+ break;
+
+ // Stack manipulation:
+
+ // Push the value at the top of the stack:
+ case DW_OP_dup:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ else
+ error = mc_dwarf_push_value(state, state->stack[state->stack_size-1]);
+ break;
+
+ case DW_OP_drop:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ else
+ state->stack_size--;
+ break;
+
+ case DW_OP_swap:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t temp = state->stack[state->stack_size-2];
+ state->stack[state->stack_size-2] = state->stack[state->stack_size-1];
+ state->stack[state->stack_size-1] = temp;
+ }
+ break;
+
+ case DW_OP_over:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ error = mc_dwarf_push_value(state, state->stack[state->stack_size-2]);
+ break;
+
+ // Operations:
+
+ case DW_OP_plus:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] + state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_mul:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] - state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_plus_uconst:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ state->stack[state->stack_size-1] += op->number;
+ break;
+
+ case DW_OP_not:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ state->stack[state->stack_size-1] = ~state->stack[state->stack_size-1];
+ break;
+
+ case DW_OP_neg:
+ if(state->stack_size==0)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ intptr_t value = state->stack[state->stack_size-1];
+ if(value<0) value = -value;
+ state->stack[state->stack_size-1] = value;
+ }
+ break;
+
+ case DW_OP_minus:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] - state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_and:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] & state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_or:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] | state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_xor:
+ if(state->stack_size<2)
+ return MC_EXPRESSION_E_STACK_UNDERFLOW;
+ {
+ uintptr_t result = state->stack[state->stack_size-2] ^ state->stack[state->stack_size-1];
+ state->stack[state->stack_size-2] = result;
+ state->stack_size--;
+ }
+ break;
+
+ case DW_OP_nop:
+ break;
+
+ // Dereference:
+ case DW_OP_deref_size:
+ case DW_OP_deref:
+ return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
+
+ // Not handled:
+ default:
+ return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
+ }
+
+ if(error) return error;
+ }
+ return 0;
+}
+
+// ***** Location
+
+/** \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) {
+ s_mc_expression_state_t state;
+ memset(&state, 0, sizeof(s_mc_expression_state_t));
+ state.frame_base = frame_pointer_address;
+ state.cursor = c;
+
+ 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];
+}
+
void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
void MC_post_process_types(mc_object_info_t info);
+// ***** Expressions
+
+/** \brief a DWARF expression with optional validity contraints */
+typedef struct s_mc_expression {
+ size_t size;
+ Dwarf_Op* ops;
+ // Optional validity:
+ void* lowpc, *highpc;
+} s_mc_expression_t, *mc_expression_t;
+
+/** A location list (list of location expressions) */
+typedef struct s_mc_location_list {
+ size_t size;
+ mc_expression_t locations;
+} s_mc_location_list_t, *mc_location_list_t;
+
+// ***** Deprecated locations:
+
typedef enum {
e_dw_loclist,
e_dw_register,
dw_location_t location;
}s_dw_location_entry_t, *dw_location_entry_t;
+// ***** Variables and functions
+
typedef struct s_dw_variable{
Dwarf_Off dwarf_offset; /* Global offset of the field. */
int global;
Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address);
void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor);
+#define MC_EXPRESSION_STACK_SIZE 64
+
+#define MC_EXPRESSION_OK 0
+#define MC_EXPRESSION_E_UNSUPPORTED_OPERATION 1
+#define MC_EXPRESSION_E_STACK_OVERFLOW 2
+#define MC_EXPRESSION_E_STACK_UNDERFLOW 3
+#define MC_EXPRESSION_E_MISSING_STACK_CONTEXT 4
+#define MC_EXPRESSION_E_MISSING_FRAME_BASE 5
+
+typedef struct s_mc_expression_state {
+ uintptr_t stack[MC_EXPRESSION_STACK_SIZE];
+ size_t stack_size;
+
+ unw_cursor_t* cursor;
+ void* frame_base;
+} s_mc_expression_state_t, *mc_expression_state_t;
+
+int mc_dwarf_execute_expression(size_t n, const Dwarf_Op* ops, mc_expression_state_t state);
+
/********************************** Miscellaneous **********************************/
typedef struct s_local_variable{
--- /dev/null
+cmake_minimum_required(VERSION 2.6)
+
+if(HAVE_MC)
+ set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+ add_executable(dwarf dwarf.c)
+ target_link_libraries(dwarf simgrid)
+
+ add_executable(dwarf-expression dwarf_expression.c)
+ target_link_libraries(dwarf-expression simgrid)
+endif()
--- /dev/null
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include <xbt.h>
+#include <mc/mc.h>
+
+#include "../../src/include/mc/datatypes.h"
+#include "../../src/mc/mc_private.h"
+
+int test_some_array[4][5][6];
+struct some_struct { int first; int second[4][5]; } test_some_struct;
+
+static dw_type_t find_type_by_name(mc_object_info_t info, const char* name) {
+ xbt_dict_cursor_t cursor = NULL;
+ char *key;
+ dw_type_t type;
+ xbt_dict_foreach(info->types, cursor, key, type) {
+ if(!strcmp(name, type->name))
+ return type;
+ }
+
+ return NULL;
+}
+
+static dw_variable_t find_global_variable_by_name(mc_object_info_t info, const char* name) {
+ unsigned int cursor = 0;
+ dw_variable_t variable;
+ xbt_dynar_foreach(info->global_variables, cursor, variable){
+ if(!strcmp(name, variable->name))
+ return variable;
+ }
+
+ return NULL;
+}
+
+static dw_variable_t test_global_variable(mc_object_info_t info, const char* name, void* address, long byte_size) {
+ dw_variable_t variable = find_global_variable_by_name(info, name);
+ xbt_assert(variable, "Global variable %s was not found", name);
+ xbt_assert(!strcmp(variable->name, name), "Name mismatch for %s", name);
+ xbt_assert(variable->global, "Variable %s is not global", name);
+ xbt_assert(variable->address == address,
+ "Address mismatch for %s : %p expected but %p found", name, address, variable->address);
+
+ dw_type_t type = xbt_dict_get_or_null(mc_binary_info->types, variable->type_origin);
+ xbt_assert(type!=NULL, "Missing type for %s", name);
+ xbt_assert(type->byte_size = byte_size, "Byte size mismatch for %s", name);
+ return variable;
+}
+
+static dw_type_t find_type(mc_object_info_t info, const char* name, dw_type_t type) {
+ unsigned int cursor = 0;
+ dw_type_t member;
+ xbt_dynar_foreach(type->members, cursor, member){
+ if(!strcmp(name,member->name))
+ return member;
+ }
+ return NULL;
+}
+
+int some_local_variable = 0;
+
+int main(int argc, char** argv) {
+
+ // xbt_init(&argc, argv);
+ SIMIX_global_init(&argc, argv);
+ MC_memory_init();
+ MC_init();
+
+ dw_variable_t var;
+ dw_type_t type;
+
+ var = test_global_variable(mc_binary_info, "some_local_variable", &some_local_variable, sizeof(int));
+
+ var = test_global_variable(mc_binary_info, "test_some_array", &test_some_array, sizeof(test_some_array));
+ type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
+ xbt_assert(type->element_count == 6*5*4, "element_count mismatch in test_some_array : %i / %i", type->element_count, 6*5*4);
+
+ var = test_global_variable(mc_binary_info, "test_some_struct", &test_some_struct, sizeof(test_some_struct));
+ type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
+ assert(find_type(mc_binary_info, "first", type)->offset == 0);
+ assert(find_type(mc_binary_info, "second", type)->offset
+ == ((const char*)&test_some_struct.second) - (const char*)&test_some_struct);
+
+ _exit(0);
+}
--- /dev/null
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "../src/mc/mc_private.h"
+
+uintptr_t eval_binary_operation(mc_expression_state_t state, int op, uintptr_t a, uintptr_t b) {
+ state->stack_size = 0;
+
+ Dwarf_Op ops[15];
+ ops[0].atom = DW_OP_addr;
+ ops[0].number = a;
+ ops[1].atom = DW_OP_addr;
+ ops[1].number = b;
+ ops[2].atom = op;
+
+ assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==1);
+ return state->stack[state->stack_size - 1];
+}
+
+void basic_test(mc_expression_state_t state) {
+ Dwarf_Op ops[60];
+
+ uintptr_t a = rand();
+ uintptr_t b = rand();
+
+ ops[0].atom = DW_OP_drop;
+ assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_E_STACK_UNDERFLOW);
+
+ ops[0].atom = DW_OP_lit21;
+ assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==1);
+ assert(state->stack[state->stack_size-1]==21);
+
+ ops[0].atom = DW_OP_addr;
+ ops[0].number = a;
+ assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==2);
+ assert(state->stack[state->stack_size-1] == a);
+
+ ops[0].atom = DW_OP_drop;
+ ops[1].atom = DW_OP_drop;
+ assert(mc_dwarf_execute_expression(2, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==0);
+
+ ops[0].atom = DW_OP_lit21;
+ ops[1].atom = DW_OP_plus_uconst;
+ ops[1].number = a;
+ assert(mc_dwarf_execute_expression(2, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==1);
+ assert(state->stack[state->stack_size-1]== a + 21);
+
+ state->stack_size = 0;
+ ops[0].atom = DW_OP_addr;
+ ops[0].number = a;
+ ops[1].atom = DW_OP_dup;
+ ops[2].atom = DW_OP_plus;
+ assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==1);
+ assert(state->stack[state->stack_size-1]== a + a);
+
+ state->stack_size = 0;
+ ops[0].atom = DW_OP_addr;
+ ops[0].number = a;
+ ops[1].atom = DW_OP_addr;
+ ops[1].number = b;
+ ops[2].atom = DW_OP_over;
+ assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size==3);
+ assert(state->stack[state->stack_size-1]== a);
+ assert(state->stack[state->stack_size-2]== b);
+ assert(state->stack[state->stack_size-3]== a);
+
+ state->stack_size = 0;
+ ops[0].atom = DW_OP_addr;
+ ops[0].number = a;
+ ops[1].atom = DW_OP_addr;
+ ops[1].number = b;
+ ops[2].atom = DW_OP_swap;
+ assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+ assert(state->stack_size=2);
+ assert(state->stack[state->stack_size-1]== a);
+ assert(state->stack[state->stack_size-2]== b);
+}
+
+int main(int argc, char** argv) {
+ s_mc_expression_state_t state;
+ memset(&state, 0, sizeof(s_mc_expression_state_t));
+
+ basic_test(&state);
+
+ for(int i=0; i!=100; ++i) {
+ uintptr_t a = rand();
+ uintptr_t b = rand();
+ assert(eval_binary_operation(&state, DW_OP_plus, a, b) == (a + b));
+ }
+
+ for(int i=0; i!=100; ++i) {
+ uintptr_t a = rand();
+ uintptr_t b = rand();
+ assert(eval_binary_operation(&state, DW_OP_or, a, b) == (a | b));
+ }
+
+ for(int i=0; i!=100; ++i) {
+ uintptr_t a = rand();
+ uintptr_t b = rand();
+ assert(eval_binary_operation(&state, DW_OP_and, a, b) == (a & b));
+ }
+
+ for(int i=0; i!=100; ++i) {
+ uintptr_t a = rand();
+ uintptr_t b = rand();
+ assert(eval_binary_operation(&state, DW_OP_xor, a, b) == (a ^ b));
+ }
+
+ return 0;
+}