void __wrap_free(void *ptr) { unsigned long addr = (unsigned long) ptr; /* * We need to know how the allocation happened, so it can be correctly * freed. This is done by seeing what region of memory the pointer is * in - * physical memory - kmalloc/kfree * kernel virtual memory - vmalloc/vfree * anywhere else - malloc/free * If kmalloc is not yet possible, then either high_physmem and/or * end_vm are still 0 (as at startup), in which case we call free, or * we have set them, but anyway addr has not been allocated from those * areas. So, in both cases __real_free is called. * * CAN_KMALLOC is checked because it would be bad to free a buffer * with kmalloc/vmalloc after they have been turned off during * shutdown. * XXX: However, we sometimes shutdown CAN_KMALLOC temporarily, so * there is a possibility for memory leaks. */ if ((addr >= uml_physmem) && (addr < high_physmem)) { if (kmalloc_ok) kfree(ptr); } else if ((addr >= start_vm) && (addr < end_vm)) { if (kmalloc_ok) vfree(ptr); } else __real_free(ptr); }
void *__wrap_realloc(void *p, size_t size) { void *n; // ptr from mem2 if(((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE)) { n = g_mem2gp.reallocate(p, size); if(n != 0) return n; n = __real_malloc(size); if(n == 0) return 0; if(p != 0) { memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size); g_mem2gp.release(p); } return n; } // ptr from malloc n = __real_realloc(p, size); if(n != 0) return n; n = g_mem2gp.allocate(size); if(n == 0) return 0; if(p != 0) { memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size); __real_free(p); } return n; }
extern "C" NS_EXPORT jobject JNICALL Java_org_mozilla_goanna_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jstring jDb, jstring jQuery, jobjectArray jParams, jlongArray jQueryRes) { JNI_Setup(jenv); int rc; jobject jCursor = NULL; const char* dbPath; sqlite3 *db; char* errorMsg; dbPath = jenv->GetStringUTFChars(jDb, NULL); rc = f_sqlite3_open(dbPath, &db); jenv->ReleaseStringUTFChars(jDb, dbPath); if (rc != SQLITE_OK) { asprintf(&errorMsg, "Can't open database: %s\n", f_sqlite3_errmsg(db)); LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/goanna/sqlite/SQLiteBridgeException", errorMsg); // errorMsg is allocated by asprintf, it needs to be freed by libc. __real_free(errorMsg); } else { jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes); } f_sqlite3_close(db); return jCursor; }
/* * __wrap_free - free wrapper function */ void __wrap_free(void *ptr) { printf("@ %s:[%p] - %p\n", program_invocation_short_name , __builtin_return_address(0) , ptr ); __real_free(ptr); }
void __wrap_free(void *addr) { if (EarlyMallocEnabled) { early_free(addr); } enter_kernel(); __real_free(addr); leave_kernel(); }
void __wrap_free( void *ptr ) { LockAlloc(); __real_free( ptr ); UnlockAlloc(); }
void operator delete[](void* ptr) throw() { printf("@ %s:[%p] - %p\n", program_invocation_short_name , __builtin_return_address(0) , ptr ); __real_free(ptr); }
void __wrap_free(void *p) { if(!p) return; if(((u32)p & 0x10000000) != 0) g_mem2gp.release(p); else __real_free(p); }
extern "C" void wrap(free)(void *p) { init_lib(); void* p1 = STUB_PTR(p); if (p1) fibjs::MemPool::global().remove(p1); __real_free(p1); }
void __wrap_free(void *p) { if(!p) return; if(((u32)p < (u32)&__init_start - 0x100 && (u32)p >= (u32)0x80004000) || ((u32)p > (u32)APPLOADER_START && (u32)p < (u32)APPLOADER_END)) MEM1_free(p); else if((u32)p & 0x10000000) MEM2_free(p); else __real_free(p); }
/* * Expires an object descriptor and decrements the object's descriptor counter. * If the descriptor counter is 0, the object to which the descriptor points * is deallocated. Returns 0 iff no more expired object descriptors exist. */ int expire_object_descriptor_if_exists(expired_descriptor_page_list_t *list) { // check pre-conditions #ifdef SCM_CHECK_CONDITIONS if (list == NULL) { printf("Expired descriptor page list is NULL but was expected to exist.\n"); return 0; } #endif object_header_t *expired_object = (object_header_t*) get_expired_memory(list); if (expired_object != NULL) { //decrement the descriptor counter of the expired object if (atomic_int_dec_and_test((int*) &expired_object->dc_or_region_id)) { //with the descriptor counter now zero run finalizer and free it int finalizer_result = run_finalizer(expired_object); if (finalizer_result != 0) { #ifdef SCM_DEBUG printf("WARNING: finalizer returned %d.\n", finalizer_result); printf("WARNING: %lx is a leak.\n", (unsigned long) PAYLOAD_OFFSET(expired_object)); #endif return 1; //do not free the object } #ifdef SCM_DEBUG printf("Object FREE(%lx).\n", (unsigned long) PAYLOAD_OFFSET(expired_object)); #endif #ifdef SCM_RECORD_MEMORY_USAGE dec_overhead(sizeof(object_header_t)); inc_freed_mem(__real_malloc_usable_size(expired_object)); #endif __real_free(expired_object); return 1; } else { #ifdef SCM_DEBUG printf("Decrementing DC==%d.\n", expired_object->dc_or_region_id); #endif return 1; } } else { #ifdef SCM_DEBUG printf("No expired object found.\n"); #endif return 0; } }
inline void out_proc(FILE* fp, void * proc) { Dl_info info; char* demangled = NULL; if (proc == 0) fprintf(fp, "null\n"); else if (!dladdr(proc, &info) || !info.dli_sname) fprintf(fp, "%p\n", proc); else if ((demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, 0))) { fprintf(fp, "%s + %ld\n", demangled, (intptr_t)proc - (intptr_t)info.dli_saddr); __real_free(demangled); } else fprintf(fp, "%s + %ld\n", info.dli_sname, (intptr_t)proc - (intptr_t)info.dli_saddr); }
void __wrap_free(void* ptr) { if (ptr == nullptr) { #ifdef DEBUG_MALLOC printf("MALLOC: %p free\n", ptr); #endif return; } void* p = (char*)ptr-16; size_t s = *(size_t*)p; mem_usage -= s+16; allocs--; #ifdef DEBUG_MALLOC printf("MALLOC: %p : %lld free\n", (char*)p+16, s); #endif __real_free(p); }
extern "C" void* wrap(realloc)(void* p, size_t sz) { init_lib(); fibjs::MemPool& mp = fibjs::MemPool::global(); if (p == 0) { void* p1 = __real_malloc(FULL_SIZE(sz)); if (p1) { memset(p1, 0, STUB_SIZE); mp.add(p1, sz); } return MEM_PTR(p1); } if (sz == 0) { void* p1 = STUB_PTR(p); if (p1) mp.remove(p1); __real_free(p1); return 0; } void* p1 = STUB_PTR(p); mp.remove(p1); void* p2 = __real_realloc(p1, FULL_SIZE(sz)); if (p2) { memset(p2, 0, STUB_SIZE); mp.add(p2, sz); } else mp.add(p1); return MEM_PTR(p2); }
static inline void recycle_descriptor_page(descriptor_page_t *page) { if (descriptor_root->number_of_pooled_descriptor_pages < SCM_DESCRIPTOR_PAGE_FREELIST_SIZE) { descriptor_root->descriptor_page_pool[descriptor_root->number_of_pooled_descriptor_pages] = page; descriptor_root->number_of_pooled_descriptor_pages++; #ifdef SCM_RECORD_MEMORY_USAGE inc_pooled_mem(sizeof(descriptor_page_t)); #endif } else { #ifdef SCM_RECORD_MEMORY_USAGE dec_overhead(__real_malloc_usable_size(page)); inc_freed_mem(__real_malloc_usable_size(page)); #endif __real_free(page); } }
extern "C" NS_EXPORT jlong JNICALL Java_org_mozilla_goanna_sqlite_SQLiteBridge_openDatabase(JNIEnv* jenv, jclass, jstring jDb) { JNI_Setup(jenv); int rc; const char* dbPath; sqlite3 *db; char* errorMsg; dbPath = jenv->GetStringUTFChars(jDb, NULL); rc = f_sqlite3_open(dbPath, &db); jenv->ReleaseStringUTFChars(jDb, dbPath); if (rc != SQLITE_OK) { asprintf(&errorMsg, "Can't open database: %s\n", f_sqlite3_errmsg(db)); LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/goanna/sqlite/SQLiteBridgeException", errorMsg); // errorMsg is allocated by asprintf, it needs to be freed by libc. __real_free(errorMsg); } return (jlong)db; }
void dump() { Item* items; Item* p; int32_t n = 0; int32_t i; char fname[32]; init_lib(); m_lock.lock(); items = (Item*)__real_malloc(sizeof(Item) * m_list.count()); p = m_list.head(); while (p) { memcpy(items + n ++, p, sizeof(Item)); p = m_list.next(p); } m_lock.unlock(); caller root(0); for (i = 0; i < n; i ++) root.put(items[i].m_sz, items[i].m_frames, items[i].m_frame_count); sprintf(fname, "fibjs.%d.heap", getpid()); FILE* fp = fopen(fname, "w"); if (fp) { fprintf(fp, "\nfound %d times, total ", root.m_times); out_size(fp, root.m_sz); root.dumpSubs(fp); fclose(fp); } __real_free(items); }
static jobject sqliteInternalCall(JNIEnv* jenv, sqlite3 *db, jstring jQuery, jobjectArray jParams, jlongArray jQueryRes) { JNI_Setup(jenv); jobject jCursor = NULL; char* errorMsg; jsize numPars = 0; const char *pzTail; sqlite3_stmt *ppStmt; int rc; const char* queryStr; queryStr = jenv->GetStringUTFChars(jQuery, NULL); rc = f_sqlite3_prepare_v2(db, queryStr, -1, &ppStmt, &pzTail); if (rc != SQLITE_OK || ppStmt == NULL) { asprintf(&errorMsg, "Can't prepare statement: %s\n", f_sqlite3_errmsg(db)); goto error_close; } jenv->ReleaseStringUTFChars(jQuery, queryStr); // Check if number of parameters matches if (jParams != NULL) { numPars = jenv->GetArrayLength(jParams); } int sqlNumPars; sqlNumPars = f_sqlite3_bind_parameter_count(ppStmt); if (numPars != sqlNumPars) { asprintf(&errorMsg, "Passed parameter count (%d) doesn't match SQL parameter count (%d)\n", numPars, sqlNumPars); goto error_close; } if (jParams != NULL) { // Bind parameters, if any if (numPars > 0) { for (int i = 0; i < numPars; i++) { jobject jObjectParam = jenv->GetObjectArrayElement(jParams, i); // IsInstanceOf or isAssignableFrom? String is final, so IsInstanceOf // should be OK. jboolean isString = jenv->IsInstanceOf(jObjectParam, stringClass); if (isString != JNI_TRUE) { asprintf(&errorMsg, "Parameter is not of String type"); goto error_close; } jstring jStringParam = (jstring)jObjectParam; const char* paramStr = jenv->GetStringUTFChars(jStringParam, NULL); // SQLite parameters index from 1. rc = f_sqlite3_bind_text(ppStmt, i + 1, paramStr, -1, SQLITE_TRANSIENT); jenv->ReleaseStringUTFChars(jStringParam, paramStr); if (rc != SQLITE_OK) { asprintf(&errorMsg, "Error binding query parameter"); goto error_close; } } } } // Execute the query and step through the results rc = f_sqlite3_step(ppStmt); if (rc != SQLITE_ROW && rc != SQLITE_DONE) { asprintf(&errorMsg, "Can't step statement: (%d) %s\n", rc, f_sqlite3_errmsg(db)); goto error_close; } // Get the column count and names int cols; cols = f_sqlite3_column_count(ppStmt); { // Allocate a String[cols] jobjectArray jStringArray = jenv->NewObjectArray(cols, stringClass, NULL); if (jStringArray == NULL) { asprintf(&errorMsg, "Can't allocate String[]\n"); goto error_close; } // Assign column names to the String[] for (int i = 0; i < cols; i++) { const char* colName = f_sqlite3_column_name(ppStmt, i); jstring jStr = jenv->NewStringUTF(colName); jenv->SetObjectArrayElement(jStringArray, i, jStr); } // Construct the MatrixCursor(String[]) with given column names jCursor = jenv->NewObject(cursorClass, jCursorConstructor, jStringArray); if (jCursor == NULL) { asprintf(&errorMsg, "Can't allocate MatrixBlobCursor\n"); goto error_close; } } // Return the id and number of changed rows in jQueryRes { jlong id = f_sqlite3_last_insert_rowid(db); jenv->SetLongArrayRegion(jQueryRes, 0, 1, &id); jlong changed = f_sqlite3_changes(db); jenv->SetLongArrayRegion(jQueryRes, 1, 1, &changed); } // For each row, add an Object[] to the passed ArrayList, // with that containing either String or ByteArray objects // containing the columns while (rc != SQLITE_DONE) { // Process row // Construct Object[] jobjectArray jRow = jenv->NewObjectArray(cols, objectClass, NULL); if (jRow == NULL) { asprintf(&errorMsg, "Can't allocate jRow Object[]\n"); goto error_close; } for (int i = 0; i < cols; i++) { int colType = f_sqlite3_column_type(ppStmt, i); if (colType == SQLITE_BLOB) { // Treat as blob const void* blob = f_sqlite3_column_blob(ppStmt, i); int colLen = f_sqlite3_column_bytes(ppStmt, i); // Construct ByteBuffer of correct size jobject jByteBuffer = jenv->CallStaticObjectMethod(byteBufferClass, jByteBufferAllocateDirect, colLen); if (jByteBuffer == NULL) { goto error_close; } // Get its backing array void* bufferArray = jenv->GetDirectBufferAddress(jByteBuffer); if (bufferArray == NULL) { asprintf(&errorMsg, "Failure calling GetDirectBufferAddress\n"); goto error_close; } memcpy(bufferArray, blob, colLen); jenv->SetObjectArrayElement(jRow, i, jByteBuffer); jenv->DeleteLocalRef(jByteBuffer); } else if (colType == SQLITE_NULL) { jenv->SetObjectArrayElement(jRow, i, NULL); } else { // Treat everything else as text const char* txt = (const char*)f_sqlite3_column_text(ppStmt, i); jstring jStr = jenv->NewStringUTF(txt); jenv->SetObjectArrayElement(jRow, i, jStr); jenv->DeleteLocalRef(jStr); } } // Append Object[] to Cursor jenv->CallVoidMethod(jCursor, jCursorAddRow, jRow); // Clean up jenv->DeleteLocalRef(jRow); // Get next row rc = f_sqlite3_step(ppStmt); // Real error? if (rc != SQLITE_ROW && rc != SQLITE_DONE) { asprintf(&errorMsg, "Can't re-step statement:(%d) %s\n", rc, f_sqlite3_errmsg(db)); goto error_close; } } rc = f_sqlite3_finalize(ppStmt); if (rc != SQLITE_OK) { asprintf(&errorMsg, "Can't finalize statement: %s\n", f_sqlite3_errmsg(db)); goto error_close; } return jCursor; error_close: LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/goanna/sqlite/SQLiteBridgeException", errorMsg); // errorMsg is allocated by asprintf, it needs to be freed by libc. __real_free(errorMsg); return jCursor; }
/* This function wraps the real free */ void * __wrap_free (void *data) { void *lptr = __real_free(data); printf("free: %p\n", data); return lptr; }
void MEM1_free(void *p) { __real_free(p); }
void __wrap_free(void *ptr) { assert_nrt(); __real_free(ptr); }
extern "C" void __wrap_free(void* ptr) { if (!isChunkInUse(ptr)) __debugbreak(); __real_free(ptr); }
extern "C" void __wrap_free(void* ptr) { breakOnHeapOpFromInterruptHandler(); __real_free(ptr); }
/** * Recycles a region in O(1) by pooling * the list of free region_pages except the * first region page iff the region_page_pool * limit is not exceeded, otherwise the region_pages * except the first one are deallocated and * the memory is handed back to the OS in O(n), * n = amount of region pages - 1. * * The remaining first region page indicates that the region * once existed, which is necessary to differentiate * it from regions which have not yet been used. * This indicates how many not-yet-used regions * are available. * * If the region was unregistered, all region pages * are recycled or deallocated. * * Returns if no or just one region_page * has been allocated in the region. */ static void recycle_region(region_t* region) { #ifdef SCM_DEBUG printf("Recycle region: %p.\n", region); #endif // check pre-conditions #ifdef SCM_CHECK_CONDITIONS if (region == NULL) { printf("Region recycling failed: NULL region should not appear in the descriptor buffers.\n"); exit(-1); } else if (region->firstPage == NULL || region->lastPage == NULL) { printf("Region recycling failed: Descriptor points to a region which was not correctly initialized.\n"); exit(-1); } if (region->dc != 0) { printf("Region recycling failed: Region seems to be still alive.\n"); exit(-1); } region_t* invar_region = region; #endif region_page_t* legacy_pages; unsigned long number_of_recycle_region_pages; // if the region has been used in the current thread... if (region->age == descriptor_root->current_time) { //.. recycle everything except the first page region_page_t* firstPage = region->firstPage; legacy_pages = firstPage->nextPage; memset(firstPage, '\0', SCM_REGION_PAGE_SIZE); region->last_address_in_last_page = firstPage->memory + SCM_REGION_PAGE_PAYLOAD_SIZE; // nothing to put into the pool if (legacy_pages == NULL) { // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 1) { printf("Region recycling failed: Number of region pages is %u but only one region page exists.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page exists.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } if(region->firstPage->nextPage != NULL) { printf("Region recycling failed: Next page pointer is corrupt: %p.\n", region->firstPage->nextPage); exit(-1); } } #endif region->dc = 0; return; } // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages <= 1) { printf("Region recycling failed: Number of region pages is %u but more than 1 region pages were expected.\n", region->number_of_region_pages); exit(-1); } #endif number_of_recycle_region_pages = region->number_of_region_pages - 1; } // if the region was a zombie in the current thread... else { #ifdef SCM_DEBUG printf("Region expired.\n"); #endif //.. recycle everything, also the first page legacy_pages = region->firstPage; // nothing to put into the pool if (legacy_pages == NULL) { // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 0) { printf("Region recycling failed: Number of region pages is not zero but no region pages exist.\n"); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page exists.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif region->dc = 0; return; } // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages == 0) { printf("Region recycling failed: Number of region pages is %u but legacy pages could be obtained.\n", region->number_of_region_pages); exit(-1); } #endif // a zombie region recycles all region pages number_of_recycle_region_pages = region->number_of_region_pages; } unsigned long number_of_pooled_region_pages = descriptor_root->number_of_pooled_region_pages; // is there space in the region page pool? if ((number_of_pooled_region_pages + number_of_recycle_region_pages) <= SCM_REGION_PAGE_FREELIST_SIZE) { //..yes, there is space in the region page pool #ifdef SCM_RECORD_MEMORY_USAGE region_page_t* p = legacy_pages; while(p != NULL) { inc_pooled_mem(SCM_REGION_PAGE_SIZE); inc_overhead(__real_malloc_usable_size(p)); p = p->nextPage; } #endif region_page_t* first_in_pool = descriptor_root->region_page_pool; region_page_t* last_page = region->lastPage; last_page->nextPage = first_in_pool; descriptor_root->region_page_pool = legacy_pages; descriptor_root->number_of_pooled_region_pages = number_of_pooled_region_pages + number_of_recycle_region_pages; } else { //..no, there is no space in the region page pool // If the first region page is not NULL, // deallocate all region pages region_page_t* page2free = legacy_pages; while (page2free != NULL && (number_of_pooled_region_pages + number_of_recycle_region_pages) > SCM_REGION_PAGE_FREELIST_SIZE) { region_page_t* next = page2free->nextPage; __real_free(page2free); #ifdef SCM_RECORD_MEMORY_USAGE inc_freed_mem(SCM_REGION_PAGE_SIZE); #endif page2free = next; number_of_recycle_region_pages--; } // check again if we can recycle now if (page2free != NULL && (number_of_pooled_region_pages + number_of_recycle_region_pages) <= SCM_REGION_PAGE_FREELIST_SIZE) { region_page_t* first_in_pool = descriptor_root->region_page_pool; region_page_t* last_page = region->lastPage; if(last_page != NULL) { last_page->nextPage = first_in_pool; descriptor_root->region_page_pool = page2free; descriptor_root->number_of_pooled_region_pages = number_of_recycle_region_pages - 1; #ifdef SCM_RECORD_MEMORY_USAGE inc_pooled_mem(number_of_recycle_region_pages * SCM_REGION_PAGE_SIZE); #endif } } descriptor_root->number_of_pooled_region_pages = number_of_pooled_region_pages + number_of_recycle_region_pages; } region->number_of_region_pages = 1; region->lastPage = region->firstPage; region->last_address_in_last_page = region->lastPage->memory + SCM_REGION_PAGE_PAYLOAD_SIZE; region->next_free_address = region->lastPage->memory; // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 1) { printf("Region recycling failed: Number of region pages is %u but only one region page exists.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page should exist.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif if (region->age != descriptor_root->current_time) { region->number_of_region_pages = 0; region->lastPage = region->firstPage = NULL; // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 0) { printf("Region recycling failed: Number of region pages is %u but no region pages should exist.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != NULL) { printf("Region recycling failed: First page is not null as expected.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif } }