void hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* cursor, void* context) { mcontext_t *mc = GET_MCONTEXT(context); cursor->pc_unnorm = MCONTEXT_PC(mc); cursor->bp = MCONTEXT_BP(mc); cursor->sp = MCONTEXT_SP(mc); cursor->ra_loc = NULL; TMSG(UNW, "unw_init: pc=%p, ra_loc=%p, sp=%p, bp=%p", cursor->pc_unnorm, cursor->ra_loc, cursor->sp, cursor->bp); cursor->flags = 0; // trolling_used cursor->intvl = hpcrun_addr_to_interval(cursor->pc_unnorm, cursor->pc_unnorm, &cursor->pc_norm); if (!cursor->intvl) { EMSG("unw_init: cursor could NOT build an interval for initial pc = %p", cursor->pc_unnorm); cursor->pc_norm = hpcrun_normalize_ip(cursor->pc_unnorm, NULL); } if (MYDBG) { dump_ui((unwind_interval *)cursor->intvl, 0); } }
void run(char * filename, unsigned long nmaxvalues, double min, double max) { unsigned int i; unsigned int nvalues; double empty_space_needed; unsigned int left; unsigned int right; double median = 0, leftquartile = 0, rightquartile = 0, percentage = 0; gsl_vector * values = gsl_vector_alloc(nmaxvalues); gsl_vector * medians = gsl_vector_alloc(100); gsl_vector * leftquartiles = gsl_vector_alloc(100); gsl_vector * rightquartiles = gsl_vector_alloc(100); gsl_vector * percentages = gsl_vector_alloc(100); gsl_vector * vectors[4]; unsigned int npeaks = 0; vectors[0] = percentages; vectors[1] = medians; vectors[2] = leftquartiles; vectors[3] = rightquartiles; dump_ul("nmaxvalues", nmaxvalues); nvalues = fill_vector(values, filename, min, max); dump_ul("nvalues", nmaxvalues); debug("data ready!"); qsort(values->data, nvalues, sizeof(double), double_comp); debug("data sorted!"); /* 0.1% of parameter space */ empty_space_needed = (max - min) / 100; dump_d("empty_space_needed", empty_space_needed); dump_d("min", min); dump_d("max", max); assert(gsl_vector_get(values, 0) >= min); assert(gsl_vector_get(values, 0) <= max); assert(gsl_vector_get(values, nvalues - 1) >= min); assert(gsl_vector_get(values, nvalues - 1) <= max); left = 0; while (1) { dump_ui("found left side", left); dump_d("left side", gsl_vector_get(values, left)); right = left + 1; for (; right < nvalues; right++) { if (gsl_vector_get(values, right) - gsl_vector_get(values, right - 1) > empty_space_needed) { dump_d("gap till next", gsl_vector_get(values, right) - gsl_vector_get(values, right - 1)); break; } } right--; dump_ui("found right side", right); dump_d("right side", gsl_vector_get(values, right)); analyse_part(values, left, right, nvalues, &median, &leftquartile, &rightquartile, &percentage); gsl_vector_set(medians, npeaks, median); gsl_vector_set(leftquartiles, npeaks, leftquartile); gsl_vector_set(rightquartiles, npeaks, rightquartile); gsl_vector_set(percentages, npeaks, percentage); npeaks++; assert(npeaks < 100); if (right == nvalues - 1) break; left = right + 1; } #ifndef NOSORT sort(vectors, 4, npeaks); #endif printf("median\t-\t+\tpercent\n"); fflush(NULL); for (i = 0; i < npeaks; i++) { printf("%f\t%f\t%f\t%f\n", gsl_vector_get(medians, i), gsl_vector_get( medians, i) - gsl_vector_get(leftquartiles, i), gsl_vector_get( rightquartiles, i) - gsl_vector_get(medians, i), gsl_vector_get(percentages, i)); } gsl_vector_free(values); gsl_vector_free(medians); gsl_vector_free(leftquartiles); gsl_vector_free(rightquartiles); gsl_vector_free(percentages); }
static step_state unw_step_bp(hpcrun_unw_cursor_t* cursor) { void *sp, **bp, *pc; void **next_sp, **next_bp, *next_pc; unwind_interval *uw; TMSG(UNW_STRATEGY,"Using BP step"); // current frame bp = cursor->bp; sp = cursor->sp; pc = cursor->pc_unnorm; uw = (unwind_interval *)cursor->intvl; TMSG(UNW,"step_bp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc); if (MYDBG) { dump_ui(uw, 0); } if (!(sp <= (void*) bp)) { TMSG(UNW," step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not" " >= sp(%p)", bp, sp); return STEP_ERROR; } if (DISABLED(OMP_SKIP_MSB)) { if (!((void *)bp < monitor_stack_bottom())) { TMSG(UNW," step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not" " between sp (%p) and monitor stack bottom (%p)", bp, sp, monitor_stack_bottom()); return STEP_ERROR; } } // bp relative next_sp = (void **)((void *)bp + uw->bp_bp_pos); next_bp = *next_sp; next_sp = (void **)((void *)bp + uw->bp_ra_pos); void* ra_loc = (void*) next_sp; next_pc = *next_sp; next_sp += 1; if ((void *)next_sp > sp) { // this condition is a weak correctness check. only // try building an interval for the return address again if it succeeds ip_normalized_t next_pc_norm = ip_normalized_NULL; uw = (unwind_interval *)hpcrun_addr_to_interval(((char *)next_pc) - 1, next_pc, &next_pc_norm); if (! uw){ if (((void *)next_sp) >= monitor_stack_bottom()) { TMSG(UNW," step_bp: STEP_STOP_WEAK, next_sp >= monitor_stack_bottom," " next_sp = %p", next_sp); return STEP_STOP_WEAK; } TMSG(UNW," step_bp: STEP_ERROR, cannot build interval for next_pc(%p)", next_pc); return STEP_ERROR; } else { cursor->pc_unnorm = next_pc; cursor->bp = next_bp; cursor->sp = next_sp; cursor->ra_loc = ra_loc; cursor->pc_norm = next_pc_norm; cursor->intvl = (splay_interval_t *)uw; TMSG(UNW," step_bp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p", cursor->intvl != NULL, next_bp, next_sp, next_pc); return STEP_OK; } } else { TMSG(UNW_STRATEGY,"BP unwind fails: bp (%p) < sp (%p)", bp, sp); return STEP_ERROR; } EMSG("FALL Through BP unwind: shouldn't happen"); return STEP_ERROR; }
static step_state unw_step_sp(hpcrun_unw_cursor_t* cursor) { TMSG(UNW_STRATEGY,"Using SP step"); // void *stack_bottom = monitor_stack_bottom(); // current frame void** bp = cursor->bp; void* sp = cursor->sp; void* pc = cursor->pc_unnorm; unwind_interval* uw = (unwind_interval *)cursor->intvl; TMSG(UNW,"step_sp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc); if (MYDBG) { dump_ui(uw, 0); } void** next_bp = NULL; void** next_sp = (void **)(sp + uw->sp_ra_pos); void* ra_loc = (void*) next_sp; void* next_pc = *next_sp; TMSG(UNW," step_sp: potential next cursor next_sp=%p ==> next_pc = %p", next_sp, next_pc); if (uw->bp_status == BP_UNCHANGED){ next_bp = bp; TMSG(UNW," step_sp: unwind step has BP_UNCHANGED ==> next_bp=%p", next_bp); } else { //----------------------------------------------------------- // reload the candidate value for the caller's BP from the // save area in the activation frame according to the unwind // information produced by binary analysis //----------------------------------------------------------- next_bp = (void **)(sp + uw->sp_bp_pos); TMSG(UNW," step_sp: unwind next_bp loc = %p", next_bp); next_bp = *next_bp; TMSG(UNW," step_sp: sp unwind next_bp val = %p", next_bp); } next_sp += 1; ip_normalized_t next_pc_norm = ip_normalized_NULL; cursor->intvl = hpcrun_addr_to_interval(((char *)next_pc) - 1, next_pc, &next_pc_norm); if (! cursor->intvl){ if (((void *)next_sp) >= monitor_stack_bottom()){ TMSG(UNW," step_sp: STEP_STOP_WEAK, no next interval and next_sp >= stack bottom," " so stop unwind ..."); return STEP_STOP_WEAK; } else { TMSG(UNW," sp STEP_ERROR: no next interval, step fails"); return STEP_ERROR; } } else { // sanity check to avoid infinite unwind loop if (next_sp <= cursor->sp){ TMSG(INTV_ERR,"@ pc = %p. sp unwind does not advance stack." " New sp = %p, old sp = %p", cursor->pc_unnorm, next_sp, cursor->sp); return STEP_ERROR; } unwind_interval* uw = (unwind_interval *)cursor->intvl; if ((RA_BP_FRAME == uw->ra_status) || (RA_STD_FRAME == uw->ra_status)) { // Makes sense to sanity check BP, do it //----------------------------------------------------------- // if value of BP reloaded from the save area does not point // into the stack, then it cannot possibly be useful as a frame // pointer in the caller or any of its ancesters. // // if the value in the BP register points into the stack, then // it might be useful as a frame pointer. in this case, we have // nothing to lose by assuming that our binary analysis for // unwinding might have been mistaken and that the value in // the register is the one we might want. // // 19 December 2007 - John Mellor-Crummey //----------------------------------------------------------- if (((unsigned long) next_bp < (unsigned long) sp) && ((unsigned long) bp > (unsigned long) sp)){ next_bp = bp; TMSG(UNW," step_sp: unwind bp sanity check fails." " Resetting next_bp to current bp = %p", next_bp); } } cursor->pc_unnorm = next_pc; cursor->bp = next_bp; cursor->sp = next_sp; cursor->ra_loc = ra_loc; cursor->pc_norm = next_pc_norm; } TMSG(UNW," step_sp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p", cursor->intvl != NULL, next_bp, next_sp, next_pc); return STEP_OK; }
static step_state hpcrun_unw_step_real(hpcrun_unw_cursor_t* cursor) { cursor->fence = hpcrun_check_fence(cursor->pc_unnorm); //----------------------------------------------------------- // check if we have reached the end of our unwind, which is // demarcated with a fence. //----------------------------------------------------------- if (fence_stop(cursor->fence)) { TMSG(UNW,"unw_step: STEP_STOP, current pc in monitor fence pc=%p\n", cursor->pc_unnorm); return STEP_STOP; } // current frame void** bp = cursor->bp; void* sp = cursor->sp; void* pc = cursor->pc_unnorm; unwind_interval* uw = (unwind_interval *)cursor->intvl; int unw_res; if (!uw){ TMSG(UNW, "unw_step: invalid unw interval for cursor, trolling ..."); TMSG(TROLL, "Troll due to Invalid interval for pc %p", pc); update_cursor_with_troll(cursor, 0); return STEP_TROLL; } switch (uw->ra_status){ case RA_SP_RELATIVE: unw_res = unw_step_sp(cursor); break; case RA_BP_FRAME: unw_res = unw_step_bp(cursor); break; case RA_STD_FRAME: unw_res = unw_step_std(cursor); break; default: EMSG("unw_step: ILLEGAL UNWIND INTERVAL"); dump_ui((unwind_interval *)cursor->intvl, 0); assert(0); } if (unw_res == STEP_STOP_WEAK) unw_res = STEP_STOP; if (unw_res != STEP_ERROR) { return unw_res; } TMSG(TROLL,"unw_step: STEP_ERROR, pc=%p, bp=%p, sp=%p", pc, bp, sp); dump_ui_troll(uw); if (ENABLED(TROLL_WAIT)) { fprintf(stderr,"Hit troll point: attach w gdb to %d\n" "Maybe call dbg_set_flag(DBG_TROLL_WAIT,0) after attached\n", getpid()); // spin wait for developer to attach a debugger and clear the flag while(DEBUG_WAIT_BEFORE_TROLLING); } update_cursor_with_troll(cursor, 1); return STEP_TROLL; }