VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp@ 44135

Last change on this file since 44135 was 43879, checked in by vboxsync, 12 years ago

Extended RTOnce with termination cleanups. (Changes existing structures and functions.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.3 KB
Line 
1/* $Id: dbgmod.cpp 43879 2012-11-15 14:49:23Z vboxsync $ */
2/** @file
3 * IPRT - Debug Module Interpreter.
4 */
5
6/*
7 * Copyright (C) 2009 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/dbg.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/avl.h>
37#include <iprt/err.h>
38#include <iprt/initterm.h>
39#include <iprt/mem.h>
40#include <iprt/once.h>
41#include <iprt/param.h>
42#include <iprt/path.h>
43#include <iprt/semaphore.h>
44#include <iprt/strcache.h>
45#include <iprt/string.h>
46#include "internal/dbgmod.h"
47#include "internal/magics.h"
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53/** Debug info interpreter registration record. */
54typedef struct RTDBGMODREGDBG
55{
56 /** Pointer to the next record. */
57 struct RTDBGMODREGDBG *pNext;
58 /** Pointer to the virtual function table for the interpreter. */
59 PCRTDBGMODVTDBG pVt;
60 /** Usage counter. */
61 uint32_t volatile cUsers;
62} RTDBGMODREGDBG;
63typedef RTDBGMODREGDBG *PRTDBGMODREGDBG;
64
65/** Image interpreter registration record. */
66typedef struct RTDBGMODREGIMG
67{
68 /** Pointer to the next record. */
69 struct RTDBGMODREGIMG *pNext;
70 /** Pointer to the virtual function table for the interpreter. */
71 PCRTDBGMODVTIMG pVt;
72 /** Usage counter. */
73 uint32_t volatile cUsers;
74} RTDBGMODREGIMG;
75typedef RTDBGMODREGIMG *PRTDBGMODREGIMG;
76
77
78/*******************************************************************************
79* Defined Constants And Macros *
80*******************************************************************************/
81/** Validates a debug module handle and returns rc if not valid. */
82#define RTDBGMOD_VALID_RETURN_RC(pDbgMod, rc) \
83 do { \
84 AssertPtrReturn((pDbgMod), (rc)); \
85 AssertReturn((pDbgMod)->u32Magic == RTDBGMOD_MAGIC, (rc)); \
86 AssertReturn((pDbgMod)->cRefs > 0, (rc)); \
87 } while (0)
88
89/** Locks the debug module. */
90#define RTDBGMOD_LOCK(pDbgMod) \
91 do { \
92 int rcLock = RTCritSectEnter(&(pDbgMod)->CritSect); \
93 AssertRC(rcLock); \
94 } while (0)
95
96/** Unlocks the debug module. */
97#define RTDBGMOD_UNLOCK(pDbgMod) \
98 do { \
99 int rcLock = RTCritSectLeave(&(pDbgMod)->CritSect); \
100 AssertRC(rcLock); \
101 } while (0)
102
103
104/*******************************************************************************
105* Global Variables *
106*******************************************************************************/
107/** Init once object for lazy registration of the built-in image and debug
108 * info interpreters. */
109static RTONCE g_rtDbgModOnce = RTONCE_INITIALIZER;
110/** Read/Write semaphore protecting the list of registered interpreters. */
111static RTSEMRW g_hDbgModRWSem = NIL_RTSEMRW;
112/** List of registered image interpreters. */
113static PRTDBGMODREGIMG g_pImgHead;
114/** List of registered debug infor interpreters. */
115static PRTDBGMODREGDBG g_pDbgHead;
116/** String cache for the debug info interpreters.
117 * RTSTRCACHE is thread safe. */
118DECLHIDDEN(RTSTRCACHE) g_hDbgModStrCache = NIL_RTSTRCACHE;
119
120
121
122/**
123 * Cleanup debug info interpreter globals.
124 *
125 * @param enmReason The cause of the termination.
126 * @param iStatus The meaning of this depends on enmReason.
127 * @param pvUser User argument, unused.
128 */
129static DECLCALLBACK(void) rtDbgModTermCallback(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
130{
131 NOREF(iStatus); NOREF(pvUser);
132 if (enmReason == RTTERMREASON_UNLOAD)
133 {
134 RTSemRWDestroy(g_hDbgModRWSem);
135 g_hDbgModRWSem = NIL_RTSEMRW;
136
137 RTStrCacheDestroy(g_hDbgModStrCache);
138 g_hDbgModStrCache = NIL_RTSTRCACHE;
139
140 PRTDBGMODREGDBG pDbg = g_pDbgHead;
141 g_pDbgHead = NULL;
142 while (pDbg)
143 {
144 PRTDBGMODREGDBG pNext = pDbg->pNext;
145 AssertMsg(pDbg->cUsers == 0, ("%#x %s\n", pDbg->cUsers, pDbg->pVt->pszName));
146 RTMemFree(pDbg);
147 pDbg = pNext;
148 }
149
150 PRTDBGMODREGIMG pImg = g_pImgHead;
151 g_pImgHead = NULL;
152 while (pImg)
153 {
154 PRTDBGMODREGIMG pNext = pImg->pNext;
155 AssertMsg(pImg->cUsers == 0, ("%#x %s\n", pImg->cUsers, pImg->pVt->pszName));
156 RTMemFree(pImg);
157 pImg = pNext;
158 }
159 }
160}
161
162
163/**
164 * Internal worker for register a debug interpreter.
165 *
166 * Called while owning the write lock or when locking isn't required.
167 *
168 * @returns IPRT status code.
169 * @retval VERR_NO_MEMORY
170 * @retval VERR_ALREADY_EXISTS
171 *
172 * @param pVt The virtual function table of the debug
173 * module interpreter.
174 */
175static int rtDbgModDebugInterpreterRegister(PCRTDBGMODVTDBG pVt)
176{
177 /*
178 * Search or duplicate registration.
179 */
180 PRTDBGMODREGDBG pPrev = NULL;
181 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
182 {
183 if (pCur->pVt == pVt)
184 return VERR_ALREADY_EXISTS;
185 if (!strcmp(pCur->pVt->pszName, pVt->pszName))
186 return VERR_ALREADY_EXISTS;
187 pPrev = pCur;
188 }
189
190 /*
191 * Create a new record and add it to the end of the list.
192 */
193 PRTDBGMODREGDBG pReg = (PRTDBGMODREGDBG)RTMemAlloc(sizeof(*pReg));
194 if (!pReg)
195 return VERR_NO_MEMORY;
196 pReg->pVt = pVt;
197 pReg->cUsers = 0;
198 pReg->pNext = NULL;
199 if (pPrev)
200 pPrev->pNext = pReg;
201 else
202 g_pDbgHead = pReg;
203 return VINF_SUCCESS;
204}
205
206
207/**
208 * Internal worker for register a image interpreter.
209 *
210 * Called while owning the write lock or when locking isn't required.
211 *
212 * @returns IPRT status code.
213 * @retval VERR_NO_MEMORY
214 * @retval VERR_ALREADY_EXISTS
215 *
216 * @param pVt The virtual function table of the image
217 * interpreter.
218 */
219static int rtDbgModImageInterpreterRegister(PCRTDBGMODVTIMG pVt)
220{
221 /*
222 * Search or duplicate registration.
223 */
224 PRTDBGMODREGIMG pPrev = NULL;
225 for (PRTDBGMODREGIMG pCur = g_pImgHead; pCur; pCur = pCur->pNext)
226 {
227 if (pCur->pVt == pVt)
228 return VERR_ALREADY_EXISTS;
229 if (!strcmp(pCur->pVt->pszName, pVt->pszName))
230 return VERR_ALREADY_EXISTS;
231 pPrev = pCur;
232 }
233
234 /*
235 * Create a new record and add it to the end of the list.
236 */
237 PRTDBGMODREGIMG pReg = (PRTDBGMODREGIMG)RTMemAlloc(sizeof(*pReg));
238 if (!pReg)
239 return VERR_NO_MEMORY;
240 pReg->pVt = pVt;
241 pReg->cUsers = 0;
242 pReg->pNext = NULL;
243 if (pPrev)
244 pPrev->pNext = pReg;
245 else
246 g_pImgHead = pReg;
247 return VINF_SUCCESS;
248}
249
250
251/**
252 * Do-once callback that initializes the read/write semaphore and registers
253 * the built-in interpreters.
254 *
255 * @returns IPRT status code.
256 * @param pvUser NULL.
257 */
258static DECLCALLBACK(int) rtDbgModInitOnce(void *pvUser)
259{
260 NOREF(pvUser);
261
262 /*
263 * Create the semaphore and string cache.
264 */
265 int rc = RTSemRWCreate(&g_hDbgModRWSem);
266 AssertRCReturn(rc, rc);
267
268 rc = RTStrCacheCreate(&g_hDbgModStrCache, "RTDBGMOD");
269 if (RT_SUCCESS(rc))
270 {
271 /*
272 * Register the interpreters.
273 */
274 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgNm);
275 if (RT_SUCCESS(rc))
276 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgDwarf);
277 if (RT_SUCCESS(rc))
278 rc = rtDbgModImageInterpreterRegister(&g_rtDbgModVtImgLdr);
279 if (RT_SUCCESS(rc))
280 {
281 /*
282 * Finally, register the IPRT cleanup callback.
283 */
284 rc = RTTermRegisterCallback(rtDbgModTermCallback, NULL);
285 if (RT_SUCCESS(rc))
286 return VINF_SUCCESS;
287
288 /* bail out: use the termination callback. */
289 }
290 }
291 else
292 g_hDbgModStrCache = NIL_RTSTRCACHE;
293 rtDbgModTermCallback(RTTERMREASON_UNLOAD, 0, NULL);
294 return rc;
295}
296
297
298DECLINLINE(int) rtDbgModLazyInit(void)
299{
300 return RTOnce(&g_rtDbgModOnce, rtDbgModInitOnce, NULL);
301}
302
303
304/**
305 * Creates a module based on the default debug info container.
306 *
307 * This can be used to manually load a module and its symbol. The primary user
308 * group is the debug info interpreters, which use this API to create an
309 * efficient debug info container behind the scenes and forward all queries to
310 * it once the info has been loaded.
311 *
312 * @returns IPRT status code.
313 *
314 * @param phDbgMod Where to return the module handle.
315 * @param pszName The name of the module (mandatory).
316 * @param cbSeg The size of initial segment. If zero, segments will
317 * have to be added manually using RTDbgModSegmentAdd.
318 * @param fFlags Flags reserved for future extensions, MBZ for now.
319 */
320RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cbSeg, uint32_t fFlags)
321{
322 /*
323 * Input validation and lazy initialization.
324 */
325 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
326 *phDbgMod = NIL_RTDBGMOD;
327 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
328 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
329 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
330
331 int rc = rtDbgModLazyInit();
332 if (RT_FAILURE(rc))
333 return rc;
334
335 /*
336 * Allocate a new module instance.
337 */
338 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
339 if (!pDbgMod)
340 return VERR_NO_MEMORY;
341 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
342 pDbgMod->cRefs = 1;
343 rc = RTCritSectInit(&pDbgMod->CritSect);
344 if (RT_SUCCESS(rc))
345 {
346 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
347 if (pDbgMod->pszName)
348 {
349 rc = rtDbgModContainerCreate(pDbgMod, cbSeg);
350 if (RT_SUCCESS(rc))
351 {
352 *phDbgMod = pDbgMod;
353 return rc;
354 }
355 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
356 }
357 RTCritSectDelete(&pDbgMod->CritSect);
358 }
359
360 RTMemFree(pDbgMod);
361 return rc;
362}
363RT_EXPORT_SYMBOL(RTDbgModCreate);
364
365
366RTDECL(int) RTDbgModCreateDeferred(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
367 RTUINTPTR cb, uint32_t fFlags)
368{
369 NOREF(phDbgMod); NOREF(pszFilename); NOREF(pszName); NOREF(cb); NOREF(fFlags);
370 return VERR_NOT_IMPLEMENTED;
371}
372RT_EXPORT_SYMBOL(RTDbgModCreateDeferred);
373
374
375RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags)
376{
377 /*
378 * Input validation and lazy initialization.
379 */
380 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
381 *phDbgMod = NIL_RTDBGMOD;
382 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
383 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
384 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
385 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
386
387 int rc = rtDbgModLazyInit();
388 if (RT_FAILURE(rc))
389 return rc;
390
391 if (!pszName)
392 pszName = RTPathFilename(pszFilename);
393
394 /*
395 * Allocate a new module instance.
396 */
397 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
398 if (!pDbgMod)
399 return VERR_NO_MEMORY;
400 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
401 pDbgMod->cRefs = 1;
402 rc = RTCritSectInit(&pDbgMod->CritSect);
403 if (RT_SUCCESS(rc))
404 {
405 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
406 if (pDbgMod->pszName)
407 {
408 pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
409 if (pDbgMod->pszImgFile)
410 {
411 /*
412 * Find an image reader which groks the file.
413 */
414 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
415 if (RT_SUCCESS(rc))
416 {
417 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
418 PRTDBGMODREGIMG pImg;
419 for (pImg = g_pImgHead; pImg; pImg = pImg->pNext)
420 {
421 pDbgMod->pImgVt = pImg->pVt;
422 pDbgMod->pvImgPriv = NULL;
423 rc = pImg->pVt->pfnTryOpen(pDbgMod);
424 if (RT_SUCCESS(rc))
425 {
426 /*
427 * Find a debug info interpreter.
428 */
429 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
430 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
431 {
432 pDbgMod->pDbgVt = pDbg->pVt;
433 pDbgMod->pvDbgPriv = NULL;
434 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
435 if (RT_SUCCESS(rc))
436 {
437 /*
438 * That's it!
439 */
440 ASMAtomicIncU32(&pDbg->cUsers);
441 ASMAtomicIncU32(&pImg->cUsers);
442 RTSemRWReleaseRead(g_hDbgModRWSem);
443
444 *phDbgMod = pDbgMod;
445 return rc;
446 }
447 }
448
449 /*
450 * Image detected, but found no debug info we were
451 * able to understand.
452 */
453 /** @todo Fall back on exported symbols! */
454 pDbgMod->pImgVt->pfnClose(pDbgMod);
455 break;
456 }
457 }
458
459 /*
460 * Could it be a file containing raw debug info?
461 */
462 if (!pImg)
463 {
464 pDbgMod->pImgVt = NULL;
465 pDbgMod->pvImgPriv = NULL;
466 pDbgMod->pszDbgFile = pDbgMod->pszImgFile;
467 pDbgMod->pszImgFile = NULL;
468
469 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
470 {
471 pDbgMod->pDbgVt = pDbg->pVt;
472 pDbgMod->pvDbgPriv = NULL;
473 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
474 if (RT_SUCCESS(rc))
475 {
476 /*
477 * That's it!
478 */
479 ASMAtomicIncU32(&pDbg->cUsers);
480 RTSemRWReleaseRead(g_hDbgModRWSem);
481
482 *phDbgMod = pDbgMod;
483 return rc;
484 }
485 }
486
487 pDbgMod->pszImgFile = pDbgMod->pszDbgFile;
488 pDbgMod->pszDbgFile = NULL;
489 }
490
491 /* bail out */
492 RTSemRWReleaseRead(g_hDbgModRWSem);
493 }
494 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
495 }
496 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
497 }
498 RTCritSectDelete(&pDbgMod->CritSect);
499 }
500
501 RTMemFree(pDbgMod);
502 return rc;
503}
504RT_EXPORT_SYMBOL(RTDbgModCreateFromImage);
505
506
507RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
508 RTUINTPTR uSubtrahend, uint32_t fFlags)
509{
510 /*
511 * Input validation and lazy initialization.
512 */
513 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
514 *phDbgMod = NIL_RTDBGMOD;
515 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
516 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
517 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
518 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
519 AssertReturn(uSubtrahend == 0, VERR_NOT_IMPLEMENTED); /** @todo implement uSubtrahend. */
520
521 int rc = rtDbgModLazyInit();
522 if (RT_FAILURE(rc))
523 return rc;
524
525 if (!pszName)
526 pszName = RTPathFilename(pszFilename);
527
528 /*
529 * Allocate a new module instance.
530 */
531 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
532 if (!pDbgMod)
533 return VERR_NO_MEMORY;
534 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
535 pDbgMod->cRefs = 1;
536 rc = RTCritSectInit(&pDbgMod->CritSect);
537 if (RT_SUCCESS(rc))
538 {
539 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
540 if (pDbgMod->pszName)
541 {
542 pDbgMod->pszDbgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
543 if (pDbgMod->pszDbgFile)
544 {
545 /*
546 * Try the map file readers.
547 */
548 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
549 if (RT_SUCCESS(rc))
550 {
551 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
552 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
553 {
554 if (pCur->pVt->fSupports & RT_DBGTYPE_MAP)
555 {
556 pDbgMod->pDbgVt = pCur->pVt;
557 pDbgMod->pvDbgPriv = NULL;
558 rc = pCur->pVt->pfnTryOpen(pDbgMod);
559 if (RT_SUCCESS(rc))
560 {
561 ASMAtomicIncU32(&pCur->cUsers);
562 RTSemRWReleaseRead(g_hDbgModRWSem);
563
564 *phDbgMod = pDbgMod;
565 return rc;
566 }
567 }
568 }
569
570 /* bail out */
571 RTSemRWReleaseRead(g_hDbgModRWSem);
572 }
573 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
574 }
575 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
576 }
577 RTCritSectDelete(&pDbgMod->CritSect);
578 }
579
580 RTMemFree(pDbgMod);
581 return rc;
582}
583RT_EXPORT_SYMBOL(RTDbgModCreateFromMap);
584
585
586/**
587 * Destroys an module after the reference count has reached zero.
588 *
589 * @param pDbgMod The module instance.
590 */
591static void rtDbgModDestroy(PRTDBGMODINT pDbgMod)
592{
593 /*
594 * Close the debug info interpreter first, then the image interpret.
595 */
596 RTCritSectEnter(&pDbgMod->CritSect); /* paranoia */
597
598 if (pDbgMod->pDbgVt)
599 {
600 pDbgMod->pDbgVt->pfnClose(pDbgMod);
601 pDbgMod->pDbgVt = NULL;
602 pDbgMod->pvDbgPriv = NULL;
603 }
604
605 if (pDbgMod->pImgVt)
606 {
607 pDbgMod->pImgVt->pfnClose(pDbgMod);
608 pDbgMod->pImgVt = NULL;
609 pDbgMod->pvImgPriv = NULL;
610 }
611
612 /*
613 * Free the resources.
614 */
615 ASMAtomicWriteU32(&pDbgMod->u32Magic, ~RTDBGMOD_MAGIC);
616 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
617 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
618 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
619 RTCritSectLeave(&pDbgMod->CritSect); /* paranoia */
620 RTCritSectDelete(&pDbgMod->CritSect);
621 RTMemFree(pDbgMod);
622}
623
624
625/**
626 * Retains another reference to the module.
627 *
628 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
629 *
630 * @param hDbgMod The module handle.
631 *
632 * @remarks Will not take any locks.
633 */
634RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod)
635{
636 PRTDBGMODINT pDbgMod = hDbgMod;
637 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
638 return ASMAtomicIncU32(&pDbgMod->cRefs);
639}
640RT_EXPORT_SYMBOL(RTDbgModRetain);
641
642
643/**
644 * Release a reference to the module.
645 *
646 * When the reference count reaches zero, the module is destroyed.
647 *
648 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
649 *
650 * @param hDbgMod The module handle. The NIL handle is quietly ignored
651 * and 0 is returned.
652 *
653 * @remarks Will not take any locks.
654 */
655RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod)
656{
657 if (hDbgMod == NIL_RTDBGMOD)
658 return 0;
659 PRTDBGMODINT pDbgMod = hDbgMod;
660 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
661
662 uint32_t cRefs = ASMAtomicDecU32(&pDbgMod->cRefs);
663 if (!cRefs)
664 rtDbgModDestroy(pDbgMod);
665 return cRefs;
666}
667RT_EXPORT_SYMBOL(RTDbgModRelease);
668
669
670/**
671 * Gets the module name.
672 *
673 * @returns Pointer to a read only string containing the name.
674 *
675 * @param hDbgMod The module handle.
676 */
677RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod)
678{
679 PRTDBGMODINT pDbgMod = hDbgMod;
680 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
681 return pDbgMod->pszName;
682}
683RT_EXPORT_SYMBOL(RTDbgModName);
684
685
686/**
687 * Converts an image relative address to a segment:offset address.
688 *
689 * @returns Segment index on success.
690 * NIL_RTDBGSEGIDX is returned if the module handle or the RVA are
691 * invalid.
692 *
693 * @param hDbgMod The module handle.
694 * @param uRva The image relative address to convert.
695 * @param poffSeg Where to return the segment offset. Optional.
696 */
697RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
698{
699 PRTDBGMODINT pDbgMod = hDbgMod;
700 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
701 RTDBGMOD_LOCK(pDbgMod);
702
703 RTDBGSEGIDX iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, uRva, poffSeg);
704
705 RTDBGMOD_UNLOCK(pDbgMod);
706 return iSeg;
707}
708RT_EXPORT_SYMBOL(RTDbgModRvaToSegOff);
709
710
711/**
712 * Image size when mapped if segments are mapped adjacently.
713 *
714 * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and
715 * NE and such it's a bit odder and the answer may not make much sense for them.
716 *
717 * @returns Image mapped size.
718 * RTUINTPTR_MAX is returned if the handle is invalid.
719 *
720 * @param hDbgMod The module handle.
721 */
722RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod)
723{
724 PRTDBGMODINT pDbgMod = hDbgMod;
725 RTDBGMOD_VALID_RETURN_RC(pDbgMod, RTUINTPTR_MAX);
726 RTDBGMOD_LOCK(pDbgMod);
727
728 RTUINTPTR cbImage = pDbgMod->pDbgVt->pfnImageSize(pDbgMod);
729
730 RTDBGMOD_UNLOCK(pDbgMod);
731 return cbImage;
732}
733RT_EXPORT_SYMBOL(RTDbgModImageSize);
734
735
736/**
737 * Gets the module tag value if any.
738 *
739 * @returns The tag. 0 if hDbgMod is invalid.
740 *
741 * @param hDbgMod The module handle.
742 */
743RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod)
744{
745 PRTDBGMODINT pDbgMod = hDbgMod;
746 RTDBGMOD_VALID_RETURN_RC(pDbgMod, 0);
747 return pDbgMod->uTag;
748}
749RT_EXPORT_SYMBOL(RTDbgModGetTag);
750
751
752/**
753 * Tags or untags the module.
754 *
755 * @returns IPRT status code.
756 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
757 *
758 * @param hDbgMod The module handle.
759 * @param uTag The tag value. The convention is that 0 is no tag
760 * and any other value means it's tagged. It's adviced
761 * to use some kind of unique number like an address
762 * (global or string cache for instance) to avoid
763 * collisions with other users
764 */
765RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag)
766{
767 PRTDBGMODINT pDbgMod = hDbgMod;
768 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
769 RTDBGMOD_LOCK(pDbgMod);
770
771 pDbgMod->uTag = uTag;
772
773 RTDBGMOD_UNLOCK(pDbgMod);
774 return VINF_SUCCESS;
775}
776RT_EXPORT_SYMBOL(RTDbgModSetTag);
777
778
779/**
780 * Adds a segment to the module. Optional feature.
781 *
782 * This method is intended used for manually constructing debug info for a
783 * module. The main usage is from other debug info interpreters that want to
784 * avoid writing a debug info database and instead uses the standard container
785 * behind the scenes.
786 *
787 * @returns IPRT status code.
788 * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info
789 * interpreter. This is a common return code.
790 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
791 * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around.
792 * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long.
793 * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags.
794 * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment.
795 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations.
796 *
797 * @param hDbgMod The module handle.
798 * @param uRva The image relative address of the segment.
799 * @param cb The size of the segment.
800 * @param pszName The segment name. Does not normally need to be
801 * unique, although this is somewhat up to the
802 * debug interpreter to decide.
803 * @param fFlags Segment flags. Reserved for future used, MBZ.
804 * @param piSeg The segment index or NIL_RTDBGSEGIDX on input.
805 * The assigned segment index on successful return.
806 * Optional.
807 */
808RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
809 uint32_t fFlags, PRTDBGSEGIDX piSeg)
810{
811 /*
812 * Validate input.
813 */
814 PRTDBGMODINT pDbgMod = hDbgMod;
815 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
816 AssertMsgReturn(uRva + cb >= uRva, ("uRva=%RTptr cb=%RTptr\n", uRva, cb), VERR_DBG_ADDRESS_WRAP);
817 Assert(*pszName);
818 size_t cchName = strlen(pszName);
819 AssertReturn(cchName > 0, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
820 AssertReturn(cchName < RTDBG_SEGMENT_NAME_LENGTH, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
821 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
822 AssertPtrNull(piSeg);
823 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg <= RTDBGSEGIDX_LAST, ("%#x\n", *piSeg), VERR_DBG_SPECIAL_SEGMENT);
824
825 /*
826 * Do the deed.
827 */
828 RTDBGMOD_LOCK(pDbgMod);
829 int rc = pDbgMod->pDbgVt->pfnSegmentAdd(pDbgMod, uRva, cb, pszName, cchName, fFlags, piSeg);
830 RTDBGMOD_UNLOCK(pDbgMod);
831
832 return rc;
833
834}
835RT_EXPORT_SYMBOL(RTDbgModSegmentAdd);
836
837
838/**
839 * Gets the number of segments in the module.
840 *
841 * This is can be used to determine the range which can be passed to
842 * RTDbgModSegmentByIndex and derivatives.
843 *
844 * @returns The segment relative address.
845 * NIL_RTDBGSEGIDX if the handle is invalid.
846 *
847 * @param hDbgMod The module handle.
848 */
849RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod)
850{
851 PRTDBGMODINT pDbgMod = hDbgMod;
852 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
853 RTDBGMOD_LOCK(pDbgMod);
854
855 RTDBGSEGIDX cSegs = pDbgMod->pDbgVt->pfnSegmentCount(pDbgMod);
856
857 RTDBGMOD_UNLOCK(pDbgMod);
858 return cSegs;
859}
860RT_EXPORT_SYMBOL(RTDbgModSegmentCount);
861
862
863/**
864 * Query information about a segment.
865 *
866 * This can be used together with RTDbgModSegmentCount to enumerate segments.
867 * The index starts a 0 and stops one below RTDbgModSegmentCount.
868 *
869 * @returns IPRT status code.
870 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high.
871 * @retval VERR_DBG_SPECIAL_SEGMENT if iSeg indicates a special segment.
872 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
873 *
874 * @param hDbgMod The module handle.
875 * @param iSeg The segment index. No special segments.
876 * @param pSegInfo Where to return the segment info. The
877 * RTDBGSEGMENT::Address member will be set to
878 * RTUINTPTR_MAX or the load address used at link time.
879 */
880RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
881{
882 AssertMsgReturn(iSeg <= RTDBGSEGIDX_LAST, ("%#x\n", iSeg), VERR_DBG_SPECIAL_SEGMENT);
883 PRTDBGMODINT pDbgMod = hDbgMod;
884 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
885 RTDBGMOD_LOCK(pDbgMod);
886
887 int rc = pDbgMod->pDbgVt->pfnSegmentByIndex(pDbgMod, iSeg, pSegInfo);
888
889 RTDBGMOD_UNLOCK(pDbgMod);
890 return rc;
891}
892RT_EXPORT_SYMBOL(RTDbgModSegmentByIndex);
893
894
895/**
896 * Gets the size of a segment.
897 *
898 * This is a just a wrapper around RTDbgModSegmentByIndex.
899 *
900 * @returns The segment size.
901 * RTUINTPTR_MAX is returned if either the handle and segment index are
902 * invalid.
903 *
904 * @param hDbgMod The module handle.
905 * @param iSeg The segment index. RTDBGSEGIDX_ABS is not allowed.
906 * If RTDBGSEGIDX_RVA is used, the functions returns
907 * the same value as RTDbgModImageSize.
908 */
909RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
910{
911 if (iSeg == RTDBGSEGIDX_RVA)
912 return RTDbgModImageSize(hDbgMod);
913 RTDBGSEGMENT SegInfo;
914 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
915 return RT_SUCCESS(rc) ? SegInfo.cb : RTUINTPTR_MAX;
916}
917RT_EXPORT_SYMBOL(RTDbgModSegmentSize);
918
919
920/**
921 * Gets the image relative address of a segment.
922 *
923 * This is a just a wrapper around RTDbgModSegmentByIndex.
924 *
925 * @returns The segment relative address.
926 * RTUINTPTR_MAX is returned if either the handle and segment index are
927 * invalid.
928 *
929 * @param hDbgMod The module handle.
930 * @param iSeg The segment index. No special segment indexes
931 * allowed (asserted).
932 */
933RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
934{
935 RTDBGSEGMENT SegInfo;
936 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
937 return RT_SUCCESS(rc) ? SegInfo.uRva : RTUINTPTR_MAX;
938}
939RT_EXPORT_SYMBOL(RTDbgModSegmentRva);
940
941
942/**
943 * Adds a line number to the module.
944 *
945 * @returns IPRT status code.
946 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
947 * custom symbols. This is a common place occurrence.
948 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
949 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
950 * short.
951 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
952 * it's not inside any of the segments defined by the module.
953 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
954 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
955 * end of the segment.
956 * @retval VERR_DBG_ADDRESS_WRAP if off+cb wraps around.
957 * @retval VERR_INVALID_PARAMETER if the symbol flags sets undefined bits.
958 *
959 * @param hDbgMod The module handle.
960 * @param pszSymbol The symbol name.
961 * @param iSeg The segment index.
962 * @param off The segment offset.
963 * @param cb The size of the symbol. Can be zero, although this
964 * may depend somewhat on the debug interpreter.
965 * @param fFlags Symbol flags. Reserved for the future, MBZ.
966 * @param piOrdinal Where to return the symbol ordinal on success. If
967 * the interpreter doesn't do ordinals, this will be set to
968 * UINT32_MAX. Optional.
969 */
970RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off,
971 RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
972{
973 /*
974 * Validate input.
975 */
976 PRTDBGMODINT pDbgMod = hDbgMod;
977 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
978 AssertPtr(pszSymbol);
979 size_t cchSymbol = strlen(pszSymbol);
980 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
981 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
982 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
983 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
984 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
985 ("%#x\n", iSeg),
986 VERR_DBG_INVALID_SEGMENT_INDEX);
987 AssertMsgReturn(off + cb >= off, ("off=%RTptr cb=%RTptr\n", off, cb), VERR_DBG_ADDRESS_WRAP);
988 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
989
990 RTDBGMOD_LOCK(pDbgMod);
991
992 /*
993 * Convert RVAs.
994 */
995 if (iSeg == RTDBGSEGIDX_RVA)
996 {
997 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
998 if (iSeg == NIL_RTDBGSEGIDX)
999 {
1000 RTDBGMOD_UNLOCK(pDbgMod);
1001 return VERR_DBG_INVALID_RVA;
1002 }
1003 }
1004
1005 /*
1006 * Get down to business.
1007 */
1008 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
1009
1010 RTDBGMOD_UNLOCK(pDbgMod);
1011 return rc;
1012}
1013RT_EXPORT_SYMBOL(RTDbgModSymbolAdd);
1014
1015
1016/**
1017 * Gets the symbol count.
1018 *
1019 * This can be used together wtih RTDbgModSymbolByOrdinal or
1020 * RTDbgModSymbolByOrdinalA to enumerate all the symbols.
1021 *
1022 * @returns The number of symbols in the module.
1023 * UINT32_MAX is returned if the module handle is invalid or some other
1024 * error occurs.
1025 *
1026 * @param hDbgMod The module handle.
1027 */
1028RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
1029{
1030 PRTDBGMODINT pDbgMod = hDbgMod;
1031 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1032 RTDBGMOD_LOCK(pDbgMod);
1033
1034 uint32_t cSymbols = pDbgMod->pDbgVt->pfnSymbolCount(pDbgMod);
1035
1036 RTDBGMOD_UNLOCK(pDbgMod);
1037 return cSymbols;
1038}
1039RT_EXPORT_SYMBOL(RTDbgModSymbolCount);
1040
1041
1042/**
1043 * Queries symbol information by ordinal number.
1044 *
1045 * @returns IPRT status code.
1046 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
1047 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1048 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1049 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
1050 *
1051 * @param hDbgMod The module handle.
1052 * @param iOrdinal The symbol ordinal number. 0-based. The highest
1053 * number is RTDbgModSymbolCount() - 1.
1054 * @param pSymInfo Where to store the symbol information.
1055 */
1056RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
1057{
1058 PRTDBGMODINT pDbgMod = hDbgMod;
1059 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1060 RTDBGMOD_LOCK(pDbgMod);
1061
1062 int rc = pDbgMod->pDbgVt->pfnSymbolByOrdinal(pDbgMod, iOrdinal, pSymInfo);
1063
1064 RTDBGMOD_UNLOCK(pDbgMod);
1065 return rc;
1066}
1067RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinal);
1068
1069
1070/**
1071 * Queries symbol information by ordinal number.
1072 *
1073 * @returns IPRT status code.
1074 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1075 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
1076 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
1077 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1078 *
1079 * @param hDbgMod The module handle.
1080 * @param iOrdinal The symbol ordinal number. 0-based. The highest
1081 * number is RTDbgModSymbolCount() - 1.
1082 * @param ppSymInfo Where to store the pointer to the returned
1083 * symbol information. Always set. Free with
1084 * RTDbgSymbolFree.
1085 */
1086RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo)
1087{
1088 AssertPtr(ppSymInfo);
1089 *ppSymInfo = NULL;
1090
1091 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1092 if (!pSymInfo)
1093 return VERR_NO_MEMORY;
1094
1095 int rc = RTDbgModSymbolByOrdinal(hDbgMod, iOrdinal, pSymInfo);
1096
1097 if (RT_SUCCESS(rc))
1098 *ppSymInfo = pSymInfo;
1099 else
1100 RTDbgSymbolFree(pSymInfo);
1101 return rc;
1102}
1103RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinalA);
1104
1105
1106/**
1107 * Queries symbol information by address.
1108 *
1109 * The returned symbol is what the debug info interpreter considers the symbol
1110 * most applicable to the specified address. This usually means a symbol with an
1111 * address equal or lower than the requested.
1112 *
1113 * @returns IPRT status code.
1114 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1115 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1116 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1117 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1118 * it's not inside any of the segments defined by the module.
1119 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1120 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1121 * end of the segment.
1122 * @retval VERR_INVALID_PARAMETER if incorrect flags.
1123 *
1124 * @param hDbgMod The module handle.
1125 * @param iSeg The segment number.
1126 * @param off The offset into the segment.
1127 * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
1128 * @param poffDisp Where to store the distance between the
1129 * specified address and the returned symbol.
1130 * Optional.
1131 * @param pSymInfo Where to store the symbol information.
1132 */
1133RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1134 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
1135{
1136 /*
1137 * Validate input.
1138 */
1139 PRTDBGMODINT pDbgMod = hDbgMod;
1140 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1141 AssertPtrNull(poffDisp);
1142 AssertPtr(pSymInfo);
1143 AssertReturn(!(fFlags & ~RTDBGSYMADDR_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
1144
1145 RTDBGMOD_LOCK(pDbgMod);
1146
1147 /*
1148 * Convert RVAs.
1149 */
1150 if (iSeg == RTDBGSEGIDX_RVA)
1151 {
1152 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1153 if (iSeg == NIL_RTDBGSEGIDX)
1154 {
1155 RTDBGMOD_UNLOCK(pDbgMod);
1156 return VERR_DBG_INVALID_RVA;
1157 }
1158 }
1159
1160 /*
1161 * Get down to business.
1162 */
1163 int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1164
1165 RTDBGMOD_UNLOCK(pDbgMod);
1166 return rc;
1167}
1168RT_EXPORT_SYMBOL(RTDbgModSymbolByAddr);
1169
1170
1171/**
1172 * Queries symbol information by address.
1173 *
1174 * The returned symbol is what the debug info interpreter considers the symbol
1175 * most applicable to the specified address. This usually means a symbol with an
1176 * address equal or lower than the requested.
1177 *
1178 * @returns IPRT status code.
1179 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1180 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1181 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1182 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1183 * it's not inside any of the segments defined by the module.
1184 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1185 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1186 * end of the segment.
1187 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1188 * @retval VERR_INVALID_PARAMETER if incorrect flags.
1189 *
1190 * @param hDbgMod The module handle.
1191 * @param iSeg The segment index.
1192 * @param off The offset into the segment.
1193 * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
1194 * @param poffDisp Where to store the distance between the
1195 * specified address and the returned symbol. Optional.
1196 * @param ppSymInfo Where to store the pointer to the returned
1197 * symbol information. Always set. Free with
1198 * RTDbgSymbolFree.
1199 */
1200RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1201 PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo)
1202{
1203 AssertPtr(ppSymInfo);
1204 *ppSymInfo = NULL;
1205
1206 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1207 if (!pSymInfo)
1208 return VERR_NO_MEMORY;
1209
1210 int rc = RTDbgModSymbolByAddr(hDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1211
1212 if (RT_SUCCESS(rc))
1213 *ppSymInfo = pSymInfo;
1214 else
1215 RTDbgSymbolFree(pSymInfo);
1216 return rc;
1217}
1218RT_EXPORT_SYMBOL(RTDbgModSymbolByAddrA);
1219
1220
1221/**
1222 * Queries symbol information by symbol name.
1223 *
1224 * @returns IPRT status code.
1225 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1226 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1227 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1228 * short.
1229 *
1230 * @param hDbgMod The module handle.
1231 * @param pszSymbol The symbol name.
1232 * @param pSymInfo Where to store the symbol information.
1233 */
1234RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo)
1235{
1236 /*
1237 * Validate input.
1238 */
1239 PRTDBGMODINT pDbgMod = hDbgMod;
1240 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1241 AssertPtr(pszSymbol);
1242 size_t cchSymbol = strlen(pszSymbol);
1243 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1244 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1245 AssertPtr(pSymInfo);
1246
1247 /*
1248 * Make the query.
1249 */
1250 RTDBGMOD_LOCK(pDbgMod);
1251 int rc = pDbgMod->pDbgVt->pfnSymbolByName(pDbgMod, pszSymbol, cchSymbol, pSymInfo);
1252 RTDBGMOD_UNLOCK(pDbgMod);
1253
1254 return rc;
1255}
1256RT_EXPORT_SYMBOL(RTDbgModSymbolByName);
1257
1258
1259/**
1260 * Queries symbol information by symbol name.
1261 *
1262 * @returns IPRT status code.
1263 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1264 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1265 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1266 * short.
1267 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1268 *
1269 * @param hDbgMod The module handle.
1270 * @param pszSymbol The symbol name.
1271 * @param ppSymInfo Where to store the pointer to the returned
1272 * symbol information. Always set. Free with
1273 * RTDbgSymbolFree.
1274 */
1275RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo)
1276{
1277 AssertPtr(ppSymInfo);
1278 *ppSymInfo = NULL;
1279
1280 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1281 if (!pSymInfo)
1282 return VERR_NO_MEMORY;
1283
1284 int rc = RTDbgModSymbolByName(hDbgMod, pszSymbol, pSymInfo);
1285
1286 if (RT_SUCCESS(rc))
1287 *ppSymInfo = pSymInfo;
1288 else
1289 RTDbgSymbolFree(pSymInfo);
1290 return rc;
1291}
1292RT_EXPORT_SYMBOL(RTDbgModSymbolByNameA);
1293
1294
1295/**
1296 * Adds a line number to the module.
1297 *
1298 * @returns IPRT status code.
1299 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
1300 * custom symbols. This should be consider a normal response.
1301 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1302 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE if the file name is too longer or
1303 * empty.
1304 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1305 * it's not inside any of the segments defined by the module.
1306 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1307 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1308 * end of the segment.
1309 * @retval VERR_INVALID_PARAMETER if the line number flags sets undefined bits.
1310 *
1311 * @param hDbgMod The module handle.
1312 * @param pszFile The file name.
1313 * @param uLineNo The line number.
1314 * @param iSeg The segment index.
1315 * @param off The segment offset.
1316 * @param piOrdinal Where to return the line number ordinal on
1317 * success. If the interpreter doesn't do ordinals,
1318 * this will be set to UINT32_MAX. Optional.
1319 */
1320RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo,
1321 RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
1322{
1323 /*
1324 * Validate input.
1325 */
1326 PRTDBGMODINT pDbgMod = hDbgMod;
1327 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1328 AssertPtr(pszFile);
1329 size_t cchFile = strlen(pszFile);
1330 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1331 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1332 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
1333 || iSeg == RTDBGSEGIDX_RVA,
1334 ("%#x\n", iSeg),
1335 VERR_DBG_INVALID_SEGMENT_INDEX);
1336 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
1337
1338 RTDBGMOD_LOCK(pDbgMod);
1339
1340 /*
1341 * Convert RVAs.
1342 */
1343 if (iSeg == RTDBGSEGIDX_RVA)
1344 {
1345 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1346 if (iSeg == NIL_RTDBGSEGIDX)
1347 {
1348 RTDBGMOD_UNLOCK(pDbgMod);
1349 return VERR_DBG_INVALID_RVA;
1350 }
1351 }
1352
1353 /*
1354 * Get down to business.
1355 */
1356 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
1357
1358 RTDBGMOD_UNLOCK(pDbgMod);
1359 return rc;
1360}
1361RT_EXPORT_SYMBOL(RTDbgModLineAdd);
1362
1363
1364/**
1365 * Gets the line number count.
1366 *
1367 * This can be used together wtih RTDbgModLineByOrdinal or RTDbgModSymbolByLineA
1368 * to enumerate all the line number information.
1369 *
1370 * @returns The number of line numbers in the module.
1371 * UINT32_MAX is returned if the module handle is invalid or some other
1372 * error occurs.
1373 *
1374 * @param hDbgMod The module handle.
1375 */
1376RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod)
1377{
1378 PRTDBGMODINT pDbgMod = hDbgMod;
1379 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1380 RTDBGMOD_LOCK(pDbgMod);
1381
1382 uint32_t cLineNumbers = pDbgMod->pDbgVt->pfnLineCount(pDbgMod);
1383
1384 RTDBGMOD_UNLOCK(pDbgMod);
1385 return cLineNumbers;
1386}
1387RT_EXPORT_SYMBOL(RTDbgModLineCount);
1388
1389
1390/**
1391 * Queries line number information by ordinal number.
1392 *
1393 * This can be used to enumerate the line numbers for the module. Use
1394 * RTDbgModLineCount() to figure the end of the ordinals.
1395 *
1396 * @returns IPRT status code.
1397 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1398 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1399 * ordinal.
1400 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1401
1402 * @param hDbgMod The module handle.
1403 * @param iOrdinal The line number ordinal number.
1404 * @param pLineInfo Where to store the information about the line
1405 * number.
1406 */
1407RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
1408{
1409 PRTDBGMODINT pDbgMod = hDbgMod;
1410 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1411 RTDBGMOD_LOCK(pDbgMod);
1412
1413 int rc = pDbgMod->pDbgVt->pfnLineByOrdinal(pDbgMod, iOrdinal, pLineInfo);
1414
1415 RTDBGMOD_UNLOCK(pDbgMod);
1416 return rc;
1417}
1418RT_EXPORT_SYMBOL(RTDbgModLineByOrdinal);
1419
1420
1421/**
1422 * Queries line number information by ordinal number.
1423 *
1424 * This can be used to enumerate the line numbers for the module. Use
1425 * RTDbgModLineCount() to figure the end of the ordinals.
1426 *
1427 * @returns IPRT status code.
1428 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1429 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1430 * ordinal.
1431 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1432 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1433 *
1434 * @param hDbgMod The module handle.
1435 * @param iOrdinal The line number ordinal number.
1436 * @param ppLineInfo Where to store the pointer to the returned line
1437 * number information. Always set. Free with
1438 * RTDbgLineFree.
1439 */
1440RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo)
1441{
1442 AssertPtr(ppLineInfo);
1443 *ppLineInfo = NULL;
1444
1445 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1446 if (!pLineInfo)
1447 return VERR_NO_MEMORY;
1448
1449 int rc = RTDbgModLineByOrdinal(hDbgMod, iOrdinal, pLineInfo);
1450
1451 if (RT_SUCCESS(rc))
1452 *ppLineInfo = pLineInfo;
1453 else
1454 RTDbgLineFree(pLineInfo);
1455 return rc;
1456}
1457RT_EXPORT_SYMBOL(RTDbgModLineByOrdinalA);
1458
1459
1460/**
1461 * Queries line number information by address.
1462 *
1463 * The returned line number is what the debug info interpreter considers the
1464 * one most applicable to the specified address. This usually means a line
1465 * number with an address equal or lower than the requested.
1466 *
1467 * @returns IPRT status code.
1468 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1469 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1470 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1471 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1472 * it's not inside any of the segments defined by the module.
1473 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1474 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1475 * end of the segment.
1476 *
1477 * @param hDbgMod The module handle.
1478 * @param iSeg The segment number.
1479 * @param off The offset into the segment.
1480 * @param poffDisp Where to store the distance between the
1481 * specified address and the returned symbol.
1482 * Optional.
1483 * @param pLineInfo Where to store the line number information.
1484 */
1485RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
1486{
1487 /*
1488 * Validate input.
1489 */
1490 PRTDBGMODINT pDbgMod = hDbgMod;
1491 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1492 AssertPtrNull(poffDisp);
1493 AssertPtr(pLineInfo);
1494
1495 RTDBGMOD_LOCK(pDbgMod);
1496
1497 /*
1498 * Convert RVAs.
1499 */
1500 if (iSeg == RTDBGSEGIDX_RVA)
1501 {
1502 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1503 if (iSeg == NIL_RTDBGSEGIDX)
1504 {
1505 RTDBGMOD_UNLOCK(pDbgMod);
1506 return VERR_DBG_INVALID_RVA;
1507 }
1508 }
1509
1510 int rc = pDbgMod->pDbgVt->pfnLineByAddr(pDbgMod, iSeg, off, poffDisp, pLineInfo);
1511
1512 RTDBGMOD_UNLOCK(pDbgMod);
1513 return rc;
1514}
1515RT_EXPORT_SYMBOL(RTDbgModLineByAddr);
1516
1517
1518/**
1519 * Queries line number information by address.
1520 *
1521 * The returned line number is what the debug info interpreter considers the
1522 * one most applicable to the specified address. This usually means a line
1523 * number with an address equal or lower than the requested.
1524 *
1525 * @returns IPRT status code.
1526 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1527 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1528 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1529 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1530 * it's not inside any of the segments defined by the module.
1531 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1532 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1533 * end of the segment.
1534 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1535 *
1536 * @param hDbgMod The module handle.
1537 * @param iSeg The segment number.
1538 * @param off The offset into the segment.
1539 * @param poffDisp Where to store the distance between the
1540 * specified address and the returned symbol.
1541 * Optional.
1542 * @param ppLineInfo Where to store the pointer to the returned line
1543 * number information. Always set. Free with
1544 * RTDbgLineFree.
1545 */
1546RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo)
1547{
1548 AssertPtr(ppLineInfo);
1549 *ppLineInfo = NULL;
1550
1551 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1552 if (!pLineInfo)
1553 return VERR_NO_MEMORY;
1554
1555 int rc = RTDbgModLineByAddr(hDbgMod, iSeg, off, poffDisp, pLineInfo);
1556
1557 if (RT_SUCCESS(rc))
1558 *ppLineInfo = pLineInfo;
1559 else
1560 RTDbgLineFree(pLineInfo);
1561 return rc;
1562}
1563RT_EXPORT_SYMBOL(RTDbgModLineByAddrA);
1564
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette