VirtualBox

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

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

RTDbgCfg: Debugging configuration, like symbol search paths and such.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.9 KB
Line 
1/* $Id: dbgmod.cpp 45984 2013-05-11 12:46:30Z vboxsync $ */
2/** @file
3 * IPRT - Debug Module Interpreter.
4 */
5
6/*
7 * Copyright (C) 2009-2012 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) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTDBGCFG hDbgCfg)
367{
368 /*
369 * Input validation and lazy initialization.
370 */
371 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
372 *phDbgMod = NIL_RTDBGMOD;
373 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
374 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
375 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
376
377 int rc = rtDbgModLazyInit();
378 if (RT_FAILURE(rc))
379 return rc;
380
381 if (!pszName)
382 pszName = RTPathFilename(pszFilename);
383
384 /*
385 * Allocate a new module instance.
386 */
387 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
388 if (!pDbgMod)
389 return VERR_NO_MEMORY;
390 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
391 pDbgMod->cRefs = 1;
392 rc = RTCritSectInit(&pDbgMod->CritSect);
393 if (RT_SUCCESS(rc))
394 {
395 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
396 if (pDbgMod->pszName)
397 {
398 pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
399 if (pDbgMod->pszImgFile)
400 {
401 /*
402 * Find an image reader which groks the file.
403 */
404 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
405 if (RT_SUCCESS(rc))
406 {
407 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
408 PRTDBGMODREGIMG pImg;
409 for (pImg = g_pImgHead; pImg; pImg = pImg->pNext)
410 {
411 pDbgMod->pImgVt = pImg->pVt;
412 pDbgMod->pvImgPriv = NULL;
413 rc = pImg->pVt->pfnTryOpen(pDbgMod);
414 if (RT_SUCCESS(rc))
415 {
416 /*
417 * Find a debug info interpreter.
418 */
419 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
420 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
421 {
422 pDbgMod->pDbgVt = pDbg->pVt;
423 pDbgMod->pvDbgPriv = NULL;
424 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
425 if (RT_SUCCESS(rc))
426 {
427 /*
428 * That's it!
429 */
430 ASMAtomicIncU32(&pDbg->cUsers);
431 ASMAtomicIncU32(&pImg->cUsers);
432 RTSemRWReleaseRead(g_hDbgModRWSem);
433
434 *phDbgMod = pDbgMod;
435 return rc;
436 }
437 }
438
439 /*
440 * Image detected, but found no debug info we were
441 * able to understand.
442 */
443 /** @todo Fall back on exported symbols! */
444 pDbgMod->pImgVt->pfnClose(pDbgMod);
445 break;
446 }
447 }
448
449 /*
450 * Could it be a file containing raw debug info?
451 */
452 if (!pImg)
453 {
454 pDbgMod->pImgVt = NULL;
455 pDbgMod->pvImgPriv = NULL;
456 pDbgMod->pszDbgFile = pDbgMod->pszImgFile;
457 pDbgMod->pszImgFile = NULL;
458
459 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
460 {
461 pDbgMod->pDbgVt = pDbg->pVt;
462 pDbgMod->pvDbgPriv = NULL;
463 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
464 if (RT_SUCCESS(rc))
465 {
466 /*
467 * That's it!
468 */
469 ASMAtomicIncU32(&pDbg->cUsers);
470 RTSemRWReleaseRead(g_hDbgModRWSem);
471
472 *phDbgMod = pDbgMod;
473 return rc;
474 }
475 }
476
477 pDbgMod->pszImgFile = pDbgMod->pszDbgFile;
478 pDbgMod->pszDbgFile = NULL;
479 }
480
481 /* bail out */
482 RTSemRWReleaseRead(g_hDbgModRWSem);
483 }
484 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
485 }
486 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
487 }
488 RTCritSectDelete(&pDbgMod->CritSect);
489 }
490
491 RTMemFree(pDbgMod);
492 return rc;
493}
494RT_EXPORT_SYMBOL(RTDbgModCreateFromImage);
495
496
497
498RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
499 RTUINTPTR uSubtrahend, RTDBGCFG hDbgCfg)
500{
501 /*
502 * Input validation and lazy initialization.
503 */
504 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
505 *phDbgMod = NIL_RTDBGMOD;
506 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
507 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
508 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
509 AssertReturn(uSubtrahend == 0, VERR_NOT_IMPLEMENTED); /** @todo implement uSubtrahend. */
510
511 int rc = rtDbgModLazyInit();
512 if (RT_FAILURE(rc))
513 return rc;
514
515 if (!pszName)
516 pszName = RTPathFilename(pszFilename);
517
518 /*
519 * Allocate a new module instance.
520 */
521 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
522 if (!pDbgMod)
523 return VERR_NO_MEMORY;
524 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
525 pDbgMod->cRefs = 1;
526 rc = RTCritSectInit(&pDbgMod->CritSect);
527 if (RT_SUCCESS(rc))
528 {
529 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
530 if (pDbgMod->pszName)
531 {
532 pDbgMod->pszDbgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
533 if (pDbgMod->pszDbgFile)
534 {
535 /*
536 * Try the map file readers.
537 */
538 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
539 if (RT_SUCCESS(rc))
540 {
541 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
542 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
543 {
544 if (pCur->pVt->fSupports & RT_DBGTYPE_MAP)
545 {
546 pDbgMod->pDbgVt = pCur->pVt;
547 pDbgMod->pvDbgPriv = NULL;
548 rc = pCur->pVt->pfnTryOpen(pDbgMod);
549 if (RT_SUCCESS(rc))
550 {
551 ASMAtomicIncU32(&pCur->cUsers);
552 RTSemRWReleaseRead(g_hDbgModRWSem);
553
554 *phDbgMod = pDbgMod;
555 return rc;
556 }
557 }
558 }
559
560 /* bail out */
561 RTSemRWReleaseRead(g_hDbgModRWSem);
562 }
563 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
564 }
565 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
566 }
567 RTCritSectDelete(&pDbgMod->CritSect);
568 }
569
570 RTMemFree(pDbgMod);
571 return rc;
572}
573RT_EXPORT_SYMBOL(RTDbgModCreateFromMap);
574
575
576/**
577 * Destroys an module after the reference count has reached zero.
578 *
579 * @param pDbgMod The module instance.
580 */
581static void rtDbgModDestroy(PRTDBGMODINT pDbgMod)
582{
583 /*
584 * Close the debug info interpreter first, then the image interpret.
585 */
586 RTCritSectEnter(&pDbgMod->CritSect); /* paranoia */
587
588 if (pDbgMod->pDbgVt)
589 {
590 pDbgMod->pDbgVt->pfnClose(pDbgMod);
591 pDbgMod->pDbgVt = NULL;
592 pDbgMod->pvDbgPriv = NULL;
593 }
594
595 if (pDbgMod->pImgVt)
596 {
597 pDbgMod->pImgVt->pfnClose(pDbgMod);
598 pDbgMod->pImgVt = NULL;
599 pDbgMod->pvImgPriv = NULL;
600 }
601
602 /*
603 * Free the resources.
604 */
605 ASMAtomicWriteU32(&pDbgMod->u32Magic, ~RTDBGMOD_MAGIC);
606 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
607 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
608 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
609 RTCritSectLeave(&pDbgMod->CritSect); /* paranoia */
610 RTCritSectDelete(&pDbgMod->CritSect);
611 RTMemFree(pDbgMod);
612}
613
614
615/**
616 * Retains another reference to the module.
617 *
618 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
619 *
620 * @param hDbgMod The module handle.
621 *
622 * @remarks Will not take any locks.
623 */
624RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod)
625{
626 PRTDBGMODINT pDbgMod = hDbgMod;
627 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
628 return ASMAtomicIncU32(&pDbgMod->cRefs);
629}
630RT_EXPORT_SYMBOL(RTDbgModRetain);
631
632
633/**
634 * Release a reference to the module.
635 *
636 * When the reference count reaches zero, the module is destroyed.
637 *
638 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
639 *
640 * @param hDbgMod The module handle. The NIL handle is quietly ignored
641 * and 0 is returned.
642 *
643 * @remarks Will not take any locks.
644 */
645RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod)
646{
647 if (hDbgMod == NIL_RTDBGMOD)
648 return 0;
649 PRTDBGMODINT pDbgMod = hDbgMod;
650 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
651
652 uint32_t cRefs = ASMAtomicDecU32(&pDbgMod->cRefs);
653 if (!cRefs)
654 rtDbgModDestroy(pDbgMod);
655 return cRefs;
656}
657RT_EXPORT_SYMBOL(RTDbgModRelease);
658
659
660/**
661 * Gets the module name.
662 *
663 * @returns Pointer to a read only string containing the name.
664 *
665 * @param hDbgMod The module handle.
666 */
667RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod)
668{
669 PRTDBGMODINT pDbgMod = hDbgMod;
670 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
671 return pDbgMod->pszName;
672}
673RT_EXPORT_SYMBOL(RTDbgModName);
674
675
676/**
677 * Converts an image relative address to a segment:offset address.
678 *
679 * @returns Segment index on success.
680 * NIL_RTDBGSEGIDX is returned if the module handle or the RVA are
681 * invalid.
682 *
683 * @param hDbgMod The module handle.
684 * @param uRva The image relative address to convert.
685 * @param poffSeg Where to return the segment offset. Optional.
686 */
687RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
688{
689 PRTDBGMODINT pDbgMod = hDbgMod;
690 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
691 RTDBGMOD_LOCK(pDbgMod);
692
693 RTDBGSEGIDX iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, uRva, poffSeg);
694
695 RTDBGMOD_UNLOCK(pDbgMod);
696 return iSeg;
697}
698RT_EXPORT_SYMBOL(RTDbgModRvaToSegOff);
699
700
701/**
702 * Image size when mapped if segments are mapped adjacently.
703 *
704 * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and
705 * NE and such it's a bit odder and the answer may not make much sense for them.
706 *
707 * @returns Image mapped size.
708 * RTUINTPTR_MAX is returned if the handle is invalid.
709 *
710 * @param hDbgMod The module handle.
711 */
712RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod)
713{
714 PRTDBGMODINT pDbgMod = hDbgMod;
715 RTDBGMOD_VALID_RETURN_RC(pDbgMod, RTUINTPTR_MAX);
716 RTDBGMOD_LOCK(pDbgMod);
717
718 RTUINTPTR cbImage = pDbgMod->pDbgVt->pfnImageSize(pDbgMod);
719
720 RTDBGMOD_UNLOCK(pDbgMod);
721 return cbImage;
722}
723RT_EXPORT_SYMBOL(RTDbgModImageSize);
724
725
726/**
727 * Gets the module tag value if any.
728 *
729 * @returns The tag. 0 if hDbgMod is invalid.
730 *
731 * @param hDbgMod The module handle.
732 */
733RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod)
734{
735 PRTDBGMODINT pDbgMod = hDbgMod;
736 RTDBGMOD_VALID_RETURN_RC(pDbgMod, 0);
737 return pDbgMod->uTag;
738}
739RT_EXPORT_SYMBOL(RTDbgModGetTag);
740
741
742/**
743 * Tags or untags the module.
744 *
745 * @returns IPRT status code.
746 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
747 *
748 * @param hDbgMod The module handle.
749 * @param uTag The tag value. The convention is that 0 is no tag
750 * and any other value means it's tagged. It's adviced
751 * to use some kind of unique number like an address
752 * (global or string cache for instance) to avoid
753 * collisions with other users
754 */
755RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag)
756{
757 PRTDBGMODINT pDbgMod = hDbgMod;
758 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
759 RTDBGMOD_LOCK(pDbgMod);
760
761 pDbgMod->uTag = uTag;
762
763 RTDBGMOD_UNLOCK(pDbgMod);
764 return VINF_SUCCESS;
765}
766RT_EXPORT_SYMBOL(RTDbgModSetTag);
767
768
769/**
770 * Adds a segment to the module. Optional feature.
771 *
772 * This method is intended used for manually constructing debug info for a
773 * module. The main usage is from other debug info interpreters that want to
774 * avoid writing a debug info database and instead uses the standard container
775 * behind the scenes.
776 *
777 * @returns IPRT status code.
778 * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info
779 * interpreter. This is a common return code.
780 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
781 * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around.
782 * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long.
783 * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags.
784 * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment.
785 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations.
786 *
787 * @param hDbgMod The module handle.
788 * @param uRva The image relative address of the segment.
789 * @param cb The size of the segment.
790 * @param pszName The segment name. Does not normally need to be
791 * unique, although this is somewhat up to the
792 * debug interpreter to decide.
793 * @param fFlags Segment flags. Reserved for future used, MBZ.
794 * @param piSeg The segment index or NIL_RTDBGSEGIDX on input.
795 * The assigned segment index on successful return.
796 * Optional.
797 */
798RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
799 uint32_t fFlags, PRTDBGSEGIDX piSeg)
800{
801 /*
802 * Validate input.
803 */
804 PRTDBGMODINT pDbgMod = hDbgMod;
805 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
806 AssertMsgReturn(uRva + cb >= uRva, ("uRva=%RTptr cb=%RTptr\n", uRva, cb), VERR_DBG_ADDRESS_WRAP);
807 Assert(*pszName);
808 size_t cchName = strlen(pszName);
809 AssertReturn(cchName > 0, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
810 AssertReturn(cchName < RTDBG_SEGMENT_NAME_LENGTH, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
811 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
812 AssertPtrNull(piSeg);
813 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg <= RTDBGSEGIDX_LAST, ("%#x\n", *piSeg), VERR_DBG_SPECIAL_SEGMENT);
814
815 /*
816 * Do the deed.
817 */
818 RTDBGMOD_LOCK(pDbgMod);
819 int rc = pDbgMod->pDbgVt->pfnSegmentAdd(pDbgMod, uRva, cb, pszName, cchName, fFlags, piSeg);
820 RTDBGMOD_UNLOCK(pDbgMod);
821
822 return rc;
823
824}
825RT_EXPORT_SYMBOL(RTDbgModSegmentAdd);
826
827
828/**
829 * Gets the number of segments in the module.
830 *
831 * This is can be used to determine the range which can be passed to
832 * RTDbgModSegmentByIndex and derivatives.
833 *
834 * @returns The segment relative address.
835 * NIL_RTDBGSEGIDX if the handle is invalid.
836 *
837 * @param hDbgMod The module handle.
838 */
839RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod)
840{
841 PRTDBGMODINT pDbgMod = hDbgMod;
842 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
843 RTDBGMOD_LOCK(pDbgMod);
844
845 RTDBGSEGIDX cSegs = pDbgMod->pDbgVt->pfnSegmentCount(pDbgMod);
846
847 RTDBGMOD_UNLOCK(pDbgMod);
848 return cSegs;
849}
850RT_EXPORT_SYMBOL(RTDbgModSegmentCount);
851
852
853/**
854 * Query information about a segment.
855 *
856 * This can be used together with RTDbgModSegmentCount to enumerate segments.
857 * The index starts a 0 and stops one below RTDbgModSegmentCount.
858 *
859 * @returns IPRT status code.
860 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high.
861 * @retval VERR_DBG_SPECIAL_SEGMENT if iSeg indicates a special segment.
862 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
863 *
864 * @param hDbgMod The module handle.
865 * @param iSeg The segment index. No special segments.
866 * @param pSegInfo Where to return the segment info. The
867 * RTDBGSEGMENT::Address member will be set to
868 * RTUINTPTR_MAX or the load address used at link time.
869 */
870RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
871{
872 AssertMsgReturn(iSeg <= RTDBGSEGIDX_LAST, ("%#x\n", iSeg), VERR_DBG_SPECIAL_SEGMENT);
873 PRTDBGMODINT pDbgMod = hDbgMod;
874 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
875 RTDBGMOD_LOCK(pDbgMod);
876
877 int rc = pDbgMod->pDbgVt->pfnSegmentByIndex(pDbgMod, iSeg, pSegInfo);
878
879 RTDBGMOD_UNLOCK(pDbgMod);
880 return rc;
881}
882RT_EXPORT_SYMBOL(RTDbgModSegmentByIndex);
883
884
885/**
886 * Gets the size of a segment.
887 *
888 * This is a just a wrapper around RTDbgModSegmentByIndex.
889 *
890 * @returns The segment size.
891 * RTUINTPTR_MAX is returned if either the handle and segment index are
892 * invalid.
893 *
894 * @param hDbgMod The module handle.
895 * @param iSeg The segment index. RTDBGSEGIDX_ABS is not allowed.
896 * If RTDBGSEGIDX_RVA is used, the functions returns
897 * the same value as RTDbgModImageSize.
898 */
899RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
900{
901 if (iSeg == RTDBGSEGIDX_RVA)
902 return RTDbgModImageSize(hDbgMod);
903 RTDBGSEGMENT SegInfo;
904 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
905 return RT_SUCCESS(rc) ? SegInfo.cb : RTUINTPTR_MAX;
906}
907RT_EXPORT_SYMBOL(RTDbgModSegmentSize);
908
909
910/**
911 * Gets the image relative address of a segment.
912 *
913 * This is a just a wrapper around RTDbgModSegmentByIndex.
914 *
915 * @returns The segment relative address.
916 * RTUINTPTR_MAX is returned if either the handle and segment index are
917 * invalid.
918 *
919 * @param hDbgMod The module handle.
920 * @param iSeg The segment index. No special segment indexes
921 * allowed (asserted).
922 */
923RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
924{
925 RTDBGSEGMENT SegInfo;
926 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
927 return RT_SUCCESS(rc) ? SegInfo.uRva : RTUINTPTR_MAX;
928}
929RT_EXPORT_SYMBOL(RTDbgModSegmentRva);
930
931
932/**
933 * Adds a line number to the module.
934 *
935 * @returns IPRT status code.
936 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
937 * custom symbols. This is a common place occurrence.
938 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
939 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
940 * short.
941 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
942 * it's not inside any of the segments defined by the module.
943 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
944 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
945 * end of the segment.
946 * @retval VERR_DBG_ADDRESS_WRAP if off+cb wraps around.
947 * @retval VERR_INVALID_PARAMETER if the symbol flags sets undefined bits.
948 *
949 * @param hDbgMod The module handle.
950 * @param pszSymbol The symbol name.
951 * @param iSeg The segment index.
952 * @param off The segment offset.
953 * @param cb The size of the symbol. Can be zero, although this
954 * may depend somewhat on the debug interpreter.
955 * @param fFlags Symbol flags. Reserved for the future, MBZ.
956 * @param piOrdinal Where to return the symbol ordinal on success. If
957 * the interpreter doesn't do ordinals, this will be set to
958 * UINT32_MAX. Optional.
959 */
960RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off,
961 RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
962{
963 /*
964 * Validate input.
965 */
966 PRTDBGMODINT pDbgMod = hDbgMod;
967 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
968 AssertPtr(pszSymbol);
969 size_t cchSymbol = strlen(pszSymbol);
970 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
971 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
972 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
973 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
974 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
975 ("%#x\n", iSeg),
976 VERR_DBG_INVALID_SEGMENT_INDEX);
977 AssertMsgReturn(off + cb >= off, ("off=%RTptr cb=%RTptr\n", off, cb), VERR_DBG_ADDRESS_WRAP);
978 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
979
980 RTDBGMOD_LOCK(pDbgMod);
981
982 /*
983 * Convert RVAs.
984 */
985 if (iSeg == RTDBGSEGIDX_RVA)
986 {
987 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
988 if (iSeg == NIL_RTDBGSEGIDX)
989 {
990 RTDBGMOD_UNLOCK(pDbgMod);
991 return VERR_DBG_INVALID_RVA;
992 }
993 }
994
995 /*
996 * Get down to business.
997 */
998 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
999
1000 RTDBGMOD_UNLOCK(pDbgMod);
1001 return rc;
1002}
1003RT_EXPORT_SYMBOL(RTDbgModSymbolAdd);
1004
1005
1006/**
1007 * Gets the symbol count.
1008 *
1009 * This can be used together wtih RTDbgModSymbolByOrdinal or
1010 * RTDbgModSymbolByOrdinalA to enumerate all the symbols.
1011 *
1012 * @returns The number of symbols in the module.
1013 * UINT32_MAX is returned if the module handle is invalid or some other
1014 * error occurs.
1015 *
1016 * @param hDbgMod The module handle.
1017 */
1018RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
1019{
1020 PRTDBGMODINT pDbgMod = hDbgMod;
1021 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1022 RTDBGMOD_LOCK(pDbgMod);
1023
1024 uint32_t cSymbols = pDbgMod->pDbgVt->pfnSymbolCount(pDbgMod);
1025
1026 RTDBGMOD_UNLOCK(pDbgMod);
1027 return cSymbols;
1028}
1029RT_EXPORT_SYMBOL(RTDbgModSymbolCount);
1030
1031
1032/**
1033 * Queries symbol information by ordinal number.
1034 *
1035 * @returns IPRT status code.
1036 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
1037 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1038 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1039 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
1040 *
1041 * @param hDbgMod The module handle.
1042 * @param iOrdinal The symbol ordinal number. 0-based. The highest
1043 * number is RTDbgModSymbolCount() - 1.
1044 * @param pSymInfo Where to store the symbol information.
1045 */
1046RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
1047{
1048 PRTDBGMODINT pDbgMod = hDbgMod;
1049 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1050 RTDBGMOD_LOCK(pDbgMod);
1051
1052 int rc = pDbgMod->pDbgVt->pfnSymbolByOrdinal(pDbgMod, iOrdinal, pSymInfo);
1053
1054 RTDBGMOD_UNLOCK(pDbgMod);
1055 return rc;
1056}
1057RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinal);
1058
1059
1060/**
1061 * Queries symbol information by ordinal number.
1062 *
1063 * @returns IPRT status code.
1064 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1065 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
1066 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
1067 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1068 *
1069 * @param hDbgMod The module handle.
1070 * @param iOrdinal The symbol ordinal number. 0-based. The highest
1071 * number is RTDbgModSymbolCount() - 1.
1072 * @param ppSymInfo Where to store the pointer to the returned
1073 * symbol information. Always set. Free with
1074 * RTDbgSymbolFree.
1075 */
1076RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo)
1077{
1078 AssertPtr(ppSymInfo);
1079 *ppSymInfo = NULL;
1080
1081 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1082 if (!pSymInfo)
1083 return VERR_NO_MEMORY;
1084
1085 int rc = RTDbgModSymbolByOrdinal(hDbgMod, iOrdinal, pSymInfo);
1086
1087 if (RT_SUCCESS(rc))
1088 *ppSymInfo = pSymInfo;
1089 else
1090 RTDbgSymbolFree(pSymInfo);
1091 return rc;
1092}
1093RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinalA);
1094
1095
1096/**
1097 * Queries symbol information by address.
1098 *
1099 * The returned symbol is what the debug info interpreter considers the symbol
1100 * most applicable to the specified address. This usually means a symbol with an
1101 * address equal or lower than the requested.
1102 *
1103 * @returns IPRT status code.
1104 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1105 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1106 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1107 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1108 * it's not inside any of the segments defined by the module.
1109 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1110 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1111 * end of the segment.
1112 * @retval VERR_INVALID_PARAMETER if incorrect flags.
1113 *
1114 * @param hDbgMod The module handle.
1115 * @param iSeg The segment number.
1116 * @param off The offset into the segment.
1117 * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
1118 * @param poffDisp Where to store the distance between the
1119 * specified address and the returned symbol.
1120 * Optional.
1121 * @param pSymInfo Where to store the symbol information.
1122 */
1123RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1124 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
1125{
1126 /*
1127 * Validate input.
1128 */
1129 PRTDBGMODINT pDbgMod = hDbgMod;
1130 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1131 AssertPtrNull(poffDisp);
1132 AssertPtr(pSymInfo);
1133 AssertReturn(!(fFlags & ~RTDBGSYMADDR_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
1134
1135 RTDBGMOD_LOCK(pDbgMod);
1136
1137 /*
1138 * Convert RVAs.
1139 */
1140 if (iSeg == RTDBGSEGIDX_RVA)
1141 {
1142 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1143 if (iSeg == NIL_RTDBGSEGIDX)
1144 {
1145 RTDBGMOD_UNLOCK(pDbgMod);
1146 return VERR_DBG_INVALID_RVA;
1147 }
1148 }
1149
1150 /*
1151 * Get down to business.
1152 */
1153 int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1154
1155 RTDBGMOD_UNLOCK(pDbgMod);
1156 return rc;
1157}
1158RT_EXPORT_SYMBOL(RTDbgModSymbolByAddr);
1159
1160
1161/**
1162 * Queries symbol information by address.
1163 *
1164 * The returned symbol is what the debug info interpreter considers the symbol
1165 * most applicable to the specified address. This usually means a symbol with an
1166 * address equal or lower than the requested.
1167 *
1168 * @returns IPRT status code.
1169 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1170 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1171 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1172 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1173 * it's not inside any of the segments defined by the module.
1174 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1175 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1176 * end of the segment.
1177 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1178 * @retval VERR_INVALID_PARAMETER if incorrect flags.
1179 *
1180 * @param hDbgMod The module handle.
1181 * @param iSeg The segment index.
1182 * @param off The offset into the segment.
1183 * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
1184 * @param poffDisp Where to store the distance between the
1185 * specified address and the returned symbol. Optional.
1186 * @param ppSymInfo Where to store the pointer to the returned
1187 * symbol information. Always set. Free with
1188 * RTDbgSymbolFree.
1189 */
1190RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1191 PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo)
1192{
1193 AssertPtr(ppSymInfo);
1194 *ppSymInfo = NULL;
1195
1196 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1197 if (!pSymInfo)
1198 return VERR_NO_MEMORY;
1199
1200 int rc = RTDbgModSymbolByAddr(hDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1201
1202 if (RT_SUCCESS(rc))
1203 *ppSymInfo = pSymInfo;
1204 else
1205 RTDbgSymbolFree(pSymInfo);
1206 return rc;
1207}
1208RT_EXPORT_SYMBOL(RTDbgModSymbolByAddrA);
1209
1210
1211/**
1212 * Queries symbol information by symbol name.
1213 *
1214 * @returns IPRT status code.
1215 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1216 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1217 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1218 * short.
1219 *
1220 * @param hDbgMod The module handle.
1221 * @param pszSymbol The symbol name.
1222 * @param pSymInfo Where to store the symbol information.
1223 */
1224RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo)
1225{
1226 /*
1227 * Validate input.
1228 */
1229 PRTDBGMODINT pDbgMod = hDbgMod;
1230 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1231 AssertPtr(pszSymbol);
1232 size_t cchSymbol = strlen(pszSymbol);
1233 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1234 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1235 AssertPtr(pSymInfo);
1236
1237 /*
1238 * Make the query.
1239 */
1240 RTDBGMOD_LOCK(pDbgMod);
1241 int rc = pDbgMod->pDbgVt->pfnSymbolByName(pDbgMod, pszSymbol, cchSymbol, pSymInfo);
1242 RTDBGMOD_UNLOCK(pDbgMod);
1243
1244 return rc;
1245}
1246RT_EXPORT_SYMBOL(RTDbgModSymbolByName);
1247
1248
1249/**
1250 * Queries symbol information by symbol name.
1251 *
1252 * @returns IPRT status code.
1253 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1254 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1255 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1256 * short.
1257 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1258 *
1259 * @param hDbgMod The module handle.
1260 * @param pszSymbol The symbol name.
1261 * @param ppSymInfo Where to store the pointer to the returned
1262 * symbol information. Always set. Free with
1263 * RTDbgSymbolFree.
1264 */
1265RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo)
1266{
1267 AssertPtr(ppSymInfo);
1268 *ppSymInfo = NULL;
1269
1270 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1271 if (!pSymInfo)
1272 return VERR_NO_MEMORY;
1273
1274 int rc = RTDbgModSymbolByName(hDbgMod, pszSymbol, pSymInfo);
1275
1276 if (RT_SUCCESS(rc))
1277 *ppSymInfo = pSymInfo;
1278 else
1279 RTDbgSymbolFree(pSymInfo);
1280 return rc;
1281}
1282RT_EXPORT_SYMBOL(RTDbgModSymbolByNameA);
1283
1284
1285/**
1286 * Adds a line number to the module.
1287 *
1288 * @returns IPRT status code.
1289 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
1290 * custom symbols. This should be consider a normal response.
1291 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1292 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE if the file name is too longer or
1293 * empty.
1294 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1295 * it's not inside any of the segments defined by the module.
1296 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1297 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1298 * end of the segment.
1299 * @retval VERR_INVALID_PARAMETER if the line number flags sets undefined bits.
1300 *
1301 * @param hDbgMod The module handle.
1302 * @param pszFile The file name.
1303 * @param uLineNo The line number.
1304 * @param iSeg The segment index.
1305 * @param off The segment offset.
1306 * @param piOrdinal Where to return the line number ordinal on
1307 * success. If the interpreter doesn't do ordinals,
1308 * this will be set to UINT32_MAX. Optional.
1309 */
1310RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo,
1311 RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
1312{
1313 /*
1314 * Validate input.
1315 */
1316 PRTDBGMODINT pDbgMod = hDbgMod;
1317 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1318 AssertPtr(pszFile);
1319 size_t cchFile = strlen(pszFile);
1320 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1321 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1322 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
1323 || iSeg == RTDBGSEGIDX_RVA,
1324 ("%#x\n", iSeg),
1325 VERR_DBG_INVALID_SEGMENT_INDEX);
1326 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
1327
1328 RTDBGMOD_LOCK(pDbgMod);
1329
1330 /*
1331 * Convert RVAs.
1332 */
1333 if (iSeg == RTDBGSEGIDX_RVA)
1334 {
1335 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1336 if (iSeg == NIL_RTDBGSEGIDX)
1337 {
1338 RTDBGMOD_UNLOCK(pDbgMod);
1339 return VERR_DBG_INVALID_RVA;
1340 }
1341 }
1342
1343 /*
1344 * Get down to business.
1345 */
1346 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
1347
1348 RTDBGMOD_UNLOCK(pDbgMod);
1349 return rc;
1350}
1351RT_EXPORT_SYMBOL(RTDbgModLineAdd);
1352
1353
1354/**
1355 * Gets the line number count.
1356 *
1357 * This can be used together wtih RTDbgModLineByOrdinal or RTDbgModSymbolByLineA
1358 * to enumerate all the line number information.
1359 *
1360 * @returns The number of line numbers in the module.
1361 * UINT32_MAX is returned if the module handle is invalid or some other
1362 * error occurs.
1363 *
1364 * @param hDbgMod The module handle.
1365 */
1366RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod)
1367{
1368 PRTDBGMODINT pDbgMod = hDbgMod;
1369 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1370 RTDBGMOD_LOCK(pDbgMod);
1371
1372 uint32_t cLineNumbers = pDbgMod->pDbgVt->pfnLineCount(pDbgMod);
1373
1374 RTDBGMOD_UNLOCK(pDbgMod);
1375 return cLineNumbers;
1376}
1377RT_EXPORT_SYMBOL(RTDbgModLineCount);
1378
1379
1380/**
1381 * Queries line number information by ordinal number.
1382 *
1383 * This can be used to enumerate the line numbers for the module. Use
1384 * RTDbgModLineCount() to figure the end of the ordinals.
1385 *
1386 * @returns IPRT status code.
1387 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1388 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1389 * ordinal.
1390 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1391
1392 * @param hDbgMod The module handle.
1393 * @param iOrdinal The line number ordinal number.
1394 * @param pLineInfo Where to store the information about the line
1395 * number.
1396 */
1397RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
1398{
1399 PRTDBGMODINT pDbgMod = hDbgMod;
1400 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1401 RTDBGMOD_LOCK(pDbgMod);
1402
1403 int rc = pDbgMod->pDbgVt->pfnLineByOrdinal(pDbgMod, iOrdinal, pLineInfo);
1404
1405 RTDBGMOD_UNLOCK(pDbgMod);
1406 return rc;
1407}
1408RT_EXPORT_SYMBOL(RTDbgModLineByOrdinal);
1409
1410
1411/**
1412 * Queries line number information by ordinal number.
1413 *
1414 * This can be used to enumerate the line numbers for the module. Use
1415 * RTDbgModLineCount() to figure the end of the ordinals.
1416 *
1417 * @returns IPRT status code.
1418 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1419 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1420 * ordinal.
1421 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1422 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1423 *
1424 * @param hDbgMod The module handle.
1425 * @param iOrdinal The line number ordinal number.
1426 * @param ppLineInfo Where to store the pointer to the returned line
1427 * number information. Always set. Free with
1428 * RTDbgLineFree.
1429 */
1430RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo)
1431{
1432 AssertPtr(ppLineInfo);
1433 *ppLineInfo = NULL;
1434
1435 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1436 if (!pLineInfo)
1437 return VERR_NO_MEMORY;
1438
1439 int rc = RTDbgModLineByOrdinal(hDbgMod, iOrdinal, pLineInfo);
1440
1441 if (RT_SUCCESS(rc))
1442 *ppLineInfo = pLineInfo;
1443 else
1444 RTDbgLineFree(pLineInfo);
1445 return rc;
1446}
1447RT_EXPORT_SYMBOL(RTDbgModLineByOrdinalA);
1448
1449
1450/**
1451 * Queries line number information by address.
1452 *
1453 * The returned line number is what the debug info interpreter considers the
1454 * one most applicable to the specified address. This usually means a line
1455 * number with an address equal or lower than the requested.
1456 *
1457 * @returns IPRT status code.
1458 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1459 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1460 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1461 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1462 * it's not inside any of the segments defined by the module.
1463 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1464 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1465 * end of the segment.
1466 *
1467 * @param hDbgMod The module handle.
1468 * @param iSeg The segment number.
1469 * @param off The offset into the segment.
1470 * @param poffDisp Where to store the distance between the
1471 * specified address and the returned symbol.
1472 * Optional.
1473 * @param pLineInfo Where to store the line number information.
1474 */
1475RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
1476{
1477 /*
1478 * Validate input.
1479 */
1480 PRTDBGMODINT pDbgMod = hDbgMod;
1481 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1482 AssertPtrNull(poffDisp);
1483 AssertPtr(pLineInfo);
1484
1485 RTDBGMOD_LOCK(pDbgMod);
1486
1487 /*
1488 * Convert RVAs.
1489 */
1490 if (iSeg == RTDBGSEGIDX_RVA)
1491 {
1492 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1493 if (iSeg == NIL_RTDBGSEGIDX)
1494 {
1495 RTDBGMOD_UNLOCK(pDbgMod);
1496 return VERR_DBG_INVALID_RVA;
1497 }
1498 }
1499
1500 int rc = pDbgMod->pDbgVt->pfnLineByAddr(pDbgMod, iSeg, off, poffDisp, pLineInfo);
1501
1502 RTDBGMOD_UNLOCK(pDbgMod);
1503 return rc;
1504}
1505RT_EXPORT_SYMBOL(RTDbgModLineByAddr);
1506
1507
1508/**
1509 * Queries line number information by address.
1510 *
1511 * The returned line number is what the debug info interpreter considers the
1512 * one most applicable to the specified address. This usually means a line
1513 * number with an address equal or lower than the requested.
1514 *
1515 * @returns IPRT status code.
1516 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1517 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1518 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1519 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1520 * it's not inside any of the segments defined by the module.
1521 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1522 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1523 * end of the segment.
1524 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1525 *
1526 * @param hDbgMod The module handle.
1527 * @param iSeg The segment number.
1528 * @param off The offset into the segment.
1529 * @param poffDisp Where to store the distance between the
1530 * specified address and the returned symbol.
1531 * Optional.
1532 * @param ppLineInfo Where to store the pointer to the returned line
1533 * number information. Always set. Free with
1534 * RTDbgLineFree.
1535 */
1536RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo)
1537{
1538 AssertPtr(ppLineInfo);
1539 *ppLineInfo = NULL;
1540
1541 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1542 if (!pLineInfo)
1543 return VERR_NO_MEMORY;
1544
1545 int rc = RTDbgModLineByAddr(hDbgMod, iSeg, off, poffDisp, pLineInfo);
1546
1547 if (RT_SUCCESS(rc))
1548 *ppLineInfo = pLineInfo;
1549 else
1550 RTDbgLineFree(pLineInfo);
1551 return rc;
1552}
1553RT_EXPORT_SYMBOL(RTDbgModLineByAddrA);
1554
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