Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/byakugan/heapModeler.cpp
Views: 11766
#include "byakugan.h"1#include "heapStructs.h"23// Get offset into the hash map4ULONG hash(PVOID addr, struct HPool *heap) {5ULONG offset;67// assume 8 bit alignment, and use the golden ratio of 2^328offset = (((ULONG) addr >> 3) * (2654435761)) % (0x007fffff/8);9//dprintf("[XXX] Hashed to bucket %d\n", offset);1011return (offset);12}1314/*15* added by jc. I need to be able to find the offset of a chunk inide the chunks array quickly.16* returns < 0 on error.17*/18int FindOffsetForChunk(struct HPool *heap, PVOID memoryPointer)19{20ULONG i;2122i = hash(memoryPointer, heap);23i = heap->map[i];24while (i != NULLNODE) {25if (CHUNK(i).addr == memoryPointer)26return (i);27i = CHUNK(i).nextBucket;28}29return (NULLNODE); // error30}3132ULONG insertBucket(ULONG newC, struct HPool *heap, ULONG inAfter) {33ULONG offset, lastNum, checkNum;3435heap->numChunks++;36CHUNK(newC).inUse = TRUE;3738// Set up nextInUse list39if (inAfter == NULLNODE) {40if (heap->inUseHead == NULLNODE) heap->inUseHead = newC;41else CHUNK(heap->lastInUse).nextInUse = newC;42heap->lastInUse = newC;43CHUNK(newC).nextInUse = NULLNODE;44//dprintf("[T] Inserting new chunk %d at the end\n", newC);45} else {46//dprintf("[T] Inserting new chunk %d after chunk %d\n", newC, inAfter);47if (heap->lastInUse == inAfter) heap->lastInUse = newC;48CHUNK(newC).nextInUse = CHUNK(inAfter).nextInUse;49CHUNK(inAfter).nextInUse = newC;50}5152offset = hash(CHUNK(newC).addr, heap);5354if (heap->map[offset] == NULLNODE) {55heap->map[offset] = newC;56CHUNK(newC).nextBucket = NULLNODE;57} else {58offset = heap->map[offset];59while (CHUNK(offset).nextBucket != NULLNODE)60offset = CHUNK(offset).nextBucket;61CHUNK(newC).nextBucket = NULLNODE;62CHUNK(offset).nextBucket = newC;63}64return (newC);65}6667void removeBucket(PVOID addr, struct HPool *heap) {68ULONG offset, chunkNum, last = NULLNODE;6970if (heap == NULL)71return;727374offset = hash(addr, heap);75chunkNum = heap->map[offset];7677// Find our bucket and the bucket before it78while (chunkNum != NULLNODE && CHUNK(chunkNum).addr != addr) {79last = chunkNum;80chunkNum = CHUNK(chunkNum).nextBucket;81}8283// remove our bucket from the list if we found it84if (chunkNum != NULLNODE) {85//dprintf("[T] Deleting node %d\n", chunkNum);86CHUNK(chunkNum).inUse = FALSE;8788if (last == NULLNODE)89heap->map[offset] = NULLNODE;90else91CHUNK(last).nextBucket = CHUNK(chunkNum).nextBucket;9293heap->numChunks--;94} else95dprintf("[T] Couldnt find chunk 0x%08x to delete :(\n", addr);969798// Head of the list case99chunkNum = heap->inUseHead;100if (CHUNK(chunkNum).addr == addr) {101heap->inUseHead = CHUNK(chunkNum).nextInUse;102return;103}104105// search the list for the previous chunk106while (chunkNum != NULLNODE && CHUNK(chunkNum).addr != addr) {107last = chunkNum;108chunkNum = CHUNK(chunkNum).nextInUse;109}110if (chunkNum != NULLNODE) {111CHUNK(last).nextInUse = CHUNK(chunkNum).nextInUse;112if (heap->lastInUse == chunkNum) heap->lastInUse = last;113}114}115116void initializeHeapModel(struct HeapState *heapModel) {117118memset(heapModel+1, 0, sizeof (struct HeapState));119heapModel->hPoolListLen = 16;120heapModel->heaps = (struct HPool *) calloc(heapModel->hPoolListLen, sizeof (struct HPool));121}122123#define ALLOCHEAD "<Allocation>\n"124#define ALLOCFOOT "</Allocation>\n"125#define REALLOCHEAD "<Reallocation>\n"126#define REALLOCFOOT "</Reallocation>\n"127#define FREEHEAD "<Free>\n"128#define FREEFOOT "</Free>\n"129#define HEAP "\t<Heap>0x%08x</Heap>\n"130#define ADDRESS "\t<Address>0x%08x</Address>\n"131#define RETURNPTR "\t<NewAddress>0x%08x</NewAddress>\n"132#define SIZE "\t<Size>0x%08x</Size>\n"133#define TRACEHEAD "\t<StackTrace>\n"134#define TRACEFOOT "\t</StackTrace>\n"135#define CALLADDR "\t\t<Caller>0x%08x</Caller>\n"136137void hprintf(HANDLE fHandle, char *format, ...) {138char ptr[1024];139DWORD out;140va_list args;141142va_start(args, format);143144145StringCbVPrintf(ptr, 1024, format, args);146WriteFile(fHandle, ptr, strlen(ptr), &out, NULL);147}148149void logAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct) {150ULONG infoUsed;151152WriteFile(heapModel->hLogFile, ALLOCHEAD, strlen(ALLOCHEAD), &infoUsed, NULL);153hprintf(heapModel->hLogFile, HEAP, aStruct->heapHandle);154hprintf(heapModel->hLogFile, ADDRESS, aStruct->ret);155hprintf(heapModel->hLogFile, SIZE, aStruct->size);156WriteFile(heapModel->hLogFile, TRACEHEAD, strlen(TRACEHEAD), &infoUsed, NULL);157158hprintf(heapModel->hLogFile, CALLADDR, aStruct->caller);159160WriteFile(heapModel->hLogFile, TRACEFOOT, strlen(TRACEFOOT), &infoUsed, NULL);161WriteFile(heapModel->hLogFile, ALLOCFOOT, strlen(ALLOCFOOT), &infoUsed, NULL);162}163164void logReallocate(struct HeapState *heapModel, struct ReallocateStruct *rStruct) {165ULONG infoUsed;166167WriteFile(heapModel->hLogFile, REALLOCHEAD, strlen(REALLOCHEAD), &infoUsed, NULL);168hprintf(heapModel->hLogFile, HEAP, rStruct->heapHandle);169hprintf(heapModel->hLogFile, ADDRESS, rStruct->memoryPointer);170hprintf(heapModel->hLogFile, RETURNPTR, rStruct->ret);171hprintf(heapModel->hLogFile, SIZE, rStruct->size);172WriteFile(heapModel->hLogFile, TRACEHEAD, strlen(TRACEHEAD), &infoUsed, NULL);173174hprintf(heapModel->hLogFile, CALLADDR, rStruct->caller);175176WriteFile(heapModel->hLogFile, TRACEFOOT, strlen(TRACEFOOT), &infoUsed, NULL);177WriteFile(heapModel->hLogFile, ALLOCFOOT, strlen(REALLOCFOOT), &infoUsed, NULL);178}179180void logFree(struct HeapState *heapModel, struct FreeStruct *fStruct) {181ULONG infoUsed;182183WriteFile(heapModel->hLogFile, FREEHEAD, strlen(FREEHEAD), &infoUsed, NULL);184hprintf(heapModel->hLogFile, HEAP, fStruct->heapHandle);185hprintf(heapModel->hLogFile, ADDRESS, fStruct->memoryPointer);186WriteFile(heapModel->hLogFile, TRACEHEAD, strlen(TRACEHEAD), &infoUsed, NULL);187188hprintf(heapModel->hLogFile, CALLADDR, fStruct->caller);189190WriteFile(heapModel->hLogFile, TRACEFOOT, strlen(TRACEFOOT), &infoUsed, NULL);191WriteFile(heapModel->hLogFile, FREEFOOT, strlen(FREEFOOT), &infoUsed, NULL);192}193194void heapAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct) {195struct HPool *myHeap;196struct HeapChunk *myChunk, *remainder;197198if (aStruct->heapHandle == 0 || aStruct->ret == 0)199return;200201myHeap = getHeap(heapModel, aStruct->heapHandle);202myChunk = getChunk(myHeap, aStruct->ret, NULLNODE);203204if (myChunk == NULL)205return;206207if (myChunk->size > aStruct->size + SPACEBETWEEN) {208//dprintf("[T] Splitting chunk at 0x%08x:\n", aStruct->ret);209//dprintf("\tNew Chunk 0x%08x, size %d bytes, after chunk %u\n",210// ((ULONG) aStruct->ret + aStruct->size + SPACEBETWEEN),211// (myChunk->size - aStruct->size - SPACEBETWEEN),212// FindOffsetForChunk(myHeap, myChunk->addr));213remainder = getChunk(myHeap,214(PVOID) ((ULONG) aStruct->ret + aStruct->size + SPACEBETWEEN),215FindOffsetForChunk(myHeap, myChunk->addr));216remainder->size = (myChunk->size - aStruct->size) - SPACEBETWEEN;217remainder->free = TRUE;218}219220myChunk->size = aStruct->size;221myChunk->flags = aStruct->flags;222myChunk->free = FALSE;223}224225void heapReallocate(struct HeapState *heapModel, struct ReallocateStruct *rStruct) {226struct HPool *myHeap;227struct HeapChunk *oChunk, *nChunk, *remainder;228229if (rStruct->heapHandle == 0 || rStruct->ret == 0)230return;231232myHeap = getHeap(heapModel, rStruct->heapHandle);233nChunk = getChunk(myHeap, rStruct->ret, NULLNODE);234if (nChunk == NULL)235return;236237if (rStruct->ret != rStruct->memoryPointer && rStruct->memoryPointer != 0) {238oChunk = getChunk(myHeap, rStruct->memoryPointer, NULLNODE);239if (oChunk != NULL)240oChunk->free = TRUE;241}242243// Split new chunk on realloc move if necessary244if (nChunk->size > rStruct->size + SPACEBETWEEN) {245remainder = getChunk(myHeap,246(PVOID) ((ULONG) rStruct->ret + rStruct->size + SPACEBETWEEN),247FindOffsetForChunk(myHeap, nChunk->addr));248remainder->size = (nChunk->size - rStruct->size) - SPACEBETWEEN;249remainder->free = TRUE;250}251252nChunk->size = rStruct->size;253nChunk->flags = rStruct->flags;254nChunk->free = FALSE;255}256257void heapFree(struct HeapState *heapModel, struct FreeStruct *fStruct) {258struct HPool *myHeap;259struct HeapChunk *myChunk;260261//dprintf("[XXX] Freeing 0x%08x\n", fStruct->memoryPointer);262263if (fStruct->heapHandle == 0 || fStruct->memoryPointer == 0x00000000) {264// So many of these that it slows us down :(265//dprintf("[T] Program attempted to free a NULL pointer.\n\n");266return;267}268myHeap = getHeap(heapModel, fStruct->heapHandle);269myChunk = getChunk(myHeap, fStruct->memoryPointer, NULLNODE);270if (myChunk == NULL)271return; // dupe free :(272273#if 0274if (myChunk->free == 2)275dprintf("[T] Possible 'double free' of chunk @ 0x%08x:0x%x\n\n",276myChunk->addr, myChunk->free);277#endif278279myChunk->flags = fStruct->flags;280myChunk->free += 1;281}282283void heapCreate(struct HeapState *heapModel, struct CreateStruct *cStruct) {284struct HPool *newHeap;285ULONG i;286287if (cStruct->base == 0)288return;289290newHeap = getHeap(heapModel, cStruct->base);291newHeap->commit = cStruct->commit;292newHeap->reserve = cStruct->reserve;293newHeap->lock = cStruct->lock;294newHeap->flags = cStruct->flags;295}296297void heapDestroy(struct HeapState *heapModel, struct DestroyStruct *dStruct) {298// Only place we mark heaps as not in use299struct HPool *deadHeap;300301if (dStruct->heapHandle == 0)302return;303304deadHeap = getHeap(heapModel, dStruct->heapHandle);305free(deadHeap->chunks);306memset(deadHeap, 0, sizeof(struct HPool));307heapModel->numHeaps--;308}309310void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct) {311// Only place we mark chunks as not in use312ULONG i, j, latest, last, offset;313struct HPool *heap;314315if (heapModel->numHeaps == 0)316return;317318// Get the heap handle from the CoalesceStruct319heap = getHeap(heapModel, cfbStruct->heapHandle);320321if (heap->numChunks < 2)322return;323324//dprintf("[T] Attempting to coalese heap 0x%08x...\n", cfbStruct->heapHandle);325326i = heap->inUseHead;327328//dprintf("[T] Starting with chunk %d at 0x%08x\n", i, CHUNK(i).addr);329330// Walk the list Coalescing consecutive free chunks331// This assumes that two chunks in a row are actually consecutive...332// This is wrong. If I alloc two large blocks, free the first, then alloc333// a small one, then free the small one and the second one, then coalesce334// the result will ignore the space in between, so we need to take addresses335// into account, and/or we need to create free spaceholder chunks when creating336// chunks in a smaller space than is currently existing.337while (i != NULLNODE) {338if (CHUNK(i).free) {339//dprintf("[T] Found free chunk %d at 0x%08x\n", i, CHUNK(i).addr);340j = FindOffsetForChunk(heap, NEXTADDR(i));341while (j != NULLNODE && CHUNK(j).free) {342343//dprintf("[T] Found free chunk %d at 0x%08x\n", j, CHUNK(j).addr);344345// XXX Handle this by address for unknown chunks346CHUNK(i).size += CHUNK(j).size + SPACEBETWEEN; // This is only right on Vista... and only347// most of the time - win2k is insane and348// goes backwards :(349350// fix up hash bucket list351removeBucket(CHUNK(j).addr, heap);352353//dprintf("[T] Coalescing 0x%08x and 0x%08x. New size: %d bytes\n",354//CHUNK(i).addr, CHUNK(j).addr, CHUNK(i).size);355356j = FindOffsetForChunk(heap, NEXTADDR(i));357}358}359i = CHUNK(i).nextInUse;360// Check Address ordering361// If out of order, quicksort then start this loop again362// from first in use363}364365}366367struct HPool *getHeap(struct HeapState *heapModel, PVOID heapHandle) {368ULONG i;369struct HPool *newHeap = NULL;370371for (i = 0; i < heapModel->hPoolListLen; i++) {372if ((heapModel->heaps[i]).base == heapHandle)373return (&(heapModel->heaps[i]));374if (heapModel->numHeaps == heapModel->hPoolListLen) // Add some short circuits here375continue;376if (newHeap != NULL)377continue;378if ((heapModel->heaps[i]).inUse == FALSE)379newHeap = &(heapModel->heaps[i]);380}381382// If we get here we haven't found a heap, so lets make one383//dprintf("[T] Creating entry for heap: 0x%08x\n", heapHandle);384385if (newHeap == NULL) {386heapModel->hPoolListLen = heapModel->hPoolListLen * 2;387newHeap = heapModel->heaps;388heapModel->heaps = (struct HPool *) realloc(heapModel->heaps,389heapModel->hPoolListLen * sizeof(struct HPool));390if (heapModel->heaps == NULL) {391heapModel->heaps = newHeap;392//crushModel(heapModel); ADD ME XXX393#ifndef THREEDHEAPFU_ENABLED394dprintf("[T] OOM getting new heaps!\n\n");395#endif396return (NULL);397}398newHeap = &(heapModel->heaps[heapModel->numHeaps]);399// Clean the newly allocated memory400memset(newHeap, 0, (sizeof (struct HPool) * (heapModel->hPoolListLen - heapModel->numHeaps)));401}402403heapModel->numHeaps++;404newHeap->base = heapHandle;405newHeap->inUse = TRUE;406newHeap->chunkListLen = 32;407newHeap->chunks = (struct HeapChunk *) calloc(newHeap->chunkListLen,408sizeof (struct HeapChunk));409newHeap->map = (ULONG *) malloc((0x007fffff/8) * sizeof (ULONG));410memset(newHeap->map, 0xff, (0x007fffff/8) * sizeof (ULONG));411newHeap->inUseHead = newHeap->lastInUse = NULLNODE;412413return (newHeap);414}415416struct HeapChunk *getChunk(struct HPool *heap, PVOID memoryPointer, ULONG inAfter) {417ULONG i, *oldMap;418struct HeapChunk *newChunk, *niuChunk = NULL;419420i = hash(memoryPointer, heap);421i = heap->map[i];422while (i != NULLNODE) {423if (CHUNK(i).addr == memoryPointer)424return (&CHUNK(i));425i = CHUNK(i).nextBucket;426}427428if (niuChunk == NULL) {429if (heap->numChunks < heap->chunkListLen) {430if ((heap->chunks[heap->numChunks]).inUse == FALSE) {431//dprintf("[XXX] FOUND CHUNK WHERE EXPECTED! :)\n\n");432niuChunk = &(heap->chunks[heap->numChunks]);433niuChunk->addr = memoryPointer;434niuChunk->heapHandle = heap->base;435insertBucket(heap->numChunks, heap, inAfter);436return (niuChunk);437}438// Heap has been coalesced and there are gaps439// Work backwards in this case - should be MUCH faster440// If this is noticably slow, we'll switch to a stack of unused chunks441// (realloc stack with heap)442for (i = 0; i < heap->chunkListLen; i++) {443if ((heap->chunks[i]).inUse == FALSE) {444niuChunk = &(heap->chunks[i]);445niuChunk->addr = memoryPointer;446niuChunk->heapHandle = heap->base;447insertBucket(i, heap, inAfter);448return (niuChunk);449}450}451dprintf("[XXX] Totally fucked up - chunk info doesnt jive with heap\n\n");452}453454heap->chunkListLen = heap->chunkListLen * 2;455niuChunk = heap->chunks;456heap->chunks = (struct HeapChunk *) realloc(heap->chunks,457heap->chunkListLen * sizeof (struct HeapChunk));458459if (heap->chunks == NULL) {460heap->chunks = niuChunk;461//crushHeap(heap);462heap->chunkListLen = heap->chunkListLen/2;463#ifndef THREEDHEAPFU_ENABLED464dprintf("[T] OOM getting new chunks! %d -> %d\n\n",465heap->chunkListLen, heap->chunkListLen*2);466#endif467return (NULL);468}469470niuChunk = &(heap->chunks[heap->numChunks]);471memset(niuChunk, 0, (sizeof (struct HeapChunk) * (heap->chunkListLen - heap->numChunks)));472}473474niuChunk->addr = memoryPointer;475niuChunk->heapHandle = heap->base;476insertBucket(heap->numChunks, heap, inAfter);477return (niuChunk);478}479480481