Changeset 53278 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Nov 9, 2014 9:01:25 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 96850
- Location:
- trunk/src/VBox/Runtime/r3
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/alloc-ef.cpp
r52333 r53278 45 45 #include <iprt/string.h> 46 46 47 #ifdef RTALLOC_REPLACE_MALLOC 48 # include <VBox/dis.h> 49 # include <VBox/disopcode.h> 50 # include <dlfcn.h> 51 # ifdef RT_OS_DARWIN 52 # include <malloc/malloc.h> 53 # endif 54 #endif 55 56 57 /******************************************************************************* 58 * Defined Constants And Macros * 59 *******************************************************************************/ 60 #ifdef RTALLOC_REPLACE_MALLOC 61 # define RTMEM_REPLACMENT_ALIGN(a_cb) ((a_cb) >= 16 ? RT_ALIGN_Z(a_cb, 16) \ 62 : (a_cb) >= sizeof(uintptr_t) ? RT_ALIGN_Z(a_cb, sizeof(uintptr_t)) : (a_cb)) 63 #endif 64 47 65 48 66 /******************************************************************************* … … 62 80 static volatile size_t g_cbBlocksDelay; 63 81 # endif /* RTALLOC_EFENCE_FREE_DELAYED */ 82 # ifdef RTALLOC_REPLACE_MALLOC 83 /** @name For calling the real allocation API we've replaced. 84 * @{ */ 85 void * (*g_pfnOrgMalloc)(size_t); 86 void * (*g_pfnOrgCalloc)(size_t, size_t); 87 void * (*g_pfnOrgRealloc)(void *, size_t); 88 void (*g_pfnOrgFree)(void *); 89 size_t (*g_pfnOrgMallocSize)(void *); 90 /** @} */ 91 # endif 64 92 #endif /* RTALLOC_EFENCE_TRACE */ 65 93 /** Array of pointers free watches for. */ … … 72 100 * Internal Functions * 73 101 *******************************************************************************/ 102 #ifdef RTALLOC_REPLACE_MALLOC 103 static void rtMemReplaceMallocAndFriends(void); 104 #endif 105 106 74 107 /** 75 108 * Complains about something. … … 131 164 const char *pszTag, void *pvCaller, RT_SRC_POS_DECL) 132 165 { 166 # ifdef RTALLOC_REPLACE_MALLOC 167 if (!g_pfnOrgMalloc) 168 rtMemReplaceMallocAndFriends(); 169 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)g_pfnOrgMalloc(sizeof(*pBlock)); 170 # else 133 171 PRTMEMBLOCK pBlock = (PRTMEMBLOCK)malloc(sizeof(*pBlock)); 172 # endif 134 173 if (pBlock) 135 174 { … … 152 191 DECLINLINE(void) rtmemBlockFree(PRTMEMBLOCK pBlock) 153 192 { 193 # ifdef RTALLOC_REPLACE_MALLOC 194 g_pfnOrgFree(pBlock); 195 # else 154 196 free(pBlock); 197 # endif 155 198 } 156 199 … … 270 313 271 314 #endif /* RTALLOC_EFENCE_TRACE */ 315 316 317 #if defined(RTALLOC_REPLACE_MALLOC) && defined(RTALLOC_EFENCE_TRACE) 318 /* 319 * 320 * Replacing malloc, calloc, realloc, & free. 321 * 322 */ 323 324 /** Replacement for malloc. */ 325 static void *rtMemReplacementMalloc(size_t cb) 326 { 327 size_t cbAligned = RTMEM_REPLACMENT_ALIGN(cb); 328 void *pv = rtR3MemAlloc("r-malloc", RTMEMTYPE_RTMEMALLOC, cb, cbAligned, "heap", ASMReturnAddress(), RT_SRC_POS); 329 if (!pv) 330 pv = g_pfnOrgMalloc(cb); 331 return pv; 332 } 333 334 /** Replacement for calloc. */ 335 static void *rtMemReplacementCalloc(size_t cbItem, size_t cItems) 336 { 337 size_t cb = cbItem * cItems; 338 size_t cbAligned = RTMEM_REPLACMENT_ALIGN(cb); 339 void *pv = rtR3MemAlloc("r-calloc", RTMEMTYPE_RTMEMALLOCZ, cb, cbAligned, "heap", ASMReturnAddress(), RT_SRC_POS); 340 if (!pv) 341 pv = g_pfnOrgCalloc(cbItem, cItems); 342 return pv; 343 } 344 345 /** Replacement for realloc. */ 346 static void *rtMemReplacementRealloc(void *pvOld, size_t cbNew) 347 { 348 if (pvOld) 349 { 350 /* We're not strict about where the memory was allocated. */ 351 PRTMEMBLOCK pBlock = rtmemBlockGet(pvOld); 352 if (pBlock) 353 { 354 size_t cbAligned = RTMEM_REPLACMENT_ALIGN(cbNew); 355 return rtR3MemRealloc("r-realloc", RTMEMTYPE_RTMEMREALLOC, pvOld, cbAligned, "heap", ASMReturnAddress(), RT_SRC_POS); 356 } 357 return g_pfnOrgRealloc(pvOld, cbNew); 358 } 359 return rtMemReplacementMalloc(cbNew); 360 } 361 362 /** Replacement for free(). */ 363 static void rtMemReplacementFree(void *pv) 364 { 365 if (pv) 366 { 367 /* We're not strict about where the memory was allocated. */ 368 PRTMEMBLOCK pBlock = rtmemBlockGet(pv); 369 if (pBlock) 370 rtR3MemFree("r-free", RTMEMTYPE_RTMEMFREE, pv, ASMReturnAddress(), RT_SRC_POS); 371 else 372 g_pfnOrgFree(pv); 373 } 374 } 375 376 # ifdef RT_OS_DARWIN 377 /** Replacement for malloc. */ 378 static size_t rtMemReplacementMallocSize(void *pv) 379 { 380 size_t cb; 381 if (pv) 382 { 383 /* We're not strict about where the memory was allocated. */ 384 PRTMEMBLOCK pBlock = rtmemBlockGet(pv); 385 if (pBlock) 386 cb = pBlock->cbUnaligned; 387 else 388 cb = g_pfnOrgMallocSize(pv); 389 } 390 else 391 cb = 0; 392 return cb; 393 } 394 # endif 395 396 397 static void rtMemReplaceMallocAndFriends(void) 398 { 399 struct 400 { 401 const char *pszName; 402 PFNRT pfnReplacement; 403 PFNRT pfnOrg; 404 PFNRT *ppfnJumpBack; 405 } aApis[] = 406 { 407 { "free", (PFNRT)rtMemReplacementFree, (PFNRT)free, (PFNRT *)&g_pfnOrgFree }, 408 { "realloc", (PFNRT)rtMemReplacementRealloc, (PFNRT)realloc, (PFNRT *)&g_pfnOrgRealloc }, 409 { "calloc", (PFNRT)rtMemReplacementCalloc, (PFNRT)calloc, (PFNRT *)&g_pfnOrgCalloc }, 410 { "malloc", (PFNRT)rtMemReplacementMalloc, (PFNRT)malloc, (PFNRT *)&g_pfnOrgMalloc }, 411 #ifdef RT_OS_DARWIN 412 { "malloc_size", (PFNRT)rtMemReplacementMallocSize, (PFNRT)malloc_size, (PFNRT *)&g_pfnOrgMallocSize }, 413 #endif 414 }; 415 416 /* 417 * Initialize the jump backs to avoid recursivly entering this function. 418 */ 419 for (unsigned i = 0; i < RT_ELEMENTS(aApis); i++) 420 *aApis[i].ppfnJumpBack = aApis[i].pfnOrg; 421 422 /* 423 * Give the user an option to skip replacing malloc. 424 */ 425 if (getenv("IPRT_DONT_REPLACE_MALLOC")) 426 return; 427 428 /* 429 * Allocate a page for jump back code (we leak it). 430 */ 431 uint8_t *pbExecPage = (uint8_t *)RTMemPageAlloc(PAGE_SIZE); AssertFatal(pbExecPage); 432 int rc = RTMemProtect(pbExecPage, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC); AssertFatalRC(rc); 433 434 /* 435 * Do the ground work. 436 */ 437 uint8_t *pb = pbExecPage; 438 for (unsigned i = 0; i < RT_ELEMENTS(aApis); i++) 439 { 440 /* Resolve it. */ 441 PFNRT pfnOrg = (PFNRT)(uintptr_t)dlsym(RTLD_DEFAULT, aApis[i].pszName); 442 if (pfnOrg) 443 aApis[i].pfnOrg = pfnOrg; 444 else 445 pfnOrg = aApis[i].pfnOrg; 446 447 /* Figure what we can replace and how much to duplicate in the jump back code. */ 448 # ifdef RT_ARCH_AMD64 449 uint32_t cbNeeded = 12; 450 DISCPUMODE const enmCpuMode = DISCPUMODE_64BIT; 451 # elif defined(RT_ARCH_X86) 452 uint32_t const cbNeeded = 5; 453 DISCPUMODE const enmCpuMode = DISCPUMODE_32BIT; 454 # else 455 # error "Port me" 456 # endif 457 uint32_t offJmpBack = 0; 458 uint32_t cbCopy = 0; 459 while (offJmpBack < cbNeeded) 460 { 461 DISCPUSTATE Dis; 462 uint32_t cbInstr = 1; 463 rc = DISInstr((void *)((uintptr_t)pfnOrg + offJmpBack), enmCpuMode, &Dis, &cbInstr); AssertFatalRC(rc); 464 AssertFatal(!(Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW))); 465 # ifdef RT_ARCH_AMD64 466 # ifdef RT_OS_DARWIN 467 /* Kludge for: cmp [malloc_def_zone_state], 1; jg 2; call _malloc_initialize; 2: */ 468 DISQPVPARAMVAL Parm; 469 if ( Dis.ModRM.Bits.Mod == 0 470 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */ 471 && (Dis.Param2.fUse & (DISUSE_IMMEDIATE16_SX8 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE64_SX8)) 472 && Dis.Param2.uValue == 1 473 && Dis.pCurInstr->uOpcode == OP_CMP) 474 { 475 cbCopy = offJmpBack; 476 477 offJmpBack += cbInstr; 478 rc = DISInstr((void *)((uintptr_t)pfnOrg + offJmpBack), enmCpuMode, &Dis, &cbInstr); AssertFatalRC(rc); 479 if ( Dis.pCurInstr->uOpcode == OP_JNBE 480 && Dis.Param1.uDisp.i8 == 5) 481 { 482 offJmpBack += cbInstr + 5; 483 AssertFatal(offJmpBack >= cbNeeded); 484 break; 485 } 486 } 487 # endif 488 AssertFatal(!(Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */)); 489 # endif 490 offJmpBack += cbInstr; 491 } 492 if (!cbCopy) 493 cbCopy = offJmpBack; 494 495 /* Assemble the jump back. */ 496 memcpy(pb, (void *)(uintptr_t)pfnOrg, cbCopy); 497 uint32_t off = cbCopy; 498 # ifdef RT_ARCH_AMD64 499 pb[off++] = 0xff; /* jmp qword [$+8 wrt RIP] */ 500 pb[off++] = 0x25; 501 *(uint32_t *)&pb[off] = 0; 502 off += 4; 503 *(uint64_t *)&pb[off] = (uintptr_t)pfnOrg + offJmpBack; 504 off += 8; 505 off = RT_ALIGN_32(off, 16); 506 # elif defined(RT_ARCH_X86) 507 pb[off++] = 0xe9; /* jmp rel32 */ 508 *(uint32_t *)&pb[off] = (uintptr_t)pfnOrg + offJmpBack - (uintptr_t)&pb[4]; 509 off += 4; 510 off = RT_ALIGN_32(off, 8); 511 # else 512 # error "Port me" 513 # endif 514 *aApis[i].ppfnJumpBack = (PFNRT)(uintptr_t)pb; 515 pb += off; 516 } 517 518 /* 519 * Modify the APIs. 520 */ 521 for (unsigned i = 0; i < RT_ELEMENTS(aApis); i++) 522 { 523 pb = (uint8_t *)(uintptr_t)aApis[i].pfnOrg; 524 rc = RTMemProtect(pb, 16, RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC); AssertFatalRC(rc); 525 526 # ifdef RT_ARCH_AMD64 527 /* Assemble the LdrLoadDll patch. */ 528 *pb++ = 0x48; /* mov rax, qword */ 529 *pb++ = 0xb8; 530 *(uint64_t *)pb = (uintptr_t)aApis[i].pfnReplacement; 531 pb += 8; 532 *pb++ = 0xff; /* jmp rax */ 533 *pb++ = 0xe0; 534 # elif defined(RT_ARCH_X86) 535 *pb++ = 0xe9; /* jmp rel32 */ 536 *(uint32_t *)pb = (uintptr_t)aApis[i].pfnReplacement - (uintptr_t)&pb[4]; 537 # else 538 # error "Port me" 539 # endif 540 } 541 } 542 543 #endif /* RTALLOC_REPLACE_MALLOC && RTALLOC_EFENCE_TRACE */ 272 544 273 545 -
trunk/src/VBox/Runtime/r3/alloc-ef.h
r34291 r53278 119 119 #endif 120 120 121 #if defined(RUNNING_DOXYGEN) 122 /** @def RTALLOC_REPLACE_MALLOC 123 * Replaces the malloc, calloc, realloc, free and friends in libc (experimental). 124 * Set in LocalConfig.kmk. Requires RTALLOC_EFENCE_TRACE to work. */ 125 # define RTALLOC_REPLACE_MALLOC 126 #endif 127 #if defined(RTALLOC_REPLACE_MALLOC) && !defined(RTALLOC_EFENCE_TRACE) 128 # error "RTALLOC_REPLACE_MALLOC requires RTALLOC_EFENCE_TRACE." 129 #endif 121 130 122 131 … … 192 201 RT_C_DECLS_END 193 202 194 #endif 195 203 204 /******************************************************************************* 205 * Global Variables * 206 *******************************************************************************/ 207 #ifdef RTALLOC_REPLACE_MALLOC 208 RT_C_DECLS_BEGIN 209 extern void * (*g_pfnOrgMalloc)(size_t); 210 extern void * (*g_pfnOrgCalloc)(size_t, size_t); 211 extern void * (*g_pfnOrgRealloc)(void *, size_t); 212 extern void (*g_pfnOrgFree)(void *); 213 RT_C_DECLS_END 214 #endif 215 216 #endif 217 -
trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp
r48935 r53278 41 41 #include <iprt/string.h> 42 42 #include "internal/mem.h" 43 #include "../alloc-ef.h" 43 44 44 45 #include <stdlib.h> … … 412 413 } 413 414 /** @todo Eliminate this rtMemBaseAlloc dependency! */ 414 PRTHEAPPAGEBLOCK pBlock = (PRTHEAPPAGEBLOCK)rtMemBaseAlloc(sizeof(*pBlock)); 415 PRTHEAPPAGEBLOCK pBlock; 416 #ifdef RTALLOC_REPLACE_MALLOC 417 if (g_pfnOrgMalloc) 418 pBlock = (PRTHEAPPAGEBLOCK)g_pfnOrgMalloc(sizeof(*pBlock)); 419 else 420 #endif 421 pBlock = (PRTHEAPPAGEBLOCK)rtMemBaseAlloc(sizeof(*pBlock)); 415 422 if (!pBlock) 416 423 { … … 583 590 pBlock->Core.Key = pBlock->Core.KeyLast = NULL; 584 591 pBlock->cFreePages = 0; 585 rtMemBaseFree(pBlock); 592 #ifdef RTALLOC_REPLACE_MALLOC 593 if (g_pfnOrgFree) 594 g_pfnOrgFree(pBlock); 595 else 596 #endif 597 rtMemBaseFree(pBlock); 586 598 587 599 RTCritSectEnter(&pHeap->CritSect);
Note:
See TracChangeset
for help on using the changeset viewer.