Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] mc_comm_pattern.c containing all communication pattern functions
[simgrid.git] / src / mc / mc_dwarf_expression.c
index 3b6c9a4..92e4e47 100644 (file)
@@ -10,6 +10,7 @@
 #include <dwarf.h>
 #include <elfutils/libdw.h>
 
+#include "mc_object_info.h"
 #include "mc_private.h"
 
 static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
@@ -21,6 +22,12 @@ static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
   return 0;
 }
 
+/** Convert a DWARF register into a libunwind register
+ *
+ *  DWARF and libunwind does not use the same convention for numbering the
+ *  registers on some architectures. The function makes the necessary
+ *  convertion.
+ */
 static int mc_dwarf_register_to_libunwind(int dwarf_register)
 {
 #if defined(UNW_TARGET_X86_64)
@@ -82,7 +89,7 @@ static int mc_dwarf_register_to_libunwind(int dwarf_register)
     xbt_die("Bad/unknown register number.");
   }
 #else
-#error This architecture is not supported yet.
+#error This architecture is not supported yet for DWARF expression evaluation.
 #endif
 }
 
@@ -166,15 +173,16 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       {
         if (!state->frame_base)
           return MC_EXPRESSION_E_MISSING_FRAME_BASE;
-        error =
-            mc_dwarf_push_value(state,
-                                ((uintptr_t) state->frame_base) + op->number);
+        uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
+        error = mc_dwarf_push_value(state, fb);
         break;
       }
 
 
-      // Constants:
+      // ***** Constants:
 
+      // Short constant literals:
+      // DW_OP_lit15 pushed the 15 on the stack.
     case DW_OP_lit0:
     case DW_OP_lit1:
     case DW_OP_lit2:
@@ -210,17 +218,20 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
       break;
 
+      // Address from the base address of this ELF object.
+      // Push the address on the stack (base_address + argument).
     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);
+      Dwarf_Off addr = (Dwarf_Off) (uintptr_t)
+        MC_object_base_address(state->object_info) + op->number;
+      error = mc_dwarf_push_value(state, addr);
       break;
 
+      // General constants:
+      // Push the constant argument on the stack.
     case DW_OP_const1u:
     case DW_OP_const2u:
     case DW_OP_const4u:
@@ -236,9 +247,9 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       error = mc_dwarf_push_value(state, op->number);
       break;
 
-      // Stack manipulation:
+      // ***** Stack manipulation:
 
-      // Push the value at the top of the stack:
+      // Push another copy/duplicate the value at the top of the stack:
     case DW_OP_dup:
       if (state->stack_size == 0)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -246,6 +257,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
         error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
       break;
 
+      // Pop/drop the top of the stack:
     case DW_OP_drop:
       if (state->stack_size == 0)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -253,6 +265,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
         state->stack_size--;
       break;
 
+      // Swap the two top-most value of the stack:
     case DW_OP_swap:
       if (state->stack_size < 2)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -264,13 +277,17 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       }
       break;
 
+      // Duplicate the value under the top of the stack:
     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:
+      // ***** Operations:
+      // Those usually take the top of the stack and the next value as argument
+      // and replace the top of the stack with the computed value
+      // (stack.top() += stack.before_top()).
 
     case DW_OP_plus:
       if (state->stack_size < 2)
@@ -371,7 +388,8 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
     case DW_OP_nop:
       break;
 
-      // Dereference:
+      // ***** Deference (memory fetch)
+
     case DW_OP_deref_size:
       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
 
@@ -381,9 +399,19 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       {
         // Computed address:
         uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
-        uintptr_t temp;
-        uintptr_t* res = (uintptr_t*) mc_snapshot_read((void*) address, state->snapshot, state->process_index, &temp, sizeof(uintptr_t));
-        state->stack[state->stack_size - 1] = *res;
+        uintptr_t value;
+        if (state->address_space) {
+          uintptr_t temp;
+          const uintptr_t* res = (uintptr_t*) MC_address_space_read(
+            state->address_space, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+            &temp, (const void*) address, sizeof(uintptr_t), state->process_index);
+          value = *res;
+        }
+        else {
+          // TODO, use a mc_process representing the current process instead of this
+          value = *(const uintptr_t*) address;
+        }
+        state->stack[state->stack_size - 1] = value;
       }
       break;
 
@@ -403,51 +431,77 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
 /** \brief Resolve a location expression
  *  \deprecated Use mc_dwarf_resolve_expression
  */
-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, int process_index)
+void mc_dwarf_resolve_location(mc_location_t location,
+                               mc_expression_t expression,
+                               mc_object_info_t object_info,
+                               unw_cursor_t * c,
+                               void *frame_pointer_address,
+                               mc_address_space_t address_space, int process_index)
 {
   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.address_space = address_space;
   state.object_info = object_info;
   state.process_index = process_index;
 
+  if (expression->size >= 1
+    && expression->ops[0].atom >=DW_OP_reg0 && expression->ops[0].atom <= DW_OP_reg31) {
+    int dwarf_register = expression->ops[0].atom - DW_OP_reg0;
+    xbt_assert(c, "Missing frame context for register operation DW_OP_reg%i",
+      dwarf_register);
+    location->memory_location = NULL;
+    location->cursor = c;
+    location->register_id = mc_dwarf_register_to_libunwind(dwarf_register);
+    return;
+  }
+
   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 state.stack[state.stack_size - 1];
+  else {
+    location->memory_location = (void*) state.stack[state.stack_size - 1];
+    location->cursor = NULL;
+    location->register_id = 0;
+  }
+}
+
+static mc_expression_t mc_find_expression(mc_location_list_t locations, unw_word_t ip) {
+  for (size_t i = 0; i != locations->size; ++i) {
+    mc_expression_t expression = locations->locations + i;
+    if ((expression->lowpc == NULL && expression->highpc == NULL)
+        || (ip && ip >= (unw_word_t) expression->lowpc
+            && ip < (unw_word_t) expression->highpc)) {
+      return expression;
+    }
+  }
+  return NULL;
 }
 
-uintptr_t mc_dwarf_resolve_locations(mc_location_list_t locations,
+void mc_dwarf_resolve_locations(mc_location_t location,
+                                     mc_location_list_t locations,
                                      mc_object_info_t object_info,
                                      unw_cursor_t * c,
                                      void *frame_pointer_address,
-                                     mc_snapshot_t snapshot, int process_index)
+                                     mc_address_space_t address_space, int process_index)
 {
 
-  unw_word_t ip;
+  unw_word_t ip = 0;
   if (c) {
     if (unw_get_reg(c, UNW_REG_IP, &ip))
       xbt_die("Could not resolve IP");
   }
 
-  for (size_t i = 0; i != locations->size; ++i) {
-    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, object_info, c,
-                                       frame_pointer_address, snapshot, process_index);
-    }
+  mc_expression_t expression = mc_find_expression(locations, ip);
+  if (expression) {
+    mc_dwarf_resolve_location(location,
+                              expression, object_info, c,
+                              frame_pointer_address, address_space, process_index);
+  } else {
+    xbt_die("Could not resolve location");
   }
-  xbt_die("Could not resolve location");
 }
 
 /** \brief Find the frame base of a given frame
@@ -458,8 +512,29 @@ uintptr_t mc_dwarf_resolve_locations(mc_location_list_t locations,
 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, -1);
+  s_mc_location_t location;
+  mc_dwarf_resolve_locations(&location,
+                             &frame->frame_base, object_info,
+                             unw_cursor, NULL, NULL, -1);
+  switch(mc_get_location_type(&location)) {
+  case MC_LOCATION_TYPE_ADDRESS:
+    return location.memory_location;
+
+  case MC_LOCATION_TYPE_REGISTER: {
+      // This is a special case.
+      // The register if not the location of the frame base
+      // (a frame base cannot be located in a register)
+      // Instead, DWARF defines this to mean that the register
+      // contains the address of the frame base.
+      unw_word_t word;
+      unw_get_reg(location.cursor, location.register_id, &word);
+      return (void*) word;
+    }
+
+  default:
+    xbt_die("Cannot handle non-address frame base");
+    return NULL; // Unreachable
+  }
 }
 
 void mc_dwarf_expression_clear(mc_expression_t expression)