Changeset 19757 in vbox
- Timestamp:
- May 15, 2009 11:37:31 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 47378
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/dbgf.h
r19639 r19757 38 38 39 39 #include <iprt/stdarg.h> 40 #include <iprt/dbg.h> 40 41 41 42 __BEGIN_DECLS … … 586 587 typedef const DBGFLINE *PCDBGFLINE; 587 588 589 /** @name Address spaces aliases. 590 * @{ */ 591 /** The guest global address space. */ 592 #define DBGF_AS_GLOBAL ((RTDBGAS)-1) 593 /** The guest kernel address space. 594 * This is usually resolves to the same as DBGF_AS_GLOBAL. */ 595 #define DBGF_AS_KERNEL ((RTDBGAS)-2) 596 /** The physical address space. */ 597 #define DBGF_AS_PHYS ((RTDBGAS)-3) 598 /** Raw-mode context. */ 599 #define DBGF_AS_RC ((RTDBGAS)-4) 600 /** Ring-0 context. */ 601 #define DBGF_AS_R0 ((RTDBGAS)-5) 602 /** Raw-mode context and then global guest context. 603 * When used for looking up information, it works as if the call was first made 604 * with DBGF_AS_RC and then on failure with DBGF_AS_GLOBAL. When called for 605 * making address space changes, it works as if DBGF_AS_RC was used. */ 606 #define DBGF_AS_RC_AND_GC_GLOBAL ((RTDBGAS)-6) 607 608 /** The first special one. */ 609 #define DBGF_AS_FIRST DBGF_AS_RC_AND_GC_GLOBAL 610 /** The last special one. */ 611 #define DBGF_AS_LAST DBGF_AS_GLOBAL 612 /** The number of special address space handles. */ 613 #define DBGF_AS_COUNT ((uintptr_t)DBGF_AS_LAST - (uintptr_t)DBGF_AS_FIRST + 1U) 614 /** Converts an alias handle to an array index. */ 615 #define DBGF_AS_ALIAS_2_INDEX(hAlias) \ 616 ( (uintptr_t)(hAlias) - (uintptr_t)DBGF_AS_FIRST ) 617 /** Predicat macro that check if the specified handle is an alias. */ 618 #define DBGF_AS_IS_ALIAS(hAlias) \ 619 ( DBGF_AS_ALIAS_2_INDEX(hAlias) < DBGF_AS_COUNT ) 620 /** Predicat macro that check if the specified alias is a fixed one or not. */ 621 #define DBGF_AS_IS_FIXED_ALIAS(hAlias) \ 622 ( DBGF_AS_ALIAS_2_INDEX(hAlias) < (uintptr_t)DBGF_AS_PHYS - (uintptr_t)DBGF_AS_FIRST + 1U ) 623 624 /** @} */ 625 626 VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId); 627 VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs); 628 VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor); 629 VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias); 630 VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias); 631 VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName); 632 VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId); 633 634 VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); 635 VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags); 636 VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); 637 638 /* The following are soon to be obsoleted: */ 588 639 VMMR3DECL(int) DBGFR3ModuleLoad(PVM pVM, const char *pszFilename, RTGCUINTPTR AddressDelta, const char *pszName, RTGCUINTPTR ModuleAddress, unsigned cbImage); 589 640 VMMR3DECL(void) DBGFR3ModuleRelocate(PVM pVM, RTGCUINTPTR OldImageBase, RTGCUINTPTR NewImageBase, RTGCUINTPTR cbImage, -
trunk/include/VBox/mm.h
r19682 r19757 66 66 67 67 MM_TAG_DBGF, 68 MM_TAG_DBGF_AS, 68 69 MM_TAG_DBGF_INFO, 69 70 MM_TAG_DBGF_LINE, -
trunk/include/iprt/dbg.h
r19561 r19757 42 42 /** NIL debug segment index. */ 43 43 #define NIL_RTDBGSEGIDX UINT32_C(0xffffffff) 44 /** The last normal segment index. */ 45 #define RTDBGSEGIDX_LAST UINT32_C(0xffffffef) 44 46 /** Special segment index that indicates that the offset is a relative 45 47 * virtual address (RVA). I.e. an offset from the start of the module. */ … … 144 146 145 147 /** 146 * Destroys the address space. 147 * 148 * This means unlinking all the modules it currently contains, potentially 148 * Retains a reference to the address space. 149 * 150 * @returns New reference count, UINT32_MAX on invalid handle (asserted). 151 * 152 * @param hDbgAs The address space handle. 153 * 154 * @remarks Will not take any locks. 155 */ 156 RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs); 157 158 /** 159 * Release a reference to the address space. 160 * 161 * When the reference count reaches zero, the address space is destroyed. 162 * That means unlinking all the modules it currently contains, potentially 149 163 * causing some or all of them to be destroyed as they are managed by 150 164 * reference counting. 151 165 * 152 * @returns IPRT status code. 153 * 154 * @param hDbgAs The address space handle. A NIL handle will 155 * be quietly ignored. 156 */ 157 RTDECL(int) RTDbgAsDestroy(RTDBGAS hDbgAs); 166 * @returns New reference count, UINT32_MAX on invalid handle (asserted). 167 * 168 * @param hDbgAs The address space handle. The NIL handle is quietly 169 * ignored and 0 is returned. 170 * 171 * @remarks Will not take any locks. 172 */ 173 RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs); 158 174 159 175 /** … … 164 180 * 165 181 * @param hDbgAs The address space handle. 182 * 183 * @remarks Will not take any locks. 166 184 */ 167 185 RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs); … … 174 192 * 175 193 * @param hDbgAs The address space handle. 194 * 195 * @remarks Will not take any locks. 176 196 */ 177 197 RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs); … … 184 204 * 185 205 * @param hDbgAs The address space handle. 206 * 207 * @remarks Will not take any locks. 186 208 */ 187 209 RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs); … … 196 218 * 197 219 * @param hDbgAs The address space handle. 220 * 221 * @remarks Will not take any locks. 198 222 */ 199 223 RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs); 224 225 /** @name Flags for RTDbgAsModuleLink and RTDbgAsModuleLinkSeg 226 * @{ */ 227 /** Replace all conflicting module. 228 * (The conflicting modules will be removed the address space and their 229 * references released.) */ 230 #define RTDBGASLINK_FLAGS_REPLACE RT_BIT_32(0) 231 /** Mask containing the valid flags. */ 232 #define RTDBGASLINK_FLAGS_VALID_MASK UINT32_C(0x00000001) 233 /** @} */ 200 234 201 235 /** … … 212 246 * @param hDbgMod The module handle of the module to be linked in. 213 247 * @param ImageAddr The address to link the module at. 214 */ 215 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr); 248 * @param fFlags See RTDBGASLINK_FLAGS_*. 249 */ 250 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags); 216 251 217 252 /** … … 230 265 * linked in. 231 266 * @param SegAddr The address to link the segment at. 232 */ 233 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr); 267 * @param fFlags See RTDBGASLINK_FLAGS_*. 268 */ 269 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags); 234 270 235 271 /** … … 414 450 * @{ 415 451 */ 416 RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, const char *pszImgFile, const char *pszDbgFile); 417 RTDECL(int) RTDbgModDestroy(RTDBGMOD hDbgMod); 452 RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cb, uint32_t fFlags); 453 RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags); 454 RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags); 418 455 RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod); 419 456 RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod); -
trunk/src/VBox/Runtime/common/dbg/dbgas.cpp
r19566 r19757 35 35 #include <iprt/asm.h> 36 36 #include <iprt/avl.h> 37 #include <iprt/assert.h> 38 #include <iprt/err.h> 39 #include <iprt/mem.h> 40 #include <iprt/param.h> 37 41 #include <iprt/string.h> 38 39 #include <iprt/mem.h> 40 #include <iprt/err.h> 41 #include <iprt/assert.h> 42 #include <iprt/param.h> 43 //#include "internal/dbg.h" 42 #include <iprt/semaphore.h> 44 43 #include "internal/magics.h" 45 44 … … 102 101 /** Magic value (RTDBGAS_MAGIC). */ 103 102 uint32_t u32Magic; 103 /** The number of reference to this address space. */ 104 uint32_t volatile cRefs; 105 /** Handle of the read-write lock. */ 106 RTSEMRW hLock; 104 107 /** Number of modules in the module address space. */ 105 108 uint32_t cModules; … … 132 135 AssertPtrReturn((pDbgAs), (rc)); \ 133 136 AssertReturn((pDbgAs)->u32Magic == RTDBGAS_MAGIC, (rc)); \ 137 AssertReturn((pDbgAs)->cRefs > 0, (rc)); \ 138 } while (0) 139 140 /** Locks the address space for reading. */ 141 #define RTDBGAS_LOCK_READ(pDbgAs) \ 142 do { \ 143 int rcLock = RTSemRWRequestRead((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \ 144 AssertRC(rcLock); \ 145 } while (0) 146 147 /** Unlocks the address space after reading. */ 148 #define RTDBGAS_UNLOCK_READ(pDbgAs) \ 149 do { \ 150 int rcLock = RTSemRWReleaseRead((pDbgAs)->hLock); \ 151 AssertRC(rcLock); \ 152 } while (0) 153 154 /** Locks the address space for writing. */ 155 #define RTDBGAS_LOCK_WRITE(pDbgAs) \ 156 do { \ 157 int rcLock = RTSemRWRequestWrite((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \ 158 AssertRC(rcLock); \ 159 } while (0) 160 161 /** Unlocks the address space after writing. */ 162 #define RTDBGAS_UNLOCK_WRITE(pDbgAs) \ 163 do { \ 164 int rcLock = RTSemRWReleaseWrite((pDbgAs)->hLock); \ 165 AssertRC(rcLock); \ 134 166 } while (0) 135 167 … … 139 171 *******************************************************************************/ 140 172 static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod); 173 static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap); 141 174 142 175 … … 170 203 /* initalize it. */ 171 204 pDbgAs->u32Magic = RTDBGAS_MAGIC; 205 pDbgAs->cRefs = 1; 206 pDbgAs->hLock = NIL_RTSEMRW; 172 207 pDbgAs->cModules = 0; 173 208 pDbgAs->paModules = NULL; … … 178 213 pDbgAs->LastAddr = LastAddr; 179 214 memcpy(pDbgAs->szName, pszName, cchName + 1); 180 181 *phDbgAs = pDbgAs; 182 return VINF_SUCCESS; 215 int rc = RTSemRWCreate(&pDbgAs->hLock); 216 if (RT_SUCCESS(rc)) 217 { 218 *phDbgAs = pDbgAs; 219 return VINF_SUCCESS; 220 } 221 222 pDbgAs->u32Magic = 0; 223 RTMemFree(pDbgAs); 224 return rc; 183 225 } 184 226 … … 269 311 * reference counting. 270 312 * 271 * @returns IPRT status code. 272 * 273 * @param hDbgAs The address space handle. A NIL handle will 274 * be quietly ignored. 275 */ 276 RTDECL(int) RTDbgAsDestroy(RTDBGAS hDbgAs) 277 { 278 /* 279 * Validate input. 280 */ 281 if (hDbgAs == NIL_RTDBGAS) 282 return VINF_SUCCESS; 283 PRTDBGASINT pDbgAs = hDbgAs; 284 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 285 313 * @param pDbgAs The address space instance to be destroyed. 314 */ 315 static void rtDbgAsDestroy(PRTDBGASINT pDbgAs) 316 { 286 317 /* 287 318 * Mark the address space invalid and release all the modules. … … 302 333 303 334 RTMemFree(pDbgAs); 304 305 return VINF_SUCCESS; 335 } 336 337 338 /** 339 * Retains a reference to the address space. 340 * 341 * @returns New reference count, UINT32_MAX on invalid handle (asserted). 342 * 343 * @param hDbgAs The address space handle. 344 * 345 * @remarks Will not take any locks. 346 */ 347 RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs) 348 { 349 PRTDBGASINT pDbgAs = hDbgAs; 350 RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX); 351 return ASMAtomicIncU32(&pDbgAs->cRefs); 352 } 353 354 355 /** 356 * Release a reference to the address space. 357 * 358 * When the reference count reaches zero, the address space is destroyed. 359 * That means unlinking all the modules it currently contains, potentially 360 * causing some or all of them to be destroyed as they are managed by 361 * reference counting. 362 * 363 * @returns New reference count, UINT32_MAX on invalid handle (asserted). 364 * 365 * @param hDbgAs The address space handle. The NIL handle is quietly 366 * ignored and 0 is returned. 367 * 368 * @remarks Will not take any locks. 369 */ 370 RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs) 371 { 372 if (hDbgAs == NIL_RTDBGAS) 373 return 0; 374 PRTDBGASINT pDbgAs = hDbgAs; 375 RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX); 376 377 uint32_t cRefs = ASMAtomicDecU32(&pDbgAs->cRefs); 378 if (!cRefs) 379 rtDbgAsDestroy(pDbgAs); 380 return cRefs; 306 381 } 307 382 … … 314 389 * 315 390 * @param hDbgAs The address space handle. 391 * 392 * @remarks Will not take any locks. 316 393 */ 317 394 RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs) … … 330 407 * 331 408 * @param hDbgAs The address space handle. 409 * 410 * @remarks Will not take any locks. 332 411 */ 333 412 RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs) … … 346 425 * 347 426 * @param hDbgAs The address space handle. 427 * 428 * @remarks Will not take any locks. 348 429 */ 349 430 RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs) … … 363 444 * 364 445 * @param hDbgAs The address space handle. 365 */ 366 RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs) 446 * 447 * @remarks Will not take any locks. 448 */ 449 RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs) 367 450 { 368 451 PRTDBGASINT pDbgAs = hDbgAs; … … 382 465 * @param cb The size of what we're linking. 383 466 * @param pszName The name of the module. 467 * @param fFlags See RTDBGASLINK_FLAGS_*. 468 * 469 * @remarks The caller must have locked the address space for writing. 384 470 */ 385 471 int rtDbgAsModuleLinkCommon(PRTDBGASINT pDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, 386 RTUINTPTR Addr, RTUINTPTR cb, const char *pszName )472 RTUINTPTR Addr, RTUINTPTR cb, const char *pszName, uint32_t fFlags) 387 473 { 388 474 /* 389 475 * Check that the requested space is undisputed. 390 476 */ 391 PRTDBGASMAP pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, false /* fAbove */); 392 if ( pAdjMod 393 && pAdjMod->Core.KeyLast >= Addr) 394 return VERR_ADDRESS_CONFLICT; 395 pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, true /* fAbove */); 396 if ( pAdjMod 397 && pAdjMod->Core.Key >= Addr + cb - 1) 398 return VERR_ADDRESS_CONFLICT; 477 for (;;) 478 { 479 PRTDBGASMAP pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, false /* fAbove */); 480 if ( pAdjMod 481 && pAdjMod->Core.KeyLast >= Addr) 482 { 483 if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE)) 484 return VERR_ADDRESS_CONFLICT; 485 rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod); 486 continue; 487 } 488 pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, true /* fAbove */); 489 if ( pAdjMod 490 && pAdjMod->Core.Key >= Addr + cb - 1) 491 { 492 if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE)) 493 return VERR_ADDRESS_CONFLICT; 494 rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod); 495 continue; 496 } 497 break; 498 } 399 499 400 500 /* … … 491 591 492 592 493 494 495 593 /** 496 594 * Links a module into the address space at the give address. … … 506 604 * @param hDbgMod The module handle of the module to be linked in. 507 605 * @param ImageAddr The address to link the module at. 508 */ 509 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr) 606 * @param fFlags See RTDBGASLINK_FLAGS_*. 607 */ 608 RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags) 510 609 { 511 610 /* … … 526 625 || ImageAddr + cb - 1 < ImageAddr) 527 626 return VERR_OUT_OF_RANGE; 627 AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); 528 628 529 629 /* 530 630 * Invoke worker common with RTDbgAsModuleLinkSeg. 531 631 */ 532 return rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, NIL_RTDBGSEGIDX, ImageAddr, cb, pszName); 632 RTDBGAS_LOCK_WRITE(pDbgAs); 633 int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, NIL_RTDBGSEGIDX, ImageAddr, cb, pszName, fFlags); 634 RTDBGAS_UNLOCK_WRITE(pDbgAs); 635 return rc; 533 636 } 534 637 … … 549 652 * linked in. 550 653 * @param SegAddr The address to link the segment at. 551 */ 552 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr) 654 * @param fFlags See RTDBGASLINK_FLAGS_*. 655 */ 656 RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags) 553 657 { 554 658 /* … … 569 673 || SegAddr + cb - 1 < SegAddr) 570 674 return VERR_OUT_OF_RANGE; 675 AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); 571 676 572 677 /* 573 678 * Invoke worker common with RTDbgAsModuleLinkSeg. 574 679 */ 575 return rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, iSeg, SegAddr, cb, pszName); 680 RTDBGAS_LOCK_WRITE(pDbgAs); 681 int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, iSeg, SegAddr, cb, pszName, fFlags); 682 RTDBGAS_UNLOCK_WRITE(pDbgAs); 683 return rc; 576 684 } 577 685 … … 582 690 * @param pDbgAs Pointer to the address space instance data. 583 691 * @param pMod The module to unlink. 692 * 693 * @remarks The caller must have locked the address space for writing. 584 694 */ 585 695 static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod) … … 636 746 * @param pDbgAs Pointer to the address space instance data. 637 747 * @param pMap The map to unlink and free. 748 * 749 * @remarks The caller must have locked the address space for writing. 638 750 */ 639 751 static void rtDbgAsModuleUnlinkMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap) … … 669 781 670 782 /** 671 * Unlinks all the mappings of a module from the address space. 672 * 673 * @returns IPRT status code. 674 * @retval VERR_NOT_FOUND if the module wasn't found. 675 * 676 * @param hDbgAs The address space handle. 677 * @param hDbgMod The module handle of the module to be unlinked. 678 */ 679 RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod) 680 { 681 /* 682 * Validate input. 683 */ 684 PRTDBGASINT pDbgAs = hDbgAs; 685 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 686 if (hDbgMod == NIL_RTDBGMOD) 687 return VINF_SUCCESS; 688 689 PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod); 690 if (!pMod) 691 return VERR_NOT_FOUND; 692 693 /* 694 * Unmap all but 695 */ 696 while (pMod->pMapHead) 697 rtDbgAsModuleUnlinkMap(pDbgAs, pMod->pMapHead); 698 rtDbgAsModuleUnlinkMod(pDbgAs, pMod); 699 return VINF_SUCCESS; 700 } 701 702 703 /** 704 * Unlinks the mapping at the specified address. 705 * 706 * @returns IPRT status code. 707 * @retval VERR_NOT_FOUND if no module or segment is mapped at that address. 708 * 709 * @param hDbgAs The address space handle. 710 * @param Addr The address within the mapping to be unlinked. 711 */ 712 RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr) 713 { 714 /* 715 * Validate input. 716 */ 717 PRTDBGASINT pDbgAs = hDbgAs; 718 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 719 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 720 if (pMap) 721 return VERR_NOT_FOUND; 722 783 * Worker for RTDbgAsModuleUnlinkByAddr and rtDbgAsModuleLinkCommon that 784 * unlinks a single mapping and releases the module if it's the last one. 785 * 786 * @param pDbgAs The address space instance. 787 * @param pMap The mapping to unlink. 788 * 789 * @remarks The caller must have locked the address space for writing. 790 */ 791 static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap) 792 { 723 793 /* 724 794 * Unlink it from the address space. … … 729 799 if (!pMod->pMapHead) 730 800 rtDbgAsModuleUnlinkMod(pDbgAs, pMod); 801 } 802 803 804 /** 805 * Unlinks all the mappings of a module from the address space. 806 * 807 * @returns IPRT status code. 808 * @retval VERR_NOT_FOUND if the module wasn't found. 809 * 810 * @param hDbgAs The address space handle. 811 * @param hDbgMod The module handle of the module to be unlinked. 812 */ 813 RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod) 814 { 815 /* 816 * Validate input. 817 */ 818 PRTDBGASINT pDbgAs = hDbgAs; 819 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 820 if (hDbgMod == NIL_RTDBGMOD) 821 return VINF_SUCCESS; 822 823 RTDBGAS_LOCK_WRITE(pDbgAs); 824 PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod); 825 if (!pMod) 826 { 827 RTDBGAS_UNLOCK_WRITE(pDbgAs); 828 return VERR_NOT_FOUND; 829 } 830 831 /* 832 * Unmap all everything and release the module. 833 */ 834 while (pMod->pMapHead) 835 rtDbgAsModuleUnlinkMap(pDbgAs, pMod->pMapHead); 836 rtDbgAsModuleUnlinkMod(pDbgAs, pMod); 837 838 RTDBGAS_UNLOCK_WRITE(pDbgAs); 839 return VINF_SUCCESS; 840 } 841 842 843 /** 844 * Unlinks the mapping at the specified address. 845 * 846 * @returns IPRT status code. 847 * @retval VERR_NOT_FOUND if no module or segment is mapped at that address. 848 * 849 * @param hDbgAs The address space handle. 850 * @param Addr The address within the mapping to be unlinked. 851 */ 852 RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr) 853 { 854 /* 855 * Validate input. 856 */ 857 PRTDBGASINT pDbgAs = hDbgAs; 858 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 859 860 RTDBGAS_LOCK_WRITE(pDbgAs); 861 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 862 if (pMap) 863 { 864 RTDBGAS_UNLOCK_WRITE(pDbgAs); 865 return VERR_NOT_FOUND; 866 } 867 868 /* 869 * Hand it to 870 */ 871 rtDbgAsModuleUnlinkByMap(pDbgAs, pMap); 872 873 RTDBGAS_UNLOCK_WRITE(pDbgAs); 731 874 return VINF_SUCCESS; 732 875 } … … 754 897 PRTDBGASINT pDbgAs = hDbgAs; 755 898 RTDBGAS_VALID_RETURN_RC(pDbgAs, NIL_RTDBGMOD); 899 900 RTDBGAS_LOCK_READ(pDbgAs); 756 901 if (iModule >= pDbgAs->cModules) 902 { 903 RTDBGAS_UNLOCK_READ(pDbgAs); 757 904 return NIL_RTDBGMOD; 905 } 758 906 759 907 /* … … 762 910 RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[iModule].Core.Key; 763 911 RTDbgModRetain(hMod); 912 913 RTDBGAS_UNLOCK_READ(pDbgAs); 764 914 return hMod; 765 915 } … … 789 939 PRTDBGASINT pDbgAs = hDbgAs; 790 940 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 941 942 RTDBGAS_LOCK_READ(pDbgAs); 791 943 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 792 944 if (pMap) 945 { 946 RTDBGAS_UNLOCK_READ(pDbgAs); 793 947 return VERR_NOT_FOUND; 948 } 794 949 795 950 /* … … 806 961 if (piSeg) 807 962 *piSeg = pMap->iSeg; 963 964 RTDBGAS_UNLOCK_READ(pDbgAs); 808 965 return VINF_SUCCESS; 809 966 } … … 832 989 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 833 990 AssertPtrReturn(phMod, VERR_INVALID_POINTER); 991 992 RTDBGAS_LOCK_READ(pDbgAs); 834 993 PRTDBGASNAME pName = (PRTDBGASNAME)RTStrSpaceGet(&pDbgAs->NameSpace, pszName); 835 994 if (!pName) 995 { 996 RTDBGAS_UNLOCK_READ(pDbgAs); 836 997 return VERR_NOT_FOUND; 998 } 837 999 838 1000 PRTDBGASMOD pMod = pName->pHead; … … 841 1003 pMod = pMod->pNextName; 842 1004 if (!pMod) 1005 { 1006 RTDBGAS_UNLOCK_READ(pDbgAs); 843 1007 return VERR_OUT_OF_RANGE; 1008 } 844 1009 } 845 1010 … … 850 1015 RTDbgModRetain(hMod); 851 1016 *phMod = hMod; 1017 1018 RTDBGAS_UNLOCK_READ(pDbgAs); 852 1019 return VINF_SUCCESS; 1020 } 1021 1022 1023 /** 1024 * Internal worker that looks up and retains a module. 1025 * 1026 * @returns Module handle, NIL_RTDBGMOD if not found. 1027 * @param pDbgAs The address space instance data. 1028 * @param Addr Address within the module. 1029 * @param piSeg where to return the segment index. 1030 * @param poffSeg Where to return the segment offset. 1031 */ 1032 DECLINLINE(RTDBGMOD) rtDbgAsModuleByAddr(PRTDBGASINT pDbgAs, RTUINTPTR Addr, PRTDBGSEGIDX piSeg, PRTUINTPTR poffSeg) 1033 { 1034 RTDBGMOD hMod = NIL_RTDBGMOD; 1035 1036 RTDBGAS_LOCK_READ(pDbgAs); 1037 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 1038 if (pMap) 1039 { 1040 hMod = (RTDBGMOD)pMap->pMod->Core.Key; 1041 RTDbgModRetain(hMod); 1042 *piSeg = pMap->iSeg; 1043 *poffSeg = Addr - pMap->Core.Key; 1044 } 1045 RTDBGAS_UNLOCK_READ(pDbgAs); 1046 1047 return hMod; 853 1048 } 854 1049 … … 869 1064 { 870 1065 /* 871 * Validate input.1066 * Validate input and resolve the address. 872 1067 */ 873 1068 PRTDBGASINT pDbgAs = hDbgAs; 874 1069 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 875 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 876 if (pMap) 1070 1071 RTDBGSEGIDX iSeg; 1072 RTUINTPTR offSeg; 1073 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg); 1074 if (hMod == NIL_RTDBGMOD) 877 1075 return VERR_NOT_FOUND; 878 1076 … … 880 1078 * Forward the call. 881 1079 */ 882 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key; 883 return RTDbgModSymbolAdd(hMod, pszSymbol, pMap->iSeg, Addr - pMap->Core.Key, cb); 1080 int rc = RTDbgModSymbolAdd(hMod, pszSymbol, iSeg, offSeg, cb); 1081 RTDbgModRelease(hMod); 1082 return rc; 884 1083 } 885 1084 … … 901 1100 { 902 1101 /* 903 * Validate input .1102 * Validate input and resolve the address. 904 1103 */ 905 1104 PRTDBGASINT pDbgAs = hDbgAs; 906 1105 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 907 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 908 if (pMap) 1106 1107 RTDBGSEGIDX iSeg; 1108 RTUINTPTR offSeg; 1109 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg); 1110 if (hMod == NIL_RTDBGMOD) 909 1111 return VERR_NOT_FOUND; 910 1112 … … 912 1114 * Forward the call. 913 1115 */ 914 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key; 915 return RTDbgModSymbolByAddr(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, pSymbol); 1116 int rc = RTDbgModSymbolByAddr(hMod, iSeg, offSeg, poffDisp, pSymbol); 1117 RTDbgModRelease(hMod); 1118 return rc; 916 1119 } 917 1120 … … 934 1137 { 935 1138 /* 936 * Validate input .1139 * Validate input and resolve the address. 937 1140 */ 938 1141 PRTDBGASINT pDbgAs = hDbgAs; 939 1142 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 940 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 941 if (pMap) 1143 1144 RTDBGSEGIDX iSeg; 1145 RTUINTPTR offSeg; 1146 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg); 1147 if (hMod == NIL_RTDBGMOD) 942 1148 return VERR_NOT_FOUND; 943 1149 … … 945 1151 * Forward the call. 946 1152 */ 947 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key; 948 return RTDbgModSymbolByAddrA(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, ppSymbol); 1153 int rc = RTDbgModSymbolByAddrA(hMod, iSeg, offSeg, poffDisp, ppSymbol); 1154 RTDbgModRelease(hMod); 1155 return rc; 1156 } 1157 1158 1159 /** 1160 * Creates a snapshot of the module table on the temporary heap. 1161 * 1162 * The caller must release all the module handles before freeing the table 1163 * using RTMemTmpFree. 1164 * 1165 * @returns Module table snaphot. 1166 * @param pDbgAs The address space instance data. 1167 * @param pcModules Where to return the number of modules. 1168 */ 1169 DECLINLINE(PRTDBGMOD) rtDbgAsSnapshotModuleTable(PRTDBGASINT pDbgAs, uint32_t *pcModules) 1170 { 1171 RTDBGAS_LOCK_READ(pDbgAs); 1172 1173 uint32_t iMod = *pcModules = pDbgAs->cModules; 1174 PRTDBGMOD paModules = (PRTDBGMOD)RTMemTmpAlloc(sizeof(paModules[0]) * RT_MAX(iMod, 1)); 1175 if (paModules) 1176 { 1177 while (iMod-- > 0) 1178 { 1179 RTDBGMOD hMod = paModules[iMod]; 1180 paModules[iMod] = hMod; 1181 RTDbgModRetain(hMod); 1182 } 1183 } 1184 1185 RTDBGAS_UNLOCK_READ(pDbgAs); 1186 return paModules; 949 1187 } 950 1188 … … 973 1211 * Iterate the modules, looking for the symbol. 974 1212 */ 975 for (uint32_t i = 0; i < pDbgAs->cModules; i++) 976 { 977 RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[i].Core.Key; 978 int rc = RTDbgModSymbolByName(hMod, pszSymbol, pSymbol); 1213 uint32_t cModules; 1214 PRTDBGMOD paModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules); 1215 if (!paModules) 1216 return VERR_NO_TMP_MEMORY; 1217 1218 for (uint32_t i = 0; i < cModules; i++) 1219 { 1220 int rc = RTDbgModSymbolByName(paModules[i], pszSymbol, pSymbol); 1221 RTDbgModRelease(paModules[i]); 979 1222 if (RT_SUCCESS(rc)) 1223 { 1224 for (i = i + 1; i < cModules; i++) 1225 RTDbgModRelease(paModules[i]); 1226 RTMemTmpFree(paModules); 980 1227 return rc; 981 } 1228 } 1229 } 1230 1231 RTMemTmpFree(paModules); 982 1232 return VERR_SYMBOL_NOT_FOUND; 983 1233 } … … 1009 1259 * Iterate the modules, looking for the symbol. 1010 1260 */ 1011 for (uint32_t i = 0; i < pDbgAs->cModules; i++) 1012 { 1013 RTDBGMOD hMod = (RTDBGMOD)pDbgAs->paModules[i].Core.Key; 1014 int rc = RTDbgModSymbolByNameA(hMod, pszSymbol, ppSymbol); 1261 uint32_t cModules; 1262 PRTDBGMOD paModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules); 1263 if (!paModules) 1264 return VERR_NO_TMP_MEMORY; 1265 1266 for (uint32_t i = 0; i < cModules; i++) 1267 { 1268 int rc = RTDbgModSymbolByNameA(paModules[i], pszSymbol, ppSymbol); 1269 RTDbgModRelease(paModules[i]); 1015 1270 if (RT_SUCCESS(rc)) 1271 { 1272 for (i = i + 1; i < cModules; i++) 1273 RTDbgModRelease(paModules[i]); 1274 RTMemTmpFree(paModules); 1016 1275 return rc; 1017 } 1276 } 1277 } 1278 1279 RTMemTmpFree(paModules); 1018 1280 return VERR_SYMBOL_NOT_FOUND; 1019 1281 } … … 1036 1298 { 1037 1299 /* 1038 * Validate input .1300 * Validate input and resolve the address. 1039 1301 */ 1040 1302 PRTDBGASINT pDbgAs = hDbgAs; 1041 1303 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 1042 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 1043 if (pMap) 1304 1305 RTDBGSEGIDX iSeg; 1306 RTUINTPTR offSeg; 1307 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg); 1308 if (hMod == NIL_RTDBGMOD) 1044 1309 return VERR_NOT_FOUND; 1045 1310 … … 1047 1312 * Forward the call. 1048 1313 */ 1049 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key; 1050 return RTDbgModLineByAddr(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, pLine); 1314 int rc = RTDbgModLineByAddr(hMod, iSeg, offSeg, poffDisp, pLine); 1315 RTDbgModRelease(hMod); 1316 return rc; 1051 1317 } 1052 1318 … … 1069 1335 { 1070 1336 /* 1071 * Validate input .1337 * Validate input and resolve the address. 1072 1338 */ 1073 1339 PRTDBGASINT pDbgAs = hDbgAs; 1074 1340 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE); 1075 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr); 1076 if (pMap) 1341 1342 RTDBGSEGIDX iSeg; 1343 RTUINTPTR offSeg; 1344 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg); 1345 if (hMod == NIL_RTDBGMOD) 1077 1346 return VERR_NOT_FOUND; 1078 1347 … … 1080 1349 * Forward the call. 1081 1350 */ 1082 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key; 1083 return RTDbgModLineByAddrA(hMod, pMap->iSeg, Addr - pMap->Core.Key, poffDisp, ppLine); 1084 } 1085 1351 int rc = RTDbgModLineByAddrA(hMod, iSeg, offSeg, poffDisp, ppLine); 1352 RTDbgModRelease(hMod); 1353 return rc; 1354 } 1355 -
trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp
r19566 r19757 45 45 46 46 47 RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, const char *pszImgFile, const char *pszDbgFile) 47 RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cb, uint32_t fFlags) 48 { 49 return VERR_NOT_IMPLEMENTED; 50 } 51 52 RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags) 53 { 54 return VERR_NOT_IMPLEMENTED; 55 } 56 57 RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags) 48 58 { 49 59 return VERR_NOT_IMPLEMENTED; -
trunk/src/VBox/VMM/DBGF.cpp
r19423 r19757 138 138 { 139 139 int rc = dbgfR3InfoInit(pVM); 140 if (RT_SUCCESS(rc)) 141 rc = dbgfR3AsInit(pVM); 140 142 if (RT_SUCCESS(rc)) 141 143 rc = dbgfR3SymInit(pVM); … … 208 210 */ 209 211 dbgfR3OSTerm(pVM); 212 dbgfR3AsTerm(pVM); 210 213 dbgfR3InfoTerm(pVM); 211 214 return VINF_SUCCESS; … … 223 226 VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta) 224 227 { 228 dbgfR3AsRelocate(pVM, offDelta); 225 229 } 226 230 -
trunk/src/VBox/VMM/DBGFAddrSpace.cpp
r12677 r19757 38 38 */ 39 39 40 40 /******************************************************************************* 41 * Header Files * 42 *******************************************************************************/ 43 #define LOG_GROUP LOG_GROUP_DBGF 44 #include <VBox/dbgf.h> 45 #include <VBox/mm.h> 46 #include "DBGFInternal.h" 47 #include <VBox/vm.h> 48 #include <VBox/err.h> 49 #include <VBox/log.h> 50 51 #include <iprt/assert.h> 52 #include <iprt/ctype.h> 53 #include <iprt/env.h> 54 #include <iprt/path.h> 55 #include <iprt/param.h> 56 57 58 /******************************************************************************* 59 * Structures and Typedefs * 60 *******************************************************************************/ 61 /** 62 * Address space database node. 63 */ 64 typedef struct DBGFASDBNODE 65 { 66 /** The node core for DBGF::AsHandleTree, the key is the address space handle. */ 67 AVLPVNODECORE HandleCore; 68 /** The node core for DBGF::AsPidTree, the key is the process id. */ 69 AVLU32NODECORE PidCore; 70 /** The node core for DBGF::AsNameSpace, the string is the address space name. */ 71 RTSTRSPACECORE NameCore; 72 73 } DBGFASDBNODE; 74 /** Pointer to an address space database node. */ 75 typedef DBGFASDBNODE *PDBGFASDBNODE; 76 77 78 /** 79 * For dbgfR3AsLoadImageOpenData and dbgfR3AsLoadMapOpenData. 80 */ 81 typedef struct DBGFR3ASLOADOPENDATA 82 { 83 const char *pszModName; 84 RTGCUINTPTR uSubtrahend; 85 uint32_t fFlags; 86 RTDBGMOD hMod; 87 } DBGFR3ASLOADOPENDATA; 88 89 /** 90 * Callback for dbgfR3AsSearchPath and dbgfR3AsSearchEnvPath. 91 * 92 * @returns VBox status code. If success, then the search is completed. 93 * @param pszFilename The file name under evaluation. 94 * @param pvUser The user argument. 95 */ 96 typedef int FNDBGFR3ASSEARCHOPEN(const char *pszFilename, void *pvUser); 97 /** Pointer to a FNDBGFR3ASSEARCHOPEN. */ 98 typedef FNDBGFR3ASSEARCHOPEN *PFNDBGFR3ASSEARCHOPEN; 99 100 101 /******************************************************************************* 102 * Defined Constants And Macros * 103 *******************************************************************************/ 104 /** Locks the address space database for writing. */ 105 #define DBGF_AS_DB_LOCK_WRITE(pVM) \ 106 do { \ 107 int rcSem = RTSemRWRequestWrite((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ 108 AssertRC(rcSem); \ 109 } while (0) 110 111 /** Unlocks the address space database after writing. */ 112 #define DBGF_AS_DB_UNLOCK_WRITE(pVM) \ 113 do { \ 114 int rcSem = RTSemRWReleaseWrite((pVM)->dbgf.s.hAsDbLock); \ 115 AssertRC(rcSem); \ 116 } while (0) 117 118 /** Locks the address space database for reading. */ 119 #define DBGF_AS_DB_LOCK_READ(pVM) \ 120 do { \ 121 int rcSem = RTSemRWRequestRead((pVM)->dbgf.s.hAsDbLock, RT_INDEFINITE_WAIT); \ 122 AssertRC(rcSem); \ 123 } while (0) 124 125 /** Unlocks the address space database after reading. */ 126 #define DBGF_AS_DB_UNLOCK_READ(pVM) \ 127 do { \ 128 int rcSem = RTSemRWReleaseRead((pVM)->dbgf.s.hAsDbLock); \ 129 AssertRC(rcSem); \ 130 } while (0) 131 132 133 134 /** 135 * Initializes the address space parts of DBGF. 136 * 137 * @returns VBox status code. 138 * @param pVM The VM handle. 139 */ 140 int dbgfR3AsInit(PVM pVM) 141 { 142 /* 143 * Create the semaphore. 144 */ 145 int rc = RTSemRWCreate(&pVM->dbgf.s.hAsDbLock); 146 AssertRCReturn(rc, rc); 147 148 /* 149 * Create the standard address spaces. 150 */ 151 RTDBGAS hDbgAs; 152 rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "Global"); 153 AssertRCReturn(rc, rc); 154 rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); 155 AssertRCReturn(rc, rc); 156 RTDbgAsRetain(hDbgAs); 157 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs; 158 159 RTDbgAsRetain(hDbgAs); 160 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs; 161 162 rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "Physical"); 163 AssertRCReturn(rc, rc); 164 rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); 165 AssertRCReturn(rc, rc); 166 RTDbgAsRetain(hDbgAs); 167 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs; 168 169 rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode"); 170 AssertRCReturn(rc, rc); 171 rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); 172 AssertRCReturn(rc, rc); 173 RTDbgAsRetain(hDbgAs); 174 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs; 175 RTDbgAsRetain(hDbgAs); 176 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs; 177 178 rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRing0"); 179 AssertRCReturn(rc, rc); 180 rc = DBGFR3AsAdd(pVM, hDbgAs, NIL_RTPROCESS); 181 AssertRCReturn(rc, rc); 182 RTDbgAsRetain(hDbgAs); 183 pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs; 184 185 return VINF_SUCCESS; 186 } 187 188 189 /** 190 * Callback used by dbgfR3AsTerm / RTAvlPVDestroy to release an address space. 191 * 192 * @returns 0. 193 * @param pNode The address space database node. 194 * @param pvIgnore NULL. 195 */ 196 static DECLCALLBACK(int) dbgfR3AsTermDestroyNode(PAVLPVNODECORE pNode, void *pvIgnore) 197 { 198 PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)pNode; 199 RTDbgAsRelease((RTDBGAS)pDbNode->HandleCore.Key); 200 pDbNode->HandleCore.Key = NIL_RTDBGAS; 201 /* Don't bother freeing it here as MM will free it soon and MM is much at 202 it when doing it wholesale instead of piecemeal. */ 203 NOREF(pvIgnore); 204 return 0; 205 } 206 207 208 /** 209 * Terminates the address space parts of DBGF. 210 * 211 * @param pVM The VM handle. 212 */ 213 void dbgfR3AsTerm(PVM pVM) 214 { 215 /* 216 * Create the semaphore. 217 */ 218 int rc = RTSemRWDestroy(pVM->dbgf.s.hAsDbLock); 219 AssertRC(rc); 220 pVM->dbgf.s.hAsDbLock = NIL_RTSEMRW; 221 222 /* 223 * Release all the address spaces. 224 */ 225 RTAvlPVDestroy(&pVM->dbgf.s.AsHandleTree, dbgfR3AsTermDestroyNode, NULL); 226 for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++) 227 { 228 RTDbgAsRelease(pVM->dbgf.s.ahAsAliases[i]); 229 pVM->dbgf.s.ahAsAliases[i] = NIL_RTDBGAS; 230 } 231 } 232 233 234 /** 235 * Relocates the RC address space. 236 * 237 * @param pVM The VM handle. 238 * @param offDelta The relocation delta. 239 */ 240 void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta) 241 { 242 /** @todo */ 243 } 244 245 246 /** 247 * Adds the address space to the database. 248 * 249 * @returns VBox status code. 250 * @param pVM The VM handle. 251 * @param hDbgAs The address space handle. The reference of the 252 * caller will NOT be consumed. 253 * @param ProcId The process id or NIL_RTPROCESS. 254 */ 255 VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId) 256 { 257 /* 258 * Input validation. 259 */ 260 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 261 const char *pszName = RTDbgAsName(hDbgAs); 262 if (!pszName) 263 return VERR_INVALID_HANDLE; 264 uint32_t cRefs = RTDbgAsRetain(hDbgAs); 265 if (cRefs == UINT32_MAX) 266 return VERR_INVALID_HANDLE; 267 268 /* 269 * Allocate a tracking node. 270 */ 271 int rc = VERR_NO_MEMORY; 272 PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_AS, sizeof(*pDbNode)); 273 if (pDbNode) 274 { 275 pDbNode->HandleCore.Key = hDbgAs; 276 pDbNode->PidCore.Key = NIL_RTPROCESS; 277 pDbNode->NameCore.pszString = pszName; 278 pDbNode->NameCore.cchString = strlen(pszName); 279 DBGF_AS_DB_LOCK_WRITE(pVM); 280 if (RTStrSpaceInsert(&pVM->dbgf.s.AsNameSpace, &pDbNode->NameCore)) 281 { 282 if (RTAvlPVInsert(&pVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore)) 283 { 284 DBGF_AS_DB_UNLOCK_WRITE(pVM); 285 return VINF_SUCCESS; 286 } 287 288 /* bail out */ 289 RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pszName); 290 } 291 DBGF_AS_DB_UNLOCK_WRITE(pVM); 292 MMR3HeapFree(pDbNode); 293 } 294 RTDbgAsRelease(hDbgAs); 295 return rc; 296 } 297 298 299 /** 300 * Delete an address space from the database. 301 * 302 * The address space must not be engaged as any of the standard aliases. 303 * 304 * @returns VBox status code. 305 * @retval VERR_SHARING_VIOLATION if in use as an alias. 306 * @retval VERR_NOT_FOUND if not found in the address space database. 307 * 308 * @param pVM The VM handle. 309 * @param hDbgAs The address space handle. Aliases are not allowed. 310 */ 311 VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs) 312 { 313 /* 314 * Input validation. Retain the address space so it can be released outside 315 * the lock as well as validated. 316 */ 317 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 318 if (hDbgAs == NIL_RTDBGAS) 319 return VINF_SUCCESS; 320 uint32_t cRefs = RTDbgAsRetain(hDbgAs); 321 if (cRefs == UINT32_MAX) 322 return VERR_INVALID_HANDLE; 323 RTDbgAsRelease(hDbgAs); 324 325 DBGF_AS_DB_LOCK_WRITE(pVM); 326 327 /* 328 * You cannot delete any of the aliases. 329 */ 330 for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++) 331 if (pVM->dbgf.s.ahAsAliases[i] == hDbgAs) 332 { 333 DBGF_AS_DB_UNLOCK_WRITE(pVM); 334 return VERR_SHARING_VIOLATION; 335 } 336 337 /* 338 * Ok, try remove it from the database. 339 */ 340 PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pVM->dbgf.s.AsHandleTree, hDbgAs); 341 if (!pDbNode) 342 { 343 DBGF_AS_DB_UNLOCK_WRITE(pVM); 344 return VERR_NOT_FOUND; 345 } 346 RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString); 347 if (pDbNode->PidCore.Key != NIL_RTPROCESS) 348 RTAvlU32Remove(&pVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key); 349 350 DBGF_AS_DB_UNLOCK_WRITE(pVM); 351 352 /* 353 * Free the resources. 354 */ 355 RTDbgAsRelease(hDbgAs); 356 MMR3HeapFree(pDbNode); 357 358 return VINF_SUCCESS; 359 } 360 361 362 /** 363 * Changes an alias to point to a new address space. 364 * 365 * Not all the aliases can be changed, currently it's only DBGF_AS_GLOBAL 366 * and DBGF_AS_KERNEL. 367 * 368 * @returns VBox status code. 369 * @param pVM The VM handle. 370 * @param hAlias The alias to change. 371 * @param hAliasFor The address space hAlias should be an alias for. 372 * This can be an alias. The caller's reference to 373 * this address space will NOT be consumed. 374 */ 375 VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor) 376 { 377 /* 378 * Input validation. 379 */ 380 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 381 AssertMsgReturn(!DBGF_AS_IS_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); 382 AssertMsgReturn(!DBGF_AS_IS_FIXED_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER); 383 RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pVM, hAlias); 384 if (hRealAliasFor == NIL_RTDBGAS) 385 return VERR_INVALID_HANDLE; 386 387 /* 388 * Make sure the handle has is already in the database. 389 */ 390 int rc = VERR_NOT_FOUND; 391 DBGF_AS_DB_LOCK_WRITE(pVM); 392 if (RTAvlPVGet(&pVM->dbgf.s.AsHandleTree, hRealAliasFor)) 393 { 394 /* 395 * Update the alias table and release the current address space. 396 */ 397 RTDBGAS hAsOld; 398 ASMAtomicXchgHandle(&pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld); 399 uint32_t cRefs = RTDbgAsRelease(hAsOld); 400 Assert(cRefs > 0); 401 Assert(cRefs != UINT32_MAX); 402 rc = VINF_SUCCESS; 403 } 404 DBGF_AS_DB_UNLOCK_WRITE(pVM); 405 406 return rc; 407 } 408 409 410 /** 411 * Resolves the address space handle into a real handle if it's an alias. 412 * 413 * @returns Real address space handle. NIL_RTDBGAS if invalid handle. 414 * 415 * @param pVM The VM handle. 416 * @param hAlias The possibly address space alias. 417 * 418 * @remarks Doesn't take any locks. 419 */ 420 VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias) 421 { 422 VM_ASSERT_VALID_EXT_RETURN(pVM, NULL); 423 AssertCompile(NIL_RTDBGAS == (RTDBGAS)0); 424 425 uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); 426 if (iAlias < DBGF_AS_COUNT) 427 ASMAtomicReadHandle(&pVM->dbgf.s.ahAsAliases[iAlias], &hAlias); 428 return hAlias; 429 } 430 431 432 /** 433 * Resolves the address space handle into a real handle if it's an alias, 434 * and retains whatever it is. 435 * 436 * @returns Real address space handle. NIL_RTDBGAS if invalid handle. 437 * 438 * @param pVM The VM handle. 439 * @param hAlias The possibly address space alias. 440 */ 441 VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias) 442 { 443 VM_ASSERT_VALID_EXT_RETURN(pVM, NULL); 444 AssertCompile(NIL_RTDBGAS == (RTDBGAS)0); 445 446 uint32_t cRefs; 447 uintptr_t iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias); 448 if (iAlias < DBGF_AS_COUNT) 449 { 450 if (DBGF_AS_IS_FIXED_ALIAS(hAlias)) 451 { 452 /* Won't ever change, no need to grab the lock. */ 453 hAlias = pVM->dbgf.s.ahAsAliases[iAlias]; 454 cRefs = RTDbgAsRetain(hAlias); 455 } 456 else 457 { 458 /* May change, grab the lock so we can read it safely. */ 459 DBGF_AS_DB_LOCK_READ(pVM); 460 hAlias = pVM->dbgf.s.ahAsAliases[iAlias]; 461 cRefs = RTDbgAsRetain(hAlias); 462 DBGF_AS_DB_UNLOCK_READ(pVM); 463 } 464 } 465 else 466 /* Not an alias, just retain it. */ 467 cRefs = RTDbgAsRetain(hAlias); 468 469 return cRefs != UINT32_MAX ? hAlias : NIL_RTDBGAS; 470 } 471 472 473 /** 474 * Query an address space by name. 475 * 476 * @returns Retained address space handle if found, NIL_RTDBGAS if not. 477 * 478 * @param pVM The VM handle. 479 * @param pszName The name. 480 */ 481 VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName) 482 { 483 /* 484 * Validate the input. 485 */ 486 VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS); 487 AssertPtrReturn(pszName, NIL_RTDBGAS); 488 AssertReturn(*pszName, NIL_RTDBGAS); 489 490 /* 491 * Look it up in the string space and retain the result. 492 */ 493 RTDBGAS hDbgAs = NIL_RTDBGAS; 494 DBGF_AS_DB_LOCK_READ(pVM); 495 496 PRTSTRSPACECORE pNode = RTStrSpaceGet(&pVM->dbgf.s.AsNameSpace, pszName); 497 if (pNode) 498 { 499 PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, NameCore); 500 hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key; 501 uint32_t cRefs = RTDbgAsRetain(hDbgAs); 502 if (RT_UNLIKELY(cRefs == UINT32_MAX)) 503 hDbgAs = NIL_RTDBGAS; 504 } 505 DBGF_AS_DB_UNLOCK_READ(pVM); 506 507 return hDbgAs; 508 } 509 510 511 /** 512 * Query an address space by process ID. 513 * 514 * @returns Retained address space handle if found, NIL_RTDBGAS if not. 515 * 516 * @param pVM The VM handle. 517 * @param ProcId The process ID. 518 */ 519 VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId) 520 { 521 /* 522 * Validate the input. 523 */ 524 VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS); 525 AssertReturn(ProcId != NIL_RTPROCESS, NIL_RTDBGAS); 526 527 /* 528 * Look it up in the PID tree and retain the result. 529 */ 530 RTDBGAS hDbgAs = NIL_RTDBGAS; 531 DBGF_AS_DB_LOCK_READ(pVM); 532 533 PAVLU32NODECORE pNode = RTAvlU32Get(&pVM->dbgf.s.AsPidTree, ProcId); 534 if (pNode) 535 { 536 PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, PidCore); 537 hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key; 538 uint32_t cRefs = RTDbgAsRetain(hDbgAs); 539 if (RT_UNLIKELY(cRefs == UINT32_MAX)) 540 hDbgAs = NIL_RTDBGAS; 541 } 542 DBGF_AS_DB_UNLOCK_READ(pVM); 543 544 return hDbgAs; 545 } 546 547 548 /** 549 * Searches for the file in the path. 550 * 551 * The file is first tested without any path modification, then we walk the path 552 * looking in each directory. 553 * 554 * @returns VBox status code. 555 * @param pszFilename The file to search for. 556 * @param pszPath The search path. 557 * @param pfnOpen The open callback function. 558 * @param pvUser User argument for the callback. 559 */ 560 static int dbgfR3AsSearchPath(const char *pszFilename, const char *pszPath, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser) 561 { 562 char szFound[RTPATH_MAX]; 563 564 /* Check the filename length. */ 565 size_t const cchFilename = strlen(pszFilename); 566 if (cchFilename >= sizeof(szFound)) 567 return VERR_FILENAME_TOO_LONG; 568 const char *pszName = RTPathFilename(pszFilename); 569 if (!pszName) 570 return VERR_IS_A_DIRECTORY; 571 size_t const cchName = strlen(pszName); 572 573 /* 574 * Try default location first. 575 */ 576 memcpy(szFound, pszFilename, cchFilename + 1); 577 int rc = pfnOpen(szFound, pvUser); 578 if (RT_SUCCESS(rc)) 579 return rc; 580 581 /* 582 * Walk the search path. 583 */ 584 const char *psz = pszPath; 585 while (*psz) 586 { 587 /* Skip leading blanks - no directories with leading spaces, thank you. */ 588 while (RT_C_IS_BLANK(*psz)) 589 psz++; 590 591 /* Fine the end of this element. */ 592 const char *pszNext; 593 const char *pszEnd = strchr(psz, ';'); 594 if (!pszEnd) 595 pszEnd = pszNext = strchr(psz, '\0'); 596 else 597 pszNext = pszEnd + 1; 598 if (pszEnd != psz) 599 { 600 size_t const cch = pszEnd - psz; 601 if (cch + 1 + cchName < sizeof(szFound)) 602 { 603 /** @todo RTPathCompose, RTPathComposeN(). This code isn't right 604 * for 'E:' on DOS systems. It may also create unwanted double slashes. */ 605 memcpy(szFound, psz, cch); 606 szFound[cch] = '/'; 607 memcpy(szFound + cch + 1, pszName, cchName + 1); 608 int rc2 = pfnOpen(szFound, pvUser); 609 if (RT_SUCCESS(rc2)) 610 return rc2; 611 if ( rc2 != rc 612 && ( rc == VERR_FILE_NOT_FOUND 613 || rc == VERR_OPEN_FAILED)) 614 rc = rc2; 615 } 616 } 617 618 /* advance */ 619 psz = pszNext; 620 } 621 622 /* 623 * Walk the path once again, this time do a depth search. 624 */ 625 /** @todo do a depth search using the specified path. */ 626 627 /* failed */ 628 return rc; 629 } 630 631 632 /** 633 * Same as dbgfR3AsSearchEnv, except that the path is taken from the environment. 634 * 635 * It the environment variable doesn't exist, the current directory is searched instead. 636 * 637 * @returns VBox status code. 638 * @param pszFilename The filename. 639 * @param pszEnvVar The environment variable name. 640 * @param pfnOpen The open callback function. 641 * @param pvUser User argument for the callback. 642 */ 643 static int dbgfR3AsSearchEnvPath(const char *pszFilename, const char *pszEnvVar, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser) 644 { 645 const char *pszPath = RTEnvGet(pszEnvVar); 646 if (!pszPath) 647 pszPath = "."; 648 return dbgfR3AsSearchPath(pszFilename, pszPath, pfnOpen, pvUser); 649 } 650 651 652 /** 653 * Callback function used by DBGFR3AsLoadImage. 654 * 655 * @returns VBox status code. 656 * @param pszFilename The filename under evaluation. 657 * @param pvUser Use arguments (DBGFR3ASLOADOPENDATA). 658 */ 659 static DECLCALLBACK(int) dbgfR3AsLoadImageOpen(const char *pszFilename, void *pvUser) 660 { 661 DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser; 662 return RTDbgModCreateFromImage(&pData->hMod, pszFilename, pData->pszModName, pData->fFlags); 663 } 664 665 666 /** 667 * Load symbols from an executable module into the specified address space. 668 * 669 * If an module exist at the specified address it will be replaced by this 670 * call, otherwise a new module is created. 671 * 672 * @returns VBox status code. 673 * 674 * @param pVM The VM handle. 675 * @param hDbgAs The address space. 676 * @param pszFilename The filename of the executable module. 677 * @param pszModName The module name. If NULL, then then the file name 678 * base is used (no extension or nothing). 679 * @param pModAddress The load address of the module. 680 * @param iModSeg The segment to load, pass NIL_RTDBGSEGIDX to load 681 * the whole image. 682 * @param fFlags Flags reserved for future extensions, must be 0. 683 */ 684 VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags) 685 { 686 /* 687 * Validate input 688 */ 689 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 690 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER); 691 AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); 692 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); 693 RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); 694 if (hRealAS == NIL_RTDBGAS) 695 return VERR_INVALID_HANDLE; 696 697 /* 698 * Do the work. 699 */ 700 DBGFR3ASLOADOPENDATA Data; 701 Data.pszModName = pszModName; 702 Data.uSubtrahend = 0; 703 Data.fFlags = 0; 704 Data.hMod = NIL_RTDBGMOD; 705 int rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_IMAGE_PATH", dbgfR3AsLoadImageOpen, &Data); 706 if (RT_FAILURE(rc)) 707 rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadImageOpen, &Data); 708 if (RT_SUCCESS(rc)) 709 { 710 rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0); 711 if (RT_FAILURE(rc)) 712 RTDbgModRelease(Data.hMod); 713 } 714 715 RTDbgAsRelease(hRealAS); 716 return rc; 717 } 718 719 720 /** 721 * Callback function used by DBGFR3AsLoadMap. 722 * 723 * @returns VBox status code. 724 * @param pszFilename The filename under evaluation. 725 * @param pvUser Use arguments (DBGFR3ASLOADOPENDATA). 726 */ 727 static DECLCALLBACK(int) dbgfR3AsLoadMapOpen(const char *pszFilename, void *pvUser) 728 { 729 DBGFR3ASLOADOPENDATA *pData = (DBGFR3ASLOADOPENDATA *)pvUser; 730 return RTDbgModCreateFromMap(&pData->hMod, pszFilename, pData->pszModName, pData->uSubtrahend, pData->fFlags); 731 } 732 733 734 /** 735 * Load symbols from a map file into a module at the specified address space. 736 * 737 * If an module exist at the specified address it will be replaced by this 738 * call, otherwise a new module is created. 739 * 740 * @returns VBox status code. 741 * 742 * @param pVM The VM handle. 743 * @param hDbgAs The address space. 744 * @param pszFilename The map file. 745 * @param pszModName The module name. If NULL, then then the file name 746 * base is used (no extension or nothing). 747 * @param pModAddress The load address of the module. 748 * @param iModSeg The segment to load, pass NIL_RTDBGSEGIDX to load 749 * the whole image. 750 * @param uSubtrahend Value to to subtract from the symbols in the map 751 * file. This is useful for the linux System.map and 752 * /proc/kallsyms. 753 * @param fFlags Flags reserved for future extensions, must be 0. 754 */ 755 VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, 756 PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags) 757 { 758 /* 759 * Validate input 760 */ 761 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 762 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER); 763 AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); 764 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); 765 RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); 766 if (hRealAS == NIL_RTDBGAS) 767 return VERR_INVALID_HANDLE; 768 769 /* 770 * Do the work. 771 */ 772 DBGFR3ASLOADOPENDATA Data; 773 Data.pszModName = pszModName; 774 Data.uSubtrahend = uSubtrahend; 775 Data.fFlags = 0; 776 Data.hMod = NIL_RTDBGMOD; 777 int rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_MAP_PATH", dbgfR3AsLoadImageOpen, &Data); 778 if (RT_FAILURE(rc)) 779 rc = dbgfR3AsSearchEnvPath(pszFilename, "VBOXDBG_PATH", dbgfR3AsLoadImageOpen, &Data); 780 if (RT_SUCCESS(rc)) 781 { 782 rc = DBGFR3AsLinkModule(pVM, hRealAS, Data.hMod, pModAddress, iModSeg, 0); 783 if (RT_FAILURE(rc)) 784 RTDbgModRelease(Data.hMod); 785 } 786 787 RTDbgAsRelease(hRealAS); 788 return rc; 789 } 790 791 792 /** 793 * Wrapper around RTDbgAsModuleLink, RTDbgAsModuleLinkSeg and DBGFR3AsResolve. 794 * 795 * @returns VBox status code. 796 * @param pVM The VM handle. 797 * @param hDbgAs The address space handle. 798 * @param hMod The module handle. 799 * @param pModAddress The link address. 800 * @param iModSeg The segment to link, NIL_RTDBGSEGIDX for the entire image. 801 * @param fFlags Flags to pass to the link functions, see RTDBGASLINK_FLAGS_*. 802 */ 803 VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags) 804 { 805 /* 806 * Input validation. 807 */ 808 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 809 AssertReturn(DBGFR3AddrIsValid(pVM, pModAddress), VERR_INVALID_PARAMETER); 810 RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs); 811 if (hRealAS == NIL_RTDBGAS) 812 return VERR_INVALID_HANDLE; 813 814 /* 815 * Do the job. 816 */ 817 int rc; 818 if (iModSeg == NIL_RTDBGSEGIDX) 819 rc = RTDbgAsModuleLink(hRealAS, hMod, pModAddress->FlatPtr, fFlags); 820 else 821 rc = RTDbgAsModuleLinkSeg(hRealAS, hMod, iModSeg, pModAddress->FlatPtr, fFlags); 822 823 RTDbgAsRelease(hRealAS); 824 return rc; 825 } 826 -
trunk/src/VBox/VMM/DBGFInternal.h
r19286 r19757 262 262 DBGFBP aBreakpoints[32]; 263 263 264 /** The address space database lock. */ 265 RTSEMRW hAsDbLock; 266 /** The address space handle database. (Protected by hAsDbLock.) */ 267 R3PTRTYPE(AVLPVTREE) AsHandleTree; 268 /** The address space process id database. (Protected by hAsDbLock.) */ 269 R3PTRTYPE(AVLU32TREE) AsPidTree; 270 /** The address space name database. (Protected by hAsDbLock.) */ 271 R3PTRTYPE(RTSTRSPACE) AsNameSpace; 272 /** Special address space aliases. (Protected by hAsDbLock.) */ 273 RTDBGAS volatile ahAsAliases[DBGF_AS_COUNT]; 274 264 275 /** The current Guest OS digger. */ 265 276 R3PTRTYPE(PDBGFOS) pCurOS; … … 300 311 301 312 302 extern int dbgfR3InfoInit(PVM pVM); 303 extern int dbgfR3InfoTerm(PVM pVM); 304 extern void dbgfR3OSTerm(PVM pVM); 305 extern int dbgfR3SymInit(PVM pVM); 306 extern int dbgfR3SymTerm(PVM pVM); 307 extern int dbgfR3BpInit(PVM pVM); 313 int dbgfR3AsInit(PVM pVM); 314 void dbgfR3AsTerm(PVM pVM); 315 void dbgfR3AsRelocate(PVM pVM, RTGCUINTPTR offDelta); 316 int dbgfR3InfoInit(PVM pVM); 317 int dbgfR3InfoTerm(PVM pVM); 318 void dbgfR3OSTerm(PVM pVM); 319 int dbgfR3SymInit(PVM pVM); 320 int dbgfR3SymTerm(PVM pVM); 321 int dbgfR3BpInit(PVM pVM); 308 322 309 323 -
trunk/src/VBox/VMM/DBGFModule.cpp
r12677 r19757 38 38 */ 39 39 40 40 #if 0 41 #include <VBox/dbgf.h> 42 43 44 /** Special segment number that indicates that the offset is a relative 45 * virtual address (RVA). I.e. an offset from the start of the module. */ 46 #define DBGF_SEG_RVA UINT32_C(0xfffffff0) 47 48 /** @defgroup grp_dbgf_dbginfo Debug Info Types 49 * @{ */ 50 /** Other format. */ 51 #define DBGF_DBGINFO_OTHER RT_BIT_32(0) 52 /** Stabs. */ 53 #define DBGF_DBGINFO_STABS RT_BIT_32(1) 54 /** Debug With Arbitrary Record Format (DWARF). */ 55 #define DBGF_DBGINFO_DWARF RT_BIT_32(2) 56 /** Microsoft Codeview debug info. */ 57 #define DBGF_DBGINFO_CODEVIEW RT_BIT_32(3) 58 /** Watcom debug info. */ 59 #define DBGF_DBGINFO_WATCOM RT_BIT_32(4) 60 /** IBM High Level Language debug info. */ 61 #define DBGF_DBGINFO_HLL RT_BIT_32(5) 62 /** Old OS/2 and Windows symbol file. */ 63 #define DBGF_DBGINFO_SYM RT_BIT_32(6) 64 /** Map file. */ 65 #define DBGF_DBGINFO_MAP RT_BIT_32(7) 66 /** @} */ 67 68 /** @defgroup grp_dbgf_exeimg Executable Image Types 69 * @{ */ 70 /** Some other format. */ 71 #define DBGF_EXEIMG_OTHER RT_BIT_32(0) 72 /** Portable Executable. */ 73 #define DBGF_EXEIMG_PE RT_BIT_32(1) 74 /** Linear eXecutable. */ 75 #define DBGF_EXEIMG_LX RT_BIT_32(2) 76 /** Linear Executable. */ 77 #define DBGF_EXEIMG_LE RT_BIT_32(3) 78 /** New Executable. */ 79 #define DBGF_EXEIMG_NE RT_BIT_32(4) 80 /** DOS Executable (Mark Zbikowski). */ 81 #define DBGF_EXEIMG_MZ RT_BIT_32(5) 82 /** COM Executable. */ 83 #define DBGF_EXEIMG_COM RT_BIT_32(6) 84 /** a.out Executable. */ 85 #define DBGF_EXEIMG_AOUT RT_BIT_32(7) 86 /** Executable and Linkable Format. */ 87 #define DBGF_EXEIMG_ELF RT_BIT_32(8) 88 /** Mach-O Executable (including FAT ones). */ 89 #define DBGF_EXEIMG_MACHO RT_BIT_32(9) 90 /** @} */ 91 92 /** Pointer to a module. */ 93 typedef struct DBGFMOD *PDBGFMOD; 94 95 96 /** 97 * Virtual method table for executable image interpreters. 98 */ 99 typedef struct DBGFMODVTIMG 100 { 101 /** Magic number (DBGFMODVTIMG_MAGIC). */ 102 uint32_t u32Magic; 103 /** Mask of supported debug info types, see grp_dbgf_exeimg. 104 * Used to speed up the search for a suitable interpreter. */ 105 uint32_t fSupports; 106 /** The name of the interpreter. */ 107 const char *pszName; 108 109 /** 110 * Try open the image. 111 * 112 * This combines probing and opening. 113 * 114 * @returns VBox status code. No informational returns defined. 115 * 116 * @param pMod Pointer to the module that is being opened. 117 * 118 * The DBGFMOD::pszDbgFile member will point to 119 * the filename of any debug info we're aware of 120 * on input. Also, or alternatively, it is expected 121 * that the interpreter will look for debug info in 122 * the executable image file when present and that it 123 * may ask the image interpreter for this when it's 124 * around. 125 * 126 * Upon successful return the method is expected to 127 * initialize pDbgOps and pvDbgPriv. 128 */ 129 DECLCALLBACKMEMBER(int, pfnTryOpen)(PDBGFMOD pMod); 130 131 /** 132 * Close the interpreter, freeing all associated resources. 133 * 134 * The caller sets the pDbgOps and pvDbgPriv DBGFMOD members 135 * to NULL upon return. 136 * 137 * @param pMod Pointer to the module structure. 138 */ 139 DECLCALLBACKMEMBER(int, pfnClose)(PDBGFMOD pMod); 140 141 } DBGFMODVTIMG 142 143 /** 144 * Virtual method table for debug info interpreters. 145 */ 146 typedef struct DBGFMODVTDBG 147 { 148 /** Magic number (DBGFMODVTDBG_MAGIC). */ 149 uint32_t u32Magic; 150 /** Mask of supported debug info types, see grp_dbgf_dbginfo. 151 * Used to speed up the search for a suitable interpreter. */ 152 uint32_t fSupports; 153 /** The name of the interpreter. */ 154 const char *pszName; 155 156 /** 157 * Try open the image. 158 * 159 * This combines probing and opening. 160 * 161 * @returns VBox status code. No informational returns defined. 162 * 163 * @param pMod Pointer to the module that is being opened. 164 * 165 * The DBGFMOD::pszDbgFile member will point to 166 * the filename of any debug info we're aware of 167 * on input. Also, or alternatively, it is expected 168 * that the interpreter will look for debug info in 169 * the executable image file when present and that it 170 * may ask the image interpreter for this when it's 171 * around. 172 * 173 * Upon successful return the method is expected to 174 * initialize pDbgOps and pvDbgPriv. 175 */ 176 DECLCALLBACKMEMBER(int, pfnTryOpen)(PDBGFMOD pMod); 177 178 /** 179 * Close the interpreter, freeing all associated resources. 180 * 181 * The caller sets the pDbgOps and pvDbgPriv DBGFMOD members 182 * to NULL upon return. 183 * 184 * @param pMod Pointer to the module structure. 185 */ 186 DECLCALLBACKMEMBER(int, pfnClose)(PDBGFMOD pMod); 187 188 /** 189 * Queries symbol information by symbol name. 190 * 191 * @returns VBox status code. 192 * @retval VINF_SUCCESS on success, no informational status code. 193 * @retval VERR_DBGF_NO_SYMBOLS if there aren't any symbols. 194 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. 195 * 196 * @param pMod Pointer to the module structure. 197 * @param pszSymbol The symbol name. 198 * @para pSymbol Where to store the symbol information. 199 */ 200 DECLCALLBACKMEMBER(int, pfnSymbolByName)(PDBGFMOD pMod, const char *pszSymbol, PDBGFSYMBOL pSymbol); 201 202 /** 203 * Queries symbol information by address. 204 * 205 * The returned symbol is what the debug info interpreter consideres the symbol 206 * most applicable to the specified address. This usually means a symbol with an 207 * address equal or lower than the requested. 208 * 209 * @returns VBox status code. 210 * @retval VINF_SUCCESS on success, no informational status code. 211 * @retval VERR_DBGF_NO_SYMBOLS if there aren't any symbols. 212 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. 213 * 214 * @param pMod Pointer to the module structure. 215 * @param iSeg The segment number (0-based). DBGF_SEG_RVA can be used. 216 * @param off The offset into the segment. 217 * @param poffDisp Where to store the distance between the specified address 218 * and the returned symbol. Optional. 219 * @param pSymbol Where to store the symbol information. 220 */ 221 DECLCALLBACKMEMBER(int, pfnSymbolByAddr)(PDBGFMOD pMod, uint32_t iSeg, RTGCUINTPTR off, PRTGCINTPTR poffDisp, PDBGFSYMBOL pSymbol); 222 223 /** 224 * Queries line number information by address. 225 * 226 * @returns VBox status code. 227 * @retval VINF_SUCCESS on success, no informational status code. 228 * @retval VERR_DBGF_NO_LINE_NUMBERS if there aren't any line numbers. 229 * @retval VERR_DBGF_LINE_NOT_FOUND if no suitable line number was found. 230 * 231 * @param pMod Pointer to the module structure. 232 * @param iSeg The segment number (0-based). DBGF_SEG_RVA can be used. 233 * @param off The offset into the segment. 234 * @param poffDisp Where to store the distance between the specified address 235 * and the returned line number. Optional. 236 * @param pLine Where to store the information about the closest line number. 237 */ 238 DECLCALLBACKMEMBER(int, pfnLineByAddr)(PDBGFMOD pMod, uint32_t iSeg, RTGCUINTPTR off, PRTGCINTPTR poffDisp, PDBGFLINE pLine); 239 240 /** 241 * Adds a symbol to the module (optional). 242 * 243 * This method is used to implement DBGFR3SymbolAdd. 244 * 245 * @returns VBox status code. 246 * @retval VERR_NOT_SUPPORTED if the interpreter doesn't support this feature. 247 * 248 * @param pMod Pointer to the module structure. 249 * @param pszSymbol The symbol name. 250 * @param iSeg The segment number (0-based). DBGF_SEG_RVA can be used. 251 * @param off The offset into the segment. 252 * @param cbSymbol The area covered by the symbol. 0 is fine. 253 */ 254 DECLCALLBACKMEMBER(int, pfnSymbolAdd)(PDBGFMOD pMod, const char *pszSymbol, uint32_t iSeg, RTGCUINTPTR off, RTUINT cbSymbol); 255 256 /** For catching initialization errors (DBGFMODVTDBG_MAGIC). */ 257 uint32_t u32EndMagic; 258 } DBGFMODVTDBG; 259 260 #define DBGFMODVTDBG_MAGIC 123 261 262 /** 263 * Module. 264 */ 265 typedef struct DBGFMOD 266 { 267 /** Magic value (DBGFMOD_MAGIC). */ 268 uint32_t u32Magic; 269 /** The number of address spaces this module is currently linked into. 270 * This is used to perform automatic cleanup and sharing. */ 271 uint32_t cLinks; 272 /** The module name (short). */ 273 const char *pszName; 274 /** The module filename. Can be NULL. */ 275 const char *pszImgFile; 276 /** The debug info file (if external). Can be NULL. */ 277 const char *pszDbgFile; 278 279 /** The method table for the executable image interpreter. */ 280 PCDBGFMODVTIMG pImgVt; 281 /** Pointer to the private data of the executable image interpreter. */ 282 void *pvImgPriv; 283 284 /** The method table for the debug info interpreter. */ 285 PCDBGFMODVTDBG pDbgVt; 286 /** Pointer to the private data of the debug info interpreter. */ 287 void *pvDbgPriv; 288 289 } DBGFMOD; 290 291 #define DBGFMOD_MAGIC 0x12345678 292 293 #endif 294 -
trunk/src/VBox/VMM/MMHeap.cpp
r18287 r19757 719 719 720 720 TAG2STR(DBGF); 721 TAG2STR(DBGF_AS); 721 722 TAG2STR(DBGF_INFO); 722 723 TAG2STR(DBGF_LINE); -
trunk/src/VBox/VMM/Makefile.kmk
r19297 r19757 53 53 DBGF.cpp \ 54 54 DBGFAddr.cpp \ 55 DBGFAddrSpace.cpp \ 55 56 DBGFBp.cpp \ 56 57 DBGFDisas.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.