static _Unwind_Reason_Code trace_callback (struct _Unwind_Context * uw_context, uw_data_t * uw_data) { char * pc; #if defined (__ia64__) && defined (__hpux__) /* Work around problem with _Unwind_GetIP on ia64 HP-UX. */ uwx_get_reg ((struct uwx_env *) uw_context, UWX_REG_IP, (uint64_t *) &pc); #else pc = (char *) _Unwind_GetIP (uw_context); #endif if (uw_data->n_frames_skipped < uw_data->n_frames_to_skip) { uw_data->n_frames_skipped ++; return _URC_NO_REASON; } if (uw_data->n_entries_filled >= uw_data->max_len) return _URC_NORMAL_STOP; if (pc < (char *)uw_data->exclude_min || pc > (char *)uw_data->exclude_max) uw_data->traceback [uw_data->n_entries_filled ++] = pc + PC_ADJUST; return _URC_NO_REASON; }
// FIXME: There should be a destructor for this function to free env and info void GetBackTrace(address_t* ipStackBuffer, int iTotalDepth, int iSkipLevel) { uint64_t ip; int status; int index = 0; int nPos = 0; if (!env) { env = uwx_init(); info = uwx_self_init_info(env); status = uwx_register_callbacks(env, (intptr_t)info, uwx_self_copyin, uwx_self_lookupip); if (status != UWX_OK) { env = NULL; return ; } } status = uwx_self_init_context(env); if (status != UWX_OK) { //hk_printf("uwx_self_init_context() error\n"); return ; } for(;;) { if (index >= iTotalDepth) break; if (nPos++ >= iSkipLevel + iTotalDepth) break; status = uwx_get_reg(env, UWX_REG_IP, &ip); if (status != UWX_OK) break; if (nPos > iSkipLevel) ipStackBuffer[index++] = (address_t)ip; status = uwx_step(env); if (status != UWX_OK) break; } // seal the array if(index < iTotalDepth) { ipStackBuffer[index] = 0; } return ; }