VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgas.cpp

Last change on this file was 99775, checked in by vboxsync, 12 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.8 KB
Line 
1/* $Id: dbgas.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * IPRT - Debug Address Space.
4 */
5
6/*
7 * Copyright (C) 2009-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/dbg.h>
42#include "internal/iprt.h"
43
44#include <iprt/asm.h>
45#include <iprt/avl.h>
46#include <iprt/assert.h>
47#include <iprt/err.h>
48#include <iprt/mem.h>
49#include <iprt/param.h>
50#include <iprt/string.h>
51#include <iprt/semaphore.h>
52#include "internal/magics.h"
53
54
55/*********************************************************************************************************************************
56* Structures and Typedefs *
57*********************************************************************************************************************************/
58/** Pointer to a module table entry. */
59typedef struct RTDBGASMOD *PRTDBGASMOD;
60/** Pointer to an address space mapping node. */
61typedef struct RTDBGASMAP *PRTDBGASMAP;
62/** Pointer to a name head. */
63typedef struct RTDBGASNAME *PRTDBGASNAME;
64
65/**
66 * Module entry.
67 */
68typedef struct RTDBGASMOD
69{
70 /** Node core, the module handle is the key. */
71 AVLPVNODECORE Core;
72 /** Pointer to the first mapping of the module or a segment within it. */
73 PRTDBGASMAP pMapHead;
74 /** Pointer to the next module with an identical name. */
75 PRTDBGASMOD pNextName;
76 /** The index into RTDBGASINT::papModules. */
77 uint32_t iOrdinal;
78} RTDBGASMOD;
79
80/**
81 * An address space mapping, either of a full module or a segment.
82 */
83typedef struct RTDBGASMAP
84{
85 /** The AVL node core. Contains the address range. */
86 AVLRUINTPTRNODECORE Core;
87 /** Pointer to the next mapping of the module. */
88 PRTDBGASMAP pNext;
89 /** Pointer to the module. */
90 PRTDBGASMOD pMod;
91 /** Which segment in the module.
92 * This is NIL_RTDBGSEGIDX when the entire module is mapped. */
93 RTDBGSEGIDX iSeg;
94} RTDBGASMAP;
95
96/**
97 * Name in the address space.
98 */
99typedef struct RTDBGASNAME
100{
101 /** The string space node core.*/
102 RTSTRSPACECORE StrCore;
103 /** The list of nodes */
104 PRTDBGASMOD pHead;
105} RTDBGASNAME;
106
107/**
108 * Debug address space instance.
109 */
110typedef struct RTDBGASINT
111{
112 /** Magic value (RTDBGAS_MAGIC). */
113 uint32_t u32Magic;
114 /** The number of reference to this address space. */
115 uint32_t volatile cRefs;
116 /** Handle of the read-write lock. */
117 RTSEMRW hLock;
118 /** Number of modules in the module address space. */
119 uint32_t cModules;
120 /** Pointer to the module table.
121 * The valid array length is given by cModules. */
122 PRTDBGASMOD *papModules;
123 /** AVL tree translating module handles to module entries. */
124 AVLPVTREE ModTree;
125 /** AVL tree mapping addresses to modules. */
126 AVLRUINTPTRTREE MapTree;
127 /** Names of the modules in the name space. */
128 RTSTRSPACE NameSpace;
129 /** The first address the AS. */
130 RTUINTPTR FirstAddr;
131 /** The last address in the AS. */
132 RTUINTPTR LastAddr;
133 /** The name of the address space. (variable length) */
134 char szName[1];
135} RTDBGASINT;
136/** Pointer to an a debug address space instance. */
137typedef RTDBGASINT *PRTDBGASINT;
138
139
140/*********************************************************************************************************************************
141* Defined Constants And Macros *
142*********************************************************************************************************************************/
143/** Validates an address space handle and returns rc if not valid. */
144#define RTDBGAS_VALID_RETURN_RC(pDbgAs, rc) \
145 do { \
146 AssertPtrReturn((pDbgAs), (rc)); \
147 AssertReturn((pDbgAs)->u32Magic == RTDBGAS_MAGIC, (rc)); \
148 AssertReturn((pDbgAs)->cRefs > 0, (rc)); \
149 } while (0)
150
151/** Locks the address space for reading. */
152#define RTDBGAS_LOCK_READ(pDbgAs) \
153 do { \
154 int rcLock = RTSemRWRequestRead((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \
155 AssertRC(rcLock); \
156 } while (0)
157
158/** Unlocks the address space after reading. */
159#define RTDBGAS_UNLOCK_READ(pDbgAs) \
160 do { \
161 int rcLock = RTSemRWReleaseRead((pDbgAs)->hLock); \
162 AssertRC(rcLock); \
163 } while (0)
164
165/** Locks the address space for writing. */
166#define RTDBGAS_LOCK_WRITE(pDbgAs) \
167 do { \
168 int rcLock = RTSemRWRequestWrite((pDbgAs)->hLock, RT_INDEFINITE_WAIT); \
169 AssertRC(rcLock); \
170 } while (0)
171
172/** Unlocks the address space after writing. */
173#define RTDBGAS_UNLOCK_WRITE(pDbgAs) \
174 do { \
175 int rcLock = RTSemRWReleaseWrite((pDbgAs)->hLock); \
176 AssertRC(rcLock); \
177 } while (0)
178
179
180/*********************************************************************************************************************************
181* Internal Functions *
182*********************************************************************************************************************************/
183static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod);
184static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap);
185
186
187RTDECL(int) RTDbgAsCreate(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszName)
188{
189 /*
190 * Input validation.
191 */
192 AssertPtrReturn(phDbgAs, VERR_INVALID_POINTER);
193 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
194 AssertReturn(FirstAddr < LastAddr, VERR_INVALID_PARAMETER);
195
196 /*
197 * Allocate memory for the instance data.
198 */
199 size_t cchName = strlen(pszName);
200 PRTDBGASINT pDbgAs = (PRTDBGASINT)RTMemAllocVar(RT_UOFFSETOF_DYN(RTDBGASINT, szName[cchName + 1]));
201 if (!pDbgAs)
202 return VERR_NO_MEMORY;
203
204 /* initialize it. */
205 pDbgAs->u32Magic = RTDBGAS_MAGIC;
206 pDbgAs->cRefs = 1;
207 pDbgAs->hLock = NIL_RTSEMRW;
208 pDbgAs->cModules = 0;
209 pDbgAs->papModules = NULL;
210 pDbgAs->ModTree = NULL;
211 pDbgAs->MapTree = NULL;
212 pDbgAs->NameSpace = NULL;
213 pDbgAs->FirstAddr = FirstAddr;
214 pDbgAs->LastAddr = LastAddr;
215 memcpy(pDbgAs->szName, pszName, cchName + 1);
216 int rc = RTSemRWCreate(&pDbgAs->hLock);
217 if (RT_SUCCESS(rc))
218 {
219 *phDbgAs = pDbgAs;
220 return VINF_SUCCESS;
221 }
222
223 pDbgAs->u32Magic = 0;
224 RTMemFree(pDbgAs);
225 return rc;
226}
227RT_EXPORT_SYMBOL(RTDbgAsCreate);
228
229
230RTDECL(int) RTDbgAsCreateV(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszNameFmt, va_list va)
231{
232 AssertPtrReturn(pszNameFmt, VERR_INVALID_POINTER);
233
234 char *pszName;
235 RTStrAPrintfV(&pszName, pszNameFmt, va);
236 if (!pszName)
237 return VERR_NO_MEMORY;
238
239 int rc = RTDbgAsCreate(phDbgAs, FirstAddr, LastAddr, pszName);
240
241 RTStrFree(pszName);
242 return rc;
243}
244RT_EXPORT_SYMBOL(RTDbgAsCreateV);
245
246
247RTDECL(int) RTDbgAsCreateF(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszNameFmt, ...)
248{
249 va_list va;
250 va_start(va, pszNameFmt);
251 int rc = RTDbgAsCreateV(phDbgAs, FirstAddr, LastAddr, pszNameFmt, va);
252 va_end(va);
253 return rc;
254}
255RT_EXPORT_SYMBOL(RTDbgAsCreateF);
256
257
258/**
259 * Callback used by RTDbgAsDestroy to free all mapping nodes.
260 *
261 * @returns 0
262 * @param pNode The map node.
263 * @param pvUser NULL.
264 */
265static DECLCALLBACK(int) rtDbgAsDestroyMapCallback(PAVLRUINTPTRNODECORE pNode, void *pvUser)
266{
267 RTMemFree(pNode);
268 NOREF(pvUser);
269 return 0;
270}
271
272
273/**
274 * Callback used by RTDbgAsDestroy to free all name space nodes.
275 *
276 * @returns 0
277 * @param pStr The name node.
278 * @param pvUser NULL.
279 */
280static DECLCALLBACK(int) rtDbgAsDestroyNameCallback(PRTSTRSPACECORE pStr, void *pvUser)
281{
282 RTMemFree(pStr);
283 NOREF(pvUser);
284 return 0;
285}
286
287
288/**
289 * Destroys the address space.
290 *
291 * This means unlinking all the modules it currently contains, potentially
292 * causing some or all of them to be destroyed as they are managed by
293 * reference counting.
294 *
295 * @param pDbgAs The address space instance to be destroyed.
296 */
297static void rtDbgAsDestroy(PRTDBGASINT pDbgAs)
298{
299 /*
300 * Mark the address space invalid and release all the modules.
301 */
302 ASMAtomicWriteU32(&pDbgAs->u32Magic, ~RTDBGAS_MAGIC);
303
304 RTAvlrUIntPtrDestroy(&pDbgAs->MapTree, rtDbgAsDestroyMapCallback, NULL);
305 RTStrSpaceDestroy(&pDbgAs->NameSpace, rtDbgAsDestroyNameCallback, NULL);
306
307 uint32_t i = pDbgAs->cModules;
308 while (i-- > 0)
309 {
310 PRTDBGASMOD pMod = pDbgAs->papModules[i];
311 AssertPtr(pMod);
312 if (RT_VALID_PTR(pMod))
313 {
314 Assert(pMod->iOrdinal == i);
315 RTDbgModRelease((RTDBGMOD)pMod->Core.Key);
316 pMod->Core.Key = NIL_RTDBGMOD;
317 pMod->iOrdinal = UINT32_MAX;
318 RTMemFree(pMod);
319 }
320 pDbgAs->papModules[i] = NULL;
321 }
322 RTSemRWDestroy(pDbgAs->hLock);
323 pDbgAs->hLock = NIL_RTSEMRW;
324 RTMemFree(pDbgAs->papModules);
325 pDbgAs->papModules = NULL;
326
327 RTMemFree(pDbgAs);
328}
329
330
331RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs)
332{
333 PRTDBGASINT pDbgAs = hDbgAs;
334 RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX);
335 return ASMAtomicIncU32(&pDbgAs->cRefs);
336}
337RT_EXPORT_SYMBOL(RTDbgAsRetain);
338
339
340RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs)
341{
342 if (hDbgAs == NIL_RTDBGAS)
343 return 0;
344 PRTDBGASINT pDbgAs = hDbgAs;
345 RTDBGAS_VALID_RETURN_RC(pDbgAs, UINT32_MAX);
346
347 uint32_t cRefs = ASMAtomicDecU32(&pDbgAs->cRefs);
348 if (!cRefs)
349 rtDbgAsDestroy(pDbgAs);
350 return cRefs;
351}
352RT_EXPORT_SYMBOL(RTDbgAsRelease);
353
354
355RTDECL(int) RTDbgAsLockExcl(RTDBGAS hDbgAs)
356{
357 PRTDBGASINT pDbgAs = hDbgAs;
358 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
359 RTDBGAS_LOCK_WRITE(pDbgAs);
360 return VINF_SUCCESS;
361}
362RT_EXPORT_SYMBOL(RTDbgAsLockExcl);
363
364
365RTDECL(int) RTDbgAsUnlockExcl(RTDBGAS hDbgAs)
366{
367 PRTDBGASINT pDbgAs = hDbgAs;
368 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
369 RTDBGAS_UNLOCK_WRITE(pDbgAs);
370 return VINF_SUCCESS;
371}
372RT_EXPORT_SYMBOL(RTDbgAsUnlockExcl);
373
374
375RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs)
376{
377 PRTDBGASINT pDbgAs = hDbgAs;
378 RTDBGAS_VALID_RETURN_RC(pDbgAs, NULL);
379 return pDbgAs->szName;
380}
381RT_EXPORT_SYMBOL(RTDbgAsName);
382
383
384RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs)
385{
386 PRTDBGASINT pDbgAs = hDbgAs;
387 RTDBGAS_VALID_RETURN_RC(pDbgAs, 0);
388 return pDbgAs->FirstAddr;
389}
390RT_EXPORT_SYMBOL(RTDbgAsFirstAddr);
391
392
393RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs)
394{
395 PRTDBGASINT pDbgAs = hDbgAs;
396 RTDBGAS_VALID_RETURN_RC(pDbgAs, 0);
397 return pDbgAs->LastAddr;
398}
399RT_EXPORT_SYMBOL(RTDbgAsLastAddr);
400
401
402RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs)
403{
404 PRTDBGASINT pDbgAs = hDbgAs;
405 RTDBGAS_VALID_RETURN_RC(pDbgAs, 0);
406 return pDbgAs->cModules;
407}
408RT_EXPORT_SYMBOL(RTDbgAsModuleCount);
409
410
411/**
412 * Common worker for RTDbgAsModuleLink and RTDbgAsModuleLinkSeg.
413 *
414 * @returns IPRT status code.
415 * @param pDbgAs Pointer to the address space instance data.
416 * @param hDbgMod The module to link.
417 * @param iSeg The segment to link or NIL if all.
418 * @param Addr The address we're linking it at.
419 * @param cb The size of what we're linking.
420 * @param pszName The name of the module.
421 * @param fFlags See RTDBGASLINK_FLAGS_*.
422 *
423 * @remarks The caller must have locked the address space for writing.
424 */
425static int rtDbgAsModuleLinkCommon(PRTDBGASINT pDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg,
426 RTUINTPTR Addr, RTUINTPTR cb, const char *pszName, uint32_t fFlags)
427{
428 /*
429 * Check that the requested space is undisputed.
430 */
431 for (;;)
432 {
433 PRTDBGASMAP pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, false /* fAbove */);
434 if ( pAdjMod
435 && pAdjMod->Core.KeyLast >= Addr)
436 {
437 if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE))
438 return VERR_ADDRESS_CONFLICT;
439 rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod);
440 continue;
441 }
442 pAdjMod = (PRTDBGASMAP)RTAvlrUIntPtrGetBestFit(&pDbgAs->MapTree, Addr, true /* fAbove */);
443 if ( pAdjMod
444 && pAdjMod->Core.Key <= Addr + cb - 1)
445 {
446 if (!(fFlags & RTDBGASLINK_FLAGS_REPLACE))
447 return VERR_ADDRESS_CONFLICT;
448 rtDbgAsModuleUnlinkByMap(pDbgAs, pAdjMod);
449 continue;
450 }
451 break;
452 }
453
454 /*
455 * First, create or find the module table entry.
456 */
457 PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod);
458 if (!pMod)
459 {
460 /*
461 * Ok, we need a new entry. Grow the table if necessary.
462 */
463 if (!(pDbgAs->cModules % 32))
464 {
465 void *pvNew = RTMemRealloc(pDbgAs->papModules, sizeof(pDbgAs->papModules[0]) * (pDbgAs->cModules + 32));
466 if (!pvNew)
467 return VERR_NO_MEMORY;
468 pDbgAs->papModules = (PRTDBGASMOD *)pvNew;
469 }
470 pMod = (PRTDBGASMOD)RTMemAlloc(sizeof(*pMod));
471 if (!pMod)
472 return VERR_NO_MEMORY;
473 pMod->Core.Key = hDbgMod;
474 pMod->pMapHead = NULL;
475 pMod->pNextName = NULL;
476 if (RT_UNLIKELY(!RTAvlPVInsert(&pDbgAs->ModTree, &pMod->Core)))
477 {
478 AssertFailed();
479 pDbgAs->cModules--;
480 RTMemFree(pMod);
481 return VERR_INTERNAL_ERROR;
482 }
483 pMod->iOrdinal = pDbgAs->cModules;
484 pDbgAs->papModules[pDbgAs->cModules] = pMod;
485 pDbgAs->cModules++;
486 RTDbgModRetain(hDbgMod);
487
488 /*
489 * Add it to the name space.
490 */
491 PRTDBGASNAME pName = (PRTDBGASNAME)RTStrSpaceGet(&pDbgAs->NameSpace, pszName);
492 if (!pName)
493 {
494 size_t cchName = strlen(pszName);
495 pName = (PRTDBGASNAME)RTMemAlloc(sizeof(*pName) + cchName + 1);
496 if (!pName)
497 {
498 RTDbgModRelease(hDbgMod);
499 pDbgAs->cModules--;
500 RTAvlPVRemove(&pDbgAs->ModTree, hDbgMod);
501 RTMemFree(pMod);
502 return VERR_NO_MEMORY;
503 }
504 pName->StrCore.cchString = cchName;
505 pName->StrCore.pszString = (char *)memcpy(pName + 1, pszName, cchName + 1);
506 pName->pHead = pMod;
507 if (!RTStrSpaceInsert(&pDbgAs->NameSpace, &pName->StrCore))
508 AssertFailed();
509 }
510 else
511 {
512 /* quick, but unfair. */
513 pMod->pNextName = pName->pHead;
514 pName->pHead = pMod;
515 }
516 }
517
518 /*
519 * Create a mapping node.
520 */
521 int rc;
522 PRTDBGASMAP pMap = (PRTDBGASMAP)RTMemAlloc(sizeof(*pMap));
523 if (pMap)
524 {
525 pMap->Core.Key = Addr;
526 pMap->Core.KeyLast = Addr + cb - 1;
527 pMap->pMod = pMod;
528 pMap->iSeg = iSeg;
529 if (RTAvlrUIntPtrInsert(&pDbgAs->MapTree, &pMap->Core))
530 {
531 PRTDBGASMAP *pp = &pMod->pMapHead;
532 while (*pp && (*pp)->Core.Key < Addr)
533 pp = &(*pp)->pNext;
534 pMap->pNext = *pp;
535 *pp = pMap;
536 return VINF_SUCCESS;
537 }
538
539 AssertFailed();
540 RTMemFree(pMap);
541 rc = VERR_ADDRESS_CONFLICT;
542 }
543 else
544 rc = VERR_NO_MEMORY;
545
546 /*
547 * Unlink the module if this was the only mapping.
548 */
549 if (!pMod->pMapHead)
550 rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
551 return rc;
552}
553
554
555RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags)
556{
557 /*
558 * Validate input.
559 */
560 PRTDBGASINT pDbgAs = hDbgAs;
561 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
562 const char *pszName = RTDbgModName(hDbgMod);
563 if (!pszName)
564 return VERR_INVALID_HANDLE;
565 RTUINTPTR cb = RTDbgModImageSize(hDbgMod);
566 if (!cb)
567 return VERR_OUT_OF_RANGE;
568 if ( ImageAddr < pDbgAs->FirstAddr
569 || ImageAddr > pDbgAs->LastAddr
570 || ImageAddr + cb - 1 < pDbgAs->FirstAddr
571 || ImageAddr + cb - 1 > pDbgAs->LastAddr
572 || ImageAddr + cb - 1 < ImageAddr)
573 return VERR_OUT_OF_RANGE;
574 AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
575
576 /*
577 * Invoke worker common with RTDbgAsModuleLinkSeg.
578 */
579 RTDBGAS_LOCK_WRITE(pDbgAs);
580 int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, NIL_RTDBGSEGIDX, ImageAddr, cb, pszName, fFlags);
581 RTDBGAS_UNLOCK_WRITE(pDbgAs);
582 return rc;
583}
584RT_EXPORT_SYMBOL(RTDbgAsModuleLink);
585
586
587RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags)
588{
589 /*
590 * Validate input.
591 */
592 PRTDBGASINT pDbgAs = hDbgAs;
593 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
594 const char *pszName = RTDbgModName(hDbgMod);
595 if (!pszName)
596 return VERR_INVALID_HANDLE;
597 RTUINTPTR cb = RTDbgModSegmentSize(hDbgMod, iSeg);
598 if (!cb)
599 return VERR_OUT_OF_RANGE;
600 if ( SegAddr < pDbgAs->FirstAddr
601 || SegAddr > pDbgAs->LastAddr
602 || SegAddr + cb - 1 < pDbgAs->FirstAddr
603 || SegAddr + cb - 1 > pDbgAs->LastAddr
604 || SegAddr + cb - 1 < SegAddr)
605 return VERR_OUT_OF_RANGE;
606 AssertReturn(!(fFlags & ~RTDBGASLINK_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
607
608 /*
609 * Invoke worker common with RTDbgAsModuleLinkSeg.
610 */
611 RTDBGAS_LOCK_WRITE(pDbgAs);
612 int rc = rtDbgAsModuleLinkCommon(pDbgAs, hDbgMod, iSeg, SegAddr, cb, pszName, fFlags);
613 RTDBGAS_UNLOCK_WRITE(pDbgAs);
614 return rc;
615}
616RT_EXPORT_SYMBOL(RTDbgAsModuleLinkSeg);
617
618
619/**
620 * Worker for RTDbgAsModuleUnlink, RTDbgAsModuleUnlinkByAddr and rtDbgAsModuleLinkCommon.
621 *
622 * @param pDbgAs Pointer to the address space instance data.
623 * @param pMod The module to unlink.
624 *
625 * @remarks The caller must have locked the address space for writing.
626 */
627static void rtDbgAsModuleUnlinkMod(PRTDBGASINT pDbgAs, PRTDBGASMOD pMod)
628{
629 Assert(!pMod->pMapHead);
630
631 /*
632 * Unlink it from the name.
633 */
634 const char *pszName = RTDbgModName((RTDBGMOD)pMod->Core.Key);
635 PRTDBGASNAME pName = (PRTDBGASNAME)RTStrSpaceGet(&pDbgAs->NameSpace, pszName);
636 AssertReturnVoid(pName);
637
638 if (pName->pHead == pMod)
639 pName->pHead = pMod->pNextName;
640 else
641 for (PRTDBGASMOD pCur = pName->pHead; pCur; pCur = pCur->pNextName)
642 if (pCur->pNextName == pMod)
643 {
644 pCur->pNextName = pMod->pNextName;
645 break;
646 }
647 pMod->pNextName = NULL;
648
649 /*
650 * Free the name if this was the last reference to it.
651 */
652 if (!pName->pHead)
653 {
654 pName = (PRTDBGASNAME)RTStrSpaceRemove(&pDbgAs->NameSpace, pName->StrCore.pszString);
655 Assert(pName);
656 RTMemFree(pName);
657 }
658
659 /*
660 * Remove it from the module handle tree.
661 */
662 PAVLPVNODECORE pNode = RTAvlPVRemove(&pDbgAs->ModTree, pMod->Core.Key);
663 Assert(pNode == &pMod->Core); NOREF(pNode);
664
665 /*
666 * Remove it from the module table by replacing it by the last entry.
667 */
668 pDbgAs->cModules--;
669 uint32_t iMod = pMod->iOrdinal;
670 Assert(iMod <= pDbgAs->cModules);
671 if (iMod != pDbgAs->cModules)
672 {
673 PRTDBGASMOD pTailMod = pDbgAs->papModules[pDbgAs->cModules];
674 pTailMod->iOrdinal = iMod;
675 pDbgAs->papModules[iMod] = pTailMod;
676 }
677 pMod->iOrdinal = UINT32_MAX;
678
679 /*
680 * Free it.
681 */
682 RTMemFree(pMod);
683}
684
685
686/**
687 * Worker for RTDbgAsModuleUnlink and RTDbgAsModuleUnlinkByAddr.
688 *
689 * @param pDbgAs Pointer to the address space instance data.
690 * @param pMap The map to unlink and free.
691 *
692 * @remarks The caller must have locked the address space for writing.
693 */
694static void rtDbgAsModuleUnlinkMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap)
695{
696 /* remove from the tree */
697 PAVLRUINTPTRNODECORE pNode = RTAvlrUIntPtrRemove(&pDbgAs->MapTree, pMap->Core.Key);
698 Assert(pNode == &pMap->Core); NOREF(pNode);
699
700 /* unlink */
701 PRTDBGASMOD pMod = pMap->pMod;
702 if (pMod->pMapHead == pMap)
703 pMod->pMapHead = pMap->pNext;
704 else
705 {
706 bool fFound = false;
707 for (PRTDBGASMAP pCur = pMod->pMapHead; pCur; pCur = pCur->pNext)
708 if (pCur->pNext == pMap)
709 {
710 pCur->pNext = pMap->pNext;
711 fFound = true;
712 break;
713 }
714 Assert(fFound);
715 }
716
717 /* free it */
718 pMap->Core.Key = pMap->Core.KeyLast = 0;
719 pMap->pNext = NULL;
720 pMap->pMod = NULL;
721 RTMemFree(pMap);
722}
723
724
725/**
726 * Worker for RTDbgAsModuleUnlinkByAddr and rtDbgAsModuleLinkCommon that
727 * unlinks a single mapping and releases the module if it's the last one.
728 *
729 * @param pDbgAs The address space instance.
730 * @param pMap The mapping to unlink.
731 *
732 * @remarks The caller must have locked the address space for writing.
733 */
734static void rtDbgAsModuleUnlinkByMap(PRTDBGASINT pDbgAs, PRTDBGASMAP pMap)
735{
736 /*
737 * Unlink it from the address space.
738 * Unlink the module as well if it's the last mapping it has.
739 */
740 PRTDBGASMOD pMod = pMap->pMod;
741 rtDbgAsModuleUnlinkMap(pDbgAs, pMap);
742 if (!pMod->pMapHead)
743 rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
744}
745
746
747RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod)
748{
749 /*
750 * Validate input.
751 */
752 PRTDBGASINT pDbgAs = hDbgAs;
753 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
754 if (hDbgMod == NIL_RTDBGMOD)
755 return VINF_SUCCESS;
756
757 RTDBGAS_LOCK_WRITE(pDbgAs);
758 PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod);
759 if (!pMod)
760 {
761 RTDBGAS_UNLOCK_WRITE(pDbgAs);
762 return VERR_NOT_FOUND;
763 }
764
765 /*
766 * Unmap all everything and release the module.
767 */
768 while (pMod->pMapHead)
769 rtDbgAsModuleUnlinkMap(pDbgAs, pMod->pMapHead);
770 rtDbgAsModuleUnlinkMod(pDbgAs, pMod);
771
772 RTDBGAS_UNLOCK_WRITE(pDbgAs);
773 return VINF_SUCCESS;
774}
775RT_EXPORT_SYMBOL(RTDbgAsModuleUnlink);
776
777
778RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr)
779{
780 /*
781 * Validate input.
782 */
783 PRTDBGASINT pDbgAs = hDbgAs;
784 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
785
786 RTDBGAS_LOCK_WRITE(pDbgAs);
787 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
788 if (!pMap)
789 {
790 RTDBGAS_UNLOCK_WRITE(pDbgAs);
791 return VERR_NOT_FOUND;
792 }
793
794 /*
795 * Hand it to
796 */
797 rtDbgAsModuleUnlinkByMap(pDbgAs, pMap);
798
799 RTDBGAS_UNLOCK_WRITE(pDbgAs);
800 return VINF_SUCCESS;
801}
802RT_EXPORT_SYMBOL(RTDbgAsModuleUnlinkByAddr);
803
804
805RTDECL(RTDBGMOD) RTDbgAsModuleByIndex(RTDBGAS hDbgAs, uint32_t iModule)
806{
807 /*
808 * Validate input.
809 */
810 PRTDBGASINT pDbgAs = hDbgAs;
811 RTDBGAS_VALID_RETURN_RC(pDbgAs, NIL_RTDBGMOD);
812
813 RTDBGAS_LOCK_READ(pDbgAs);
814 if (iModule >= pDbgAs->cModules)
815 {
816 RTDBGAS_UNLOCK_READ(pDbgAs);
817 return NIL_RTDBGMOD;
818 }
819
820 /*
821 * Get, retain and return it.
822 */
823 RTDBGMOD hMod = (RTDBGMOD)pDbgAs->papModules[iModule]->Core.Key;
824 RTDbgModRetain(hMod);
825
826 RTDBGAS_UNLOCK_READ(pDbgAs);
827 return hMod;
828}
829RT_EXPORT_SYMBOL(RTDbgAsModuleByIndex);
830
831
832RTDECL(int) RTDbgAsModuleByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTDBGMOD phMod, PRTUINTPTR pAddr, PRTDBGSEGIDX piSeg)
833{
834 /*
835 * Validate input.
836 */
837 PRTDBGASINT pDbgAs = hDbgAs;
838 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
839
840 RTDBGAS_LOCK_READ(pDbgAs);
841 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
842 if (!pMap)
843 {
844 RTDBGAS_UNLOCK_READ(pDbgAs);
845 return VERR_NOT_FOUND;
846 }
847
848 /*
849 * Set up the return values.
850 */
851 if (phMod)
852 {
853 RTDBGMOD hMod = (RTDBGMOD)pMap->pMod->Core.Key;
854 RTDbgModRetain(hMod);
855 *phMod = hMod;
856 }
857 if (pAddr)
858 *pAddr = pMap->Core.Key;
859 if (piSeg)
860 *piSeg = pMap->iSeg;
861
862 RTDBGAS_UNLOCK_READ(pDbgAs);
863 return VINF_SUCCESS;
864}
865RT_EXPORT_SYMBOL(RTDbgAsModuleByAddr);
866
867
868RTDECL(int) RTDbgAsModuleByName(RTDBGAS hDbgAs, const char *pszName, uint32_t iName, PRTDBGMOD phMod)
869{
870 /*
871 * Validate input.
872 */
873 PRTDBGASINT pDbgAs = hDbgAs;
874 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
875 AssertPtrReturn(phMod, VERR_INVALID_POINTER);
876
877 RTDBGAS_LOCK_READ(pDbgAs);
878 PRTDBGASNAME pName = (PRTDBGASNAME)RTStrSpaceGet(&pDbgAs->NameSpace, pszName);
879 if (!pName)
880 {
881 RTDBGAS_UNLOCK_READ(pDbgAs);
882 return VERR_NOT_FOUND;
883 }
884
885 PRTDBGASMOD pMod = pName->pHead;
886 while (iName-- > 0)
887 {
888 pMod = pMod->pNextName;
889 if (!pMod)
890 {
891 RTDBGAS_UNLOCK_READ(pDbgAs);
892 return VERR_OUT_OF_RANGE;
893 }
894 }
895
896 /*
897 * Get, retain and return it.
898 */
899 RTDBGMOD hMod = (RTDBGMOD)pMod->Core.Key;
900 RTDbgModRetain(hMod);
901 *phMod = hMod;
902
903 RTDBGAS_UNLOCK_READ(pDbgAs);
904 return VINF_SUCCESS;
905}
906RT_EXPORT_SYMBOL(RTDbgAsModuleByName);
907
908
909RTDECL(int) RTDbgAsModuleQueryMapByIndex(RTDBGAS hDbgAs, uint32_t iModule, PRTDBGASMAPINFO paMappings, uint32_t *pcMappings, uint32_t fFlags)
910{
911 /*
912 * Validate input.
913 */
914 uint32_t const cMappings = *pcMappings;
915 PRTDBGASINT pDbgAs = hDbgAs;
916 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
917 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
918
919 RTDBGAS_LOCK_READ(pDbgAs);
920 if (iModule >= pDbgAs->cModules)
921 {
922 RTDBGAS_UNLOCK_READ(pDbgAs);
923 return VERR_OUT_OF_RANGE;
924 }
925
926 /*
927 * Copy the mapping information about the module.
928 */
929 int rc = VINF_SUCCESS;
930 PRTDBGASMAP pMap = pDbgAs->papModules[iModule]->pMapHead;
931 uint32_t cMaps = 0;
932 while (pMap)
933 {
934 if (cMaps >= cMappings)
935 {
936 rc = VINF_BUFFER_OVERFLOW;
937 break;
938 }
939 paMappings[cMaps].Address = pMap->Core.Key;
940 paMappings[cMaps].iSeg = pMap->iSeg;
941 cMaps++;
942 pMap = pMap->pNext;
943 }
944
945 RTDBGAS_UNLOCK_READ(pDbgAs);
946 *pcMappings = cMaps;
947 return rc;
948}
949RT_EXPORT_SYMBOL(RTDbgAsModuleQueryMapByIndex);
950
951
952/**
953 * Internal worker that looks up and retains a module.
954 *
955 * @returns Module handle, NIL_RTDBGMOD if not found.
956 * @param pDbgAs The address space instance data.
957 * @param Addr Address within the module.
958 * @param piSeg where to return the segment index.
959 * @param poffSeg Where to return the segment offset.
960 * @param pMapAddr The mapping address (RTDBGASMAP::Core.Key).
961 */
962DECLINLINE(RTDBGMOD) rtDbgAsModuleByAddr(PRTDBGASINT pDbgAs, RTUINTPTR Addr, PRTDBGSEGIDX piSeg, PRTUINTPTR poffSeg, PRTUINTPTR pMapAddr)
963{
964 RTDBGMOD hMod = NIL_RTDBGMOD;
965
966 RTDBGAS_LOCK_READ(pDbgAs);
967 PRTDBGASMAP pMap = (PRTDBGASMAP)RTAvlrUIntPtrRangeGet(&pDbgAs->MapTree, Addr);
968 if (pMap)
969 {
970 hMod = (RTDBGMOD)pMap->pMod->Core.Key;
971 RTDbgModRetain(hMod);
972 *piSeg = pMap->iSeg != NIL_RTDBGSEGIDX ? pMap->iSeg : RTDBGSEGIDX_RVA;
973 *poffSeg = Addr - pMap->Core.Key;
974 if (pMapAddr)
975 *pMapAddr = pMap->Core.Key;
976 }
977 RTDBGAS_UNLOCK_READ(pDbgAs);
978
979 return hMod;
980}
981
982
983/**
984 * Adjusts the address to correspond to the mapping of the module/segment.
985 *
986 * @param pAddr The address to adjust (in/out).
987 * @param iSeg The related segment.
988 * @param hDbgMod The module handle.
989 * @param MapAddr The mapping address.
990 * @param iMapSeg The segment that's mapped, NIL_RTDBGSEGIDX or
991 * RTDBGSEGIDX_RVA if the whole module is mapped here.
992 */
993DECLINLINE(void) rtDbgAsAdjustAddressByMapping(PRTUINTPTR pAddr, RTDBGSEGIDX iSeg,
994 RTDBGMOD hDbgMod, RTUINTPTR MapAddr, RTDBGSEGIDX iMapSeg)
995{
996 if (iSeg == RTDBGSEGIDX_ABS)
997 return;
998
999 if (iSeg == RTDBGSEGIDX_RVA)
1000 {
1001 if ( iMapSeg == RTDBGSEGIDX_RVA
1002 || iMapSeg == NIL_RTDBGSEGIDX)
1003 *pAddr += MapAddr;
1004 else
1005 {
1006 RTUINTPTR SegRva = RTDbgModSegmentRva(hDbgMod, iMapSeg);
1007 AssertReturnVoid(SegRva != RTUINTPTR_MAX);
1008 AssertMsg(SegRva <= *pAddr, ("SegRva=%RTptr *pAddr=%RTptr\n", SegRva, *pAddr));
1009 *pAddr += MapAddr - SegRva;
1010 }
1011 }
1012 else
1013 {
1014 if ( iMapSeg != RTDBGSEGIDX_RVA
1015 && iMapSeg != NIL_RTDBGSEGIDX)
1016 {
1017 Assert(iMapSeg == iSeg);
1018 *pAddr += MapAddr;
1019 }
1020 else
1021 {
1022 RTUINTPTR SegRva = RTDbgModSegmentRva(hDbgMod, iSeg);
1023 AssertReturnVoid(SegRva != RTUINTPTR_MAX);
1024 *pAddr += MapAddr + SegRva;
1025 }
1026 }
1027}
1028
1029
1030/**
1031 * Adjusts the symbol value to correspond to the mapping of the module/segment.
1032 *
1033 * @param pSymbol The returned symbol info.
1034 * @param hDbgMod The module handle.
1035 * @param MapAddr The mapping address.
1036 * @param iMapSeg The segment that's mapped, NIL_RTDBGSEGIDX if the
1037 * whole module is mapped here.
1038 */
1039DECLINLINE(void) rtDbgAsAdjustSymbolValue(PRTDBGSYMBOL pSymbol, RTDBGMOD hDbgMod, RTUINTPTR MapAddr, RTDBGSEGIDX iMapSeg)
1040{
1041 Assert(pSymbol->iSeg != NIL_RTDBGSEGIDX);
1042 Assert(pSymbol->offSeg == pSymbol->Value);
1043 rtDbgAsAdjustAddressByMapping(&pSymbol->Value, pSymbol->iSeg, hDbgMod, MapAddr, iMapSeg);
1044}
1045
1046
1047/**
1048 * Adjusts the line number address to correspond to the mapping of the module/segment.
1049 *
1050 * @param pLine The returned line number info.
1051 * @param hDbgMod The module handle.
1052 * @param MapAddr The mapping address.
1053 * @param iMapSeg The segment that's mapped, NIL_RTDBGSEGIDX if the
1054 * whole module is mapped here.
1055 */
1056DECLINLINE(void) rtDbgAsAdjustLineAddress(PRTDBGLINE pLine, RTDBGMOD hDbgMod, RTUINTPTR MapAddr, RTDBGSEGIDX iMapSeg)
1057{
1058 Assert(pLine->iSeg != NIL_RTDBGSEGIDX);
1059 Assert(pLine->offSeg == pLine->Address);
1060 rtDbgAsAdjustAddressByMapping(&pLine->Address, pLine->iSeg, hDbgMod, MapAddr, iMapSeg);
1061}
1062
1063
1064RTDECL(int) RTDbgAsSymbolAdd(RTDBGAS hDbgAs, const char *pszSymbol, RTUINTPTR Addr, RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
1065{
1066 /*
1067 * Validate input and resolve the address.
1068 */
1069 PRTDBGASINT pDbgAs = hDbgAs;
1070 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1071
1072 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX; /* shut up gcc */
1073 RTUINTPTR offSeg = 0;
1074 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, NULL);
1075 if (hMod == NIL_RTDBGMOD)
1076 return VERR_NOT_FOUND;
1077
1078 /*
1079 * Forward the call.
1080 */
1081 int rc = RTDbgModSymbolAdd(hMod, pszSymbol, iSeg, offSeg, cb, fFlags, piOrdinal);
1082 RTDbgModRelease(hMod);
1083 return rc;
1084}
1085RT_EXPORT_SYMBOL(RTDbgAsSymbolAdd);
1086
1087
1088/**
1089 * Creates a snapshot of the module table on the temporary heap.
1090 *
1091 * The caller must release all the module handles before freeing the table
1092 * using RTMemTmpFree.
1093 *
1094 * @returns Module table snaphot.
1095 * @param pDbgAs The address space instance data.
1096 * @param pcModules Where to return the number of modules.
1097 */
1098static PRTDBGMOD rtDbgAsSnapshotModuleTable(PRTDBGASINT pDbgAs, uint32_t *pcModules)
1099{
1100 RTDBGAS_LOCK_READ(pDbgAs);
1101
1102 uint32_t iMod = *pcModules = pDbgAs->cModules;
1103 PRTDBGMOD pahModules = (PRTDBGMOD)RTMemTmpAlloc(sizeof(pahModules[0]) * RT_MAX(iMod, 1));
1104 if (pahModules)
1105 {
1106 while (iMod-- > 0)
1107 {
1108 RTDBGMOD hMod = (RTDBGMOD)pDbgAs->papModules[iMod]->Core.Key;
1109 pahModules[iMod] = hMod;
1110 RTDbgModRetain(hMod);
1111 }
1112 }
1113
1114 RTDBGAS_UNLOCK_READ(pDbgAs);
1115 return pahModules;
1116}
1117
1118
1119RTDECL(int) RTDbgAsSymbolByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags,
1120 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod)
1121{
1122 /*
1123 * Validate input and resolve the address.
1124 */
1125 PRTDBGASINT pDbgAs = hDbgAs;
1126 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1127 if (phMod)
1128 *phMod = NIL_RTDBGMOD;
1129
1130 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX; /* shut up gcc */
1131 RTUINTPTR offSeg = 0;
1132 RTUINTPTR MapAddr = 0;
1133 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, &MapAddr);
1134 if (hMod == NIL_RTDBGMOD)
1135 {
1136 /*
1137 * Check for absolute symbols. Requires iterating all modules.
1138 */
1139 if (fFlags & RTDBGSYMADDR_FLAGS_SKIP_ABS)
1140 return VERR_NOT_FOUND;
1141
1142 uint32_t cModules;
1143 PRTDBGMOD pahModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules);
1144 if (!pahModules)
1145 return VERR_NO_TMP_MEMORY;
1146
1147 int rc;
1148 RTINTPTR offBestDisp = RTINTPTR_MAX;
1149 uint32_t iBest = UINT32_MAX;
1150 for (uint32_t i = 0; i < cModules; i++)
1151 {
1152 RTINTPTR offDisp;
1153 rc = RTDbgModSymbolByAddr(pahModules[i], RTDBGSEGIDX_ABS, Addr, fFlags, &offDisp, pSymbol);
1154 if (RT_SUCCESS(rc) && RT_ABS(offDisp) < offBestDisp)
1155 {
1156 offBestDisp = RT_ABS(offDisp);
1157 iBest = i;
1158 }
1159 }
1160
1161 if (iBest == UINT32_MAX)
1162 rc = VERR_NOT_FOUND;
1163 else
1164 {
1165 hMod = pahModules[iBest];
1166 rc = RTDbgModSymbolByAddr(hMod, RTDBGSEGIDX_ABS, Addr, fFlags, poffDisp, pSymbol);
1167 if (RT_SUCCESS(rc))
1168 {
1169 rtDbgAsAdjustSymbolValue(pSymbol, hMod, MapAddr, iSeg);
1170 if (phMod)
1171 RTDbgModRetain(*phMod = hMod);
1172 }
1173 }
1174
1175 for (uint32_t i = 0; i < cModules; i++)
1176 RTDbgModRelease(pahModules[i]);
1177 RTMemTmpFree(pahModules);
1178 return rc;
1179 }
1180
1181 /*
1182 * Forward the call.
1183 */
1184 int rc = RTDbgModSymbolByAddr(hMod, iSeg, offSeg, fFlags, poffDisp, pSymbol);
1185 if (RT_SUCCESS(rc))
1186 rtDbgAsAdjustSymbolValue(pSymbol, hMod, MapAddr, iSeg);
1187 if (phMod)
1188 *phMod = hMod;
1189 else
1190 RTDbgModRelease(hMod);
1191 return rc;
1192}
1193RT_EXPORT_SYMBOL(RTDbgAsSymbolByAddr);
1194
1195
1196RTDECL(int) RTDbgAsSymbolByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags,
1197 PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo, PRTDBGMOD phMod)
1198{
1199 /*
1200 * Validate input and resolve the address.
1201 */
1202 PRTDBGASINT pDbgAs = hDbgAs;
1203 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1204
1205 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX;
1206 RTUINTPTR offSeg = 0;
1207 RTUINTPTR MapAddr = 0;
1208 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, &MapAddr);
1209 if (hMod == NIL_RTDBGMOD)
1210 {
1211 if (phMod)
1212 *phMod = NIL_RTDBGMOD;
1213 return VERR_NOT_FOUND;
1214 }
1215
1216 /*
1217 * Forward the call.
1218 */
1219 int rc = RTDbgModSymbolByAddrA(hMod, iSeg, offSeg, fFlags, poffDisp, ppSymInfo);
1220 if (RT_SUCCESS(rc))
1221 rtDbgAsAdjustSymbolValue(*ppSymInfo, hMod, MapAddr, iSeg);
1222 if (phMod)
1223 *phMod = hMod;
1224 else
1225 RTDbgModRelease(hMod);
1226 return rc;
1227}
1228RT_EXPORT_SYMBOL(RTDbgAsSymbolByAddrA);
1229
1230
1231/**
1232 * Attempts to find a mapping of the specified symbol/module and
1233 * adjust it's Value field accordingly.
1234 *
1235 * @returns true / false success indicator.
1236 * @param pDbgAs The address space.
1237 * @param hDbgMod The module handle.
1238 * @param pSymbol The symbol info.
1239 */
1240static bool rtDbgAsFindMappingAndAdjustSymbolValue(PRTDBGASINT pDbgAs, RTDBGMOD hDbgMod, PRTDBGSYMBOL pSymbol)
1241{
1242 /*
1243 * Absolute segments needs no fixing.
1244 */
1245 RTDBGSEGIDX const iSeg = pSymbol->iSeg;
1246 if (iSeg == RTDBGSEGIDX_ABS)
1247 return true;
1248
1249 RTDBGAS_LOCK_READ(pDbgAs);
1250
1251 /*
1252 * Lookup up the module by it's handle and iterate the mappings looking for one
1253 * that either encompasses the entire module or the segment in question.
1254 */
1255 PRTDBGASMOD pMod = (PRTDBGASMOD)RTAvlPVGet(&pDbgAs->ModTree, hDbgMod);
1256 if (pMod)
1257 {
1258 for (PRTDBGASMAP pMap = pMod->pMapHead; pMap; pMap = pMap->pNext)
1259 {
1260 /* Exact segment match or full-mapping. */
1261 if ( iSeg == pMap->iSeg
1262 || pMap->iSeg == NIL_RTDBGSEGIDX)
1263 {
1264 RTUINTPTR MapAddr = pMap->Core.Key;
1265 RTDBGSEGIDX iMapSeg = pMap->iSeg;
1266
1267 RTDBGAS_UNLOCK_READ(pDbgAs);
1268 rtDbgAsAdjustSymbolValue(pSymbol, hDbgMod, MapAddr, iMapSeg);
1269 return true;
1270 }
1271
1272 /* Symbol uses RVA and the mapping doesn't, see if it's in the mapped segment. */
1273 if (iSeg == RTDBGSEGIDX_RVA)
1274 {
1275 Assert(pMap->iSeg != NIL_RTDBGSEGIDX);
1276 RTUINTPTR SegRva = RTDbgModSegmentRva(hDbgMod, pMap->iSeg);
1277 Assert(SegRva != RTUINTPTR_MAX);
1278 RTUINTPTR cbSeg = RTDbgModSegmentSize(hDbgMod, pMap->iSeg);
1279 if (SegRva - pSymbol->Value < cbSeg)
1280 {
1281 RTUINTPTR MapAddr = pMap->Core.Key;
1282 RTDBGSEGIDX iMapSeg = pMap->iSeg;
1283
1284 RTDBGAS_UNLOCK_READ(pDbgAs);
1285 rtDbgAsAdjustSymbolValue(pSymbol, hDbgMod, MapAddr, iMapSeg);
1286 return true;
1287 }
1288 }
1289 }
1290 }
1291 /* else: Unmapped while we were searching. */
1292
1293 RTDBGAS_UNLOCK_READ(pDbgAs);
1294 return false;
1295}
1296
1297
1298RTDECL(int) RTDbgAsSymbolByName(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod)
1299{
1300 /*
1301 * Validate input.
1302 */
1303 PRTDBGASINT pDbgAs = hDbgAs;
1304 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1305 AssertPtrReturn(pszSymbol, VERR_INVALID_POINTER);
1306 AssertPtrReturn(pSymbol, VERR_INVALID_POINTER);
1307
1308 /*
1309 * Look for module pattern.
1310 */
1311 const char *pachModPat = NULL;
1312 size_t cchModPat = 0;
1313 const char *pszBang = strchr(pszSymbol, '!');
1314 if (pszBang)
1315 {
1316 pachModPat = pszSymbol;
1317 cchModPat = pszBang - pszSymbol;
1318 pszSymbol = pszBang + 1;
1319 if (!*pszSymbol)
1320 return VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE;
1321 /* Note! Zero length module -> no pattern -> escape for symbol with '!'. */
1322 }
1323
1324 /*
1325 * Iterate the modules, looking for the symbol.
1326 */
1327 uint32_t cModules;
1328 PRTDBGMOD pahModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules);
1329 if (!pahModules)
1330 return VERR_NO_TMP_MEMORY;
1331
1332 for (uint32_t i = 0; i < cModules; i++)
1333 {
1334 if ( cchModPat == 0
1335 || RTStrSimplePatternNMatch(pachModPat, cchModPat, RTDbgModName(pahModules[i]), RTSTR_MAX))
1336 {
1337 int rc = RTDbgModSymbolByName(pahModules[i], pszSymbol, pSymbol);
1338 if (RT_SUCCESS(rc))
1339 {
1340 if (rtDbgAsFindMappingAndAdjustSymbolValue(pDbgAs, pahModules[i], pSymbol))
1341 {
1342 if (phMod)
1343 RTDbgModRetain(*phMod = pahModules[i]);
1344 for (; i < cModules; i++)
1345 RTDbgModRelease(pahModules[i]);
1346 RTMemTmpFree(pahModules);
1347 return rc;
1348 }
1349 }
1350 }
1351 RTDbgModRelease(pahModules[i]);
1352 }
1353
1354 RTMemTmpFree(pahModules);
1355 return VERR_SYMBOL_NOT_FOUND;
1356}
1357RT_EXPORT_SYMBOL(RTDbgAsSymbolByName);
1358
1359
1360RTDECL(int) RTDbgAsSymbolByNameA(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL *ppSymbol, PRTDBGMOD phMod)
1361{
1362 /*
1363 * Validate input.
1364 */
1365 AssertPtrReturn(ppSymbol, VERR_INVALID_POINTER);
1366 *ppSymbol = NULL;
1367 PRTDBGASINT pDbgAs = hDbgAs;
1368 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1369 AssertPtrReturn(pszSymbol, VERR_INVALID_POINTER);
1370
1371 /*
1372 * Look for module pattern.
1373 */
1374 const char *pachModPat = NULL;
1375 size_t cchModPat = 0;
1376 const char *pszBang = strchr(pszSymbol, '!');
1377 if (pszBang)
1378 {
1379 pachModPat = pszSymbol;
1380 cchModPat = pszBang - pszSymbol;
1381 pszSymbol = pszBang + 1;
1382 if (!*pszSymbol)
1383 return VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE;
1384 /* Note! Zero length module -> no pattern -> escape for symbol with '!'. */
1385 }
1386
1387 /*
1388 * Iterate the modules, looking for the symbol.
1389 */
1390 uint32_t cModules;
1391 PRTDBGMOD pahModules = rtDbgAsSnapshotModuleTable(pDbgAs, &cModules);
1392 if (!pahModules)
1393 return VERR_NO_TMP_MEMORY;
1394
1395 for (uint32_t i = 0; i < cModules; i++)
1396 {
1397 if ( cchModPat == 0
1398 || RTStrSimplePatternNMatch(pachModPat, cchModPat, RTDbgModName(pahModules[i]), RTSTR_MAX))
1399 {
1400 int rc = RTDbgModSymbolByNameA(pahModules[i], pszSymbol, ppSymbol);
1401 if (RT_SUCCESS(rc))
1402 {
1403 if (rtDbgAsFindMappingAndAdjustSymbolValue(pDbgAs, pahModules[i], *ppSymbol))
1404 {
1405 if (phMod)
1406 RTDbgModRetain(*phMod = pahModules[i]);
1407 for (; i < cModules; i++)
1408 RTDbgModRelease(pahModules[i]);
1409 RTMemTmpFree(pahModules);
1410 return rc;
1411 }
1412 }
1413 }
1414 RTDbgModRelease(pahModules[i]);
1415 }
1416
1417 RTMemTmpFree(pahModules);
1418 return VERR_SYMBOL_NOT_FOUND;
1419}
1420RT_EXPORT_SYMBOL(RTDbgAsSymbolByNameA);
1421
1422
1423RTDECL(int) RTDbgAsLineAdd(RTDBGAS hDbgAs, const char *pszFile, uint32_t uLineNo, RTUINTPTR Addr, uint32_t *piOrdinal)
1424{
1425 /*
1426 * Validate input and resolve the address.
1427 */
1428 PRTDBGASINT pDbgAs = hDbgAs;
1429 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1430
1431 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX; /* shut up gcc */
1432 RTUINTPTR offSeg = 0; /* ditto */
1433 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, NULL);
1434 if (hMod == NIL_RTDBGMOD)
1435 return VERR_NOT_FOUND;
1436
1437 /*
1438 * Forward the call.
1439 */
1440 int rc = RTDbgModLineAdd(hMod, pszFile, uLineNo, iSeg, offSeg, piOrdinal);
1441 RTDbgModRelease(hMod);
1442 return rc;
1443}
1444RT_EXPORT_SYMBOL(RTDbgAsLineAdd);
1445
1446
1447RTDECL(int) RTDbgAsLineByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod)
1448{
1449 /*
1450 * Validate input and resolve the address.
1451 */
1452 PRTDBGASINT pDbgAs = hDbgAs;
1453 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1454
1455 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX; /* shut up gcc */
1456 RTUINTPTR offSeg = 0;
1457 RTUINTPTR MapAddr = 0;
1458 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, &MapAddr);
1459 if (hMod == NIL_RTDBGMOD)
1460 return VERR_NOT_FOUND;
1461
1462 /*
1463 * Forward the call.
1464 */
1465 int rc = RTDbgModLineByAddr(hMod, iSeg, offSeg, poffDisp, pLine);
1466 if (RT_SUCCESS(rc))
1467 {
1468 rtDbgAsAdjustLineAddress(pLine, hMod, MapAddr, iSeg);
1469 if (phMod)
1470 *phMod = hMod;
1471 else
1472 RTDbgModRelease(hMod);
1473 }
1474 else
1475 RTDbgModRelease(hMod);
1476 return rc;
1477}
1478RT_EXPORT_SYMBOL(RTDbgAsLineByAddr);
1479
1480
1481RTDECL(int) RTDbgAsLineByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE *ppLine, PRTDBGMOD phMod)
1482{
1483 /*
1484 * Validate input and resolve the address.
1485 */
1486 PRTDBGASINT pDbgAs = hDbgAs;
1487 RTDBGAS_VALID_RETURN_RC(pDbgAs, VERR_INVALID_HANDLE);
1488
1489 RTDBGSEGIDX iSeg = NIL_RTDBGSEGIDX; /* shut up gcc */
1490 RTUINTPTR offSeg = 0;
1491 RTUINTPTR MapAddr = 0;
1492 RTDBGMOD hMod = rtDbgAsModuleByAddr(pDbgAs, Addr, &iSeg, &offSeg, &MapAddr);
1493 if (hMod == NIL_RTDBGMOD)
1494 return VERR_NOT_FOUND;
1495
1496 /*
1497 * Forward the call.
1498 */
1499 int rc = RTDbgModLineByAddrA(hMod, iSeg, offSeg, poffDisp, ppLine);
1500 if (RT_SUCCESS(rc))
1501 {
1502 rtDbgAsAdjustLineAddress(*ppLine, hMod, MapAddr, iSeg);
1503 if (phMod)
1504 *phMod = hMod;
1505 else
1506 RTDbgModRelease(hMod);
1507 }
1508 else
1509 RTDbgModRelease(hMod);
1510 return rc;
1511}
1512RT_EXPORT_SYMBOL(RTDbgAsLineByAddrA);
1513
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use