static int idbg_setstackitem( SGS_CTX ) { sgs_Bool full = 0; sgs_Int off, cnt; sgs_Variable* a, *b, *x, tmp; SGS_IDBG = (sgs_IDbg*) C->msg_ctx; SGSFN( "dbg_setstackitem" ); if( !sgs_LoadArgs( C, "i?v|b", &off, &full ) ) return 0; a = full ? C->stack_base : C->stack_base + D->stkoff; b = C->stack_base + D->stksize; cnt = b - a; if( off >= cnt || -off > cnt ) { sgs_Msg( C, SGS_WARNING, "index %d out of bounds, count = %d\n", (int) off, (int) cnt ); return 0; } x = off >= 0 ? a + off : b + off; tmp = *x; sgs_Acquire( C, &tmp ); sgs_GetStackItem( C, 1, x ); sgs_Release( C, &tmp ); return 0; }
static void mode3hook( void* userdata, SGS_CTX, int evid ) { sgs_ProfData* P = (sgs_ProfData*) userdata; if( P->hfn ) P->hfn( P->hctx, C, evid ); if( evid == SGS_HOOK_ENTER || evid == SGS_HOOK_CONT || evid == SGS_HOOK_EXIT || evid == SGS_HOOK_PAUSE ) { SGS_SHCTX_USE; mode3item CD = { NULL, S->numallocs, S->numfrees, S->numblocks, (double) S->memsize }; sgs_StackFrame* target = NULL, *sf, *lastrec = NULL; mode3item* items = SGS_ASSUME_ALIGNED( P->frametmp.ptr, mode3item ); size_t i, itemcount = P->frametmp.size / sizeof(mode3item); if( evid == SGS_HOOK_ENTER || evid == SGS_HOOK_CONT ) target = C->sf_last; else if( evid == SGS_HOOK_EXIT ) target = C->sf_last->prev; /* pause => null */ /* ignore the case when target = current */ if( itemcount && items[ itemcount - 1 ].frame == target ) return; /* find target in stack */ for( i = 0; i < itemcount; ++i ) { if( items[ i ].frame == target ) break; } if( i == itemcount ) { /* find last recorded frame in call stack */ sf = NULL; if( itemcount ) { sf = C->sf_first; while( sf ) { if( items[ itemcount - 1 ].frame == sf ) break; sf = sf->next; } } lastrec = sf; if( sf == NULL || target == NULL ) i = 0; /* frame not found/req., remove everything */ /* otherwise, remove nothing, it's an "ENTER" */ } else i++; /* remove starting from next frame */ /* if there is anything to remove */ if( i < itemcount ) { size_t bki = i; sf = C->sf_first; /* generate core key (from start to first removed incl.) */ sgs_membuf_resize( &P->keytmp, C, 0 ); while( sf && sf != items[ i ].frame ) { const char* fname = "<error>"; sgs_StackFrameInfo( C, sf, &fname, NULL, NULL ); sgs_membuf_appbuf( &P->keytmp, C, fname, strlen( fname ) ); sgs_membuf_appchr( &P->keytmp, C, 0 ); sf = sf->next; } /* iterate removable frames (assuming frame pointers are valid) */ for( ; i < itemcount; ++i ) { const char* fname = "<error>"; sgs_StackFrameInfo( C, items[ i ].frame, &fname, NULL, NULL ); sgs_membuf_appbuf( &P->keytmp, C, fname, strlen( fname ) ); sgs_membuf_appchr( &P->keytmp, C, 0 ); /* commit memory addition */ { mode3item prevCD = items[ i ], *PD; sgs_VHTVar* pair = sgs_vht_get_str( &P->prof->timings, P->keytmp.ptr, (uint32_t) P->keytmp.size, sgs_HashFunc( P->keytmp.ptr, P->keytmp.size ) ); if( pair ) { PD = (mode3item*) pair->val.data.P; } else { sgs_Variable key, val; val.type = SGS_VT_PTR; val.data.P = PD = sgs_Alloc( mode3item ); memset( PD, 0, sizeof(*PD) ); sgs_InitStringBuf( C, &key, P->keytmp.ptr, (sgs_SizeVal) P->keytmp.size ); sgs_vht_set( &P->prof->timings, C, &key, &val ); sgs_Release( C, &key ); } PD->numallocs += CD.numallocs - prevCD.numallocs; PD->numfrees += CD.numfrees - prevCD.numfrees; PD->numblocks += CD.numblocks - prevCD.numblocks; PD->szdelta += CD.szdelta - prevCD.szdelta; } } /* commit size */ sgs_membuf_resize( &P->frametmp, C, bki * sizeof(mode3item) ); itemcount = bki; } /* add new frame start times */ if( lastrec || ( target != NULL && itemcount == 0 ) ) { if( lastrec ) sf = lastrec->next; else sf = C->sf_first; while( sf ) { mode3item NI = CD; NI.frame = sf; sgs_membuf_appbuf( &P->frametmp, C, &NI, sizeof(NI) ); if( sf == target ) break; sf = sf->next; } } } else if( evid == SGS_HOOK_CREAT ) { sgs_ProfAttach( C, P->prof ); } else if( evid == SGS_HOOK_CFREE ) { sgs_ProfDetach( C, P->prof ); } /* CFORK not supported yet */ }