VirtualBox

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

Last change on this file since 33540 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.3 KB
Line 
1/* $Id: dbgmod.cpp 33540 2010-10-28 09:27:05Z 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 if (enmReason == RTTERMREASON_UNLOAD)
132 {
133 RTSemRWDestroy(g_hDbgModRWSem);
134 g_hDbgModRWSem = NIL_RTSEMRW;
135
136 RTStrCacheDestroy(g_hDbgModStrCache);
137 g_hDbgModStrCache = NIL_RTSTRCACHE;
138
139 PRTDBGMODREGDBG pCur = g_pDbgHead;
140 g_pDbgHead = NULL;
141 while (pCur)
142 {
143 PRTDBGMODREGDBG pNext = pCur->pNext;
144 AssertMsg(pCur->cUsers == 0, ("%#x %s\n", pCur->cUsers, pCur->pVt->pszName));
145 RTMemFree(pCur);
146 pCur = pNext;
147 }
148
149 Assert(!g_pImgHead);
150 }
151}
152
153
154/**
155 * Internal worker for register a debug interpreter.
156 *
157 * Called while owning the write lock or when locking isn't required.
158 *
159 * @returns IPRT status code.
160 * @retval VERR_NO_MEMORY
161 * @retval VERR_ALREADY_EXISTS
162 *
163 * @param pVt The virtual function table of the debug
164 * module interpreter.
165 */
166static int rtDbgModDebugInterpreterRegister(PCRTDBGMODVTDBG pVt)
167{
168 /*
169 * Search or duplicate registration.
170 */
171 PRTDBGMODREGDBG pPrev = NULL;
172 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
173 {
174 if (pCur->pVt == pVt)
175 return VERR_ALREADY_EXISTS;
176 if (!strcmp(pCur->pVt->pszName, pVt->pszName))
177 return VERR_ALREADY_EXISTS;
178 pPrev = pCur;
179 }
180
181 /*
182 * Create a new record and add it to the end of the list.
183 */
184 PRTDBGMODREGDBG pReg = (PRTDBGMODREGDBG)RTMemAlloc(sizeof(*pReg));
185 if (!pReg)
186 return VERR_NO_MEMORY;
187 pReg->pVt = pVt;
188 pReg->cUsers = 0;
189 pReg->pNext = NULL;
190 if (pPrev)
191 pPrev->pNext = pReg;
192 else
193 g_pDbgHead = pReg;
194 return VINF_SUCCESS;
195}
196
197
198/**
199 * Do-once callback that initializes the read/write semaphore and registers
200 * the built-in interpreters.
201 *
202 * @returns IPRT status code.
203 * @param pvUser1 NULL.
204 * @param pvUser2 NULL.
205 */
206static DECLCALLBACK(int) rtDbgModInitOnce(void *pvUser1, void *pvUser2)
207{
208 /*
209 * Create the semaphore and string cache.
210 */
211 int rc = RTSemRWCreate(&g_hDbgModRWSem);
212 AssertRCReturn(rc, rc);
213
214 rc = RTStrCacheCreate(&g_hDbgModStrCache, "RTDBGMOD");
215 if (RT_SUCCESS(rc))
216 {
217 /*
218 * Register the interpreters.
219 */
220 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgNm);
221 if (RT_SUCCESS(rc))
222 {
223 /*
224 * Finally, register the IPRT cleanup callback.
225 */
226 rc = RTTermRegisterCallback(rtDbgModTermCallback, NULL);
227 if (RT_SUCCESS(rc))
228 return VINF_SUCCESS;
229
230 /* bail out: use the termination callback. */
231 }
232 }
233 else
234 g_hDbgModStrCache = NIL_RTSTRCACHE;
235 rtDbgModTermCallback(RTTERMREASON_UNLOAD, 0, NULL);
236 return rc;
237}
238
239
240DECLINLINE(int) rtDbgModLazyInit(void)
241{
242 return RTOnce(&g_rtDbgModOnce, rtDbgModInitOnce, NULL, NULL);
243}
244
245
246/**
247 * Creates a module based on the default debug info container.
248 *
249 * This can be used to manually load a module and its symbol. The primary user
250 * group is the debug info interpreters, which use this API to create an
251 * efficient debug info container behind the scenes and forward all queries to
252 * it once the info has been loaded.
253 *
254 * @returns IPRT status code.
255 *
256 * @param phDbgMod Where to return the module handle.
257 * @param pszName The name of the module (mandatory).
258 * @param cbSeg The size of initial segment. If zero, segments will
259 * have to be added manually using RTDbgModSegmentAdd.
260 * @param fFlags Flags reserved for future extensions, MBZ for now.
261 */
262RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cbSeg, uint32_t fFlags)
263{
264 /*
265 * Input validation and lazy initialization.
266 */
267 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
268 *phDbgMod = NIL_RTDBGMOD;
269 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
270 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
271 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
272
273 int rc = rtDbgModLazyInit();
274 if (RT_FAILURE(rc))
275 return rc;
276
277 /*
278 * Allocate a new module instance.
279 */
280 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
281 if (!pDbgMod)
282 return VERR_NO_MEMORY;
283 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
284 pDbgMod->cRefs = 1;
285 rc = RTCritSectInit(&pDbgMod->CritSect);
286 if (RT_SUCCESS(rc))
287 {
288 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
289 if (pDbgMod->pszName)
290 {
291 rc = rtDbgModContainerCreate(pDbgMod, cbSeg);
292 if (RT_SUCCESS(rc))
293 {
294 *phDbgMod = pDbgMod;
295 return rc;
296 }
297 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
298 }
299 RTCritSectDelete(&pDbgMod->CritSect);
300 }
301
302 RTMemFree(pDbgMod);
303 return rc;
304}
305RT_EXPORT_SYMBOL(RTDbgModCreate);
306
307
308RTDECL(int) RTDbgModCreateDeferred(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR cb, uint32_t fFlags)
309{
310 return VERR_NOT_IMPLEMENTED;
311}
312RT_EXPORT_SYMBOL(RTDbgModCreateDeferred);
313
314
315RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags)
316{
317
318 return VERR_NOT_IMPLEMENTED;
319}
320RT_EXPORT_SYMBOL(RTDbgModCreateFromImage);
321
322
323RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags)
324{
325 /*
326 * Input validation and lazy initialization.
327 */
328 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
329 *phDbgMod = NIL_RTDBGMOD;
330 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
331 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
332 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
333 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
334
335 int rc = rtDbgModLazyInit();
336 if (RT_FAILURE(rc))
337 return rc;
338
339 if (!pszName)
340 pszName = RTPathFilename(pszFilename);
341
342 /*
343 * Allocate a new module instance.
344 */
345 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
346 if (!pDbgMod)
347 return VERR_NO_MEMORY;
348 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
349 pDbgMod->cRefs = 1;
350 rc = RTCritSectInit(&pDbgMod->CritSect);
351 if (RT_SUCCESS(rc))
352 {
353 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
354 if (pDbgMod->pszName)
355 {
356 pDbgMod->pszDbgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
357 if (pDbgMod->pszDbgFile)
358 {
359 /*
360 * Try the map file readers.
361 */
362 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
363 if (RT_SUCCESS(rc))
364 {
365 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
366 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
367 {
368 if (pCur->pVt->fSupports & RT_DBGTYPE_MAP)
369 {
370 pDbgMod->pDbgVt = pCur->pVt;
371 pDbgMod->pvDbgPriv = NULL;
372 rc = pCur->pVt->pfnTryOpen(pDbgMod);
373 if (RT_SUCCESS(rc))
374 {
375 ASMAtomicIncU32(&pCur->cUsers);
376 RTSemRWReleaseRead(g_hDbgModRWSem);
377
378 *phDbgMod = pDbgMod;
379 return rc;
380 }
381 }
382 }
383
384 /* bail out */
385 RTSemRWReleaseRead(g_hDbgModRWSem);
386 }
387 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
388 }
389 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
390 }
391 RTCritSectDelete(&pDbgMod->CritSect);
392 }
393
394 RTMemFree(pDbgMod);
395 return rc;
396}
397RT_EXPORT_SYMBOL(RTDbgModCreateFromMap);
398
399
400/**
401 * Destroys an module after the reference count has reached zero.
402 *
403 * @param pDbgMod The module instance.
404 */
405static void rtDbgModDestroy(PRTDBGMODINT pDbgMod)
406{
407 /*
408 * Close the debug info interpreter first, then the image interpret.
409 */
410 RTCritSectEnter(&pDbgMod->CritSect); /* paranoia */
411
412 if (pDbgMod->pDbgVt)
413 {
414 pDbgMod->pDbgVt->pfnClose(pDbgMod);
415 pDbgMod->pDbgVt = NULL;
416 pDbgMod->pvDbgPriv = NULL;
417 }
418
419 if (pDbgMod->pImgVt)
420 {
421 pDbgMod->pImgVt->pfnClose(pDbgMod);
422 pDbgMod->pImgVt = NULL;
423 pDbgMod->pvImgPriv = NULL;
424 }
425
426 /*
427 * Free the resources.
428 */
429 ASMAtomicWriteU32(&pDbgMod->u32Magic, ~RTDBGMOD_MAGIC);
430 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
431 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
432 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
433 RTCritSectLeave(&pDbgMod->CritSect); /* paranoia */
434 RTCritSectDelete(&pDbgMod->CritSect);
435 RTMemFree(pDbgMod);
436}
437
438
439/**
440 * Retains another reference to the module.
441 *
442 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
443 *
444 * @param hDbgMod The module handle.
445 *
446 * @remarks Will not take any locks.
447 */
448RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod)
449{
450 PRTDBGMODINT pDbgMod = hDbgMod;
451 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
452 return ASMAtomicIncU32(&pDbgMod->cRefs);
453}
454RT_EXPORT_SYMBOL(RTDbgModRetain);
455
456
457/**
458 * Release a reference to the module.
459 *
460 * When the reference count reaches zero, the module is destroyed.
461 *
462 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
463 *
464 * @param hDbgMod The module handle. The NIL handle is quietly ignored
465 * and 0 is returned.
466 *
467 * @remarks Will not take any locks.
468 */
469RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod)
470{
471 if (hDbgMod == NIL_RTDBGMOD)
472 return 0;
473 PRTDBGMODINT pDbgMod = hDbgMod;
474 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
475
476 uint32_t cRefs = ASMAtomicDecU32(&pDbgMod->cRefs);
477 if (!cRefs)
478 rtDbgModDestroy(pDbgMod);
479 return cRefs;
480}
481RT_EXPORT_SYMBOL(RTDbgModRelease);
482
483
484/**
485 * Gets the module name.
486 *
487 * @returns Pointer to a read only string containing the name.
488 *
489 * @param hDbgMod The module handle.
490 */
491RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod)
492{
493 PRTDBGMODINT pDbgMod = hDbgMod;
494 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
495 return pDbgMod->pszName;
496}
497RT_EXPORT_SYMBOL(RTDbgModName);
498
499
500/**
501 * Converts an image relative address to a segment:offset address.
502 *
503 * @returns Segment index on success.
504 * NIL_RTDBGSEGIDX is returned if the module handle or the RVA are
505 * invalid.
506 *
507 * @param hDbgMod The module handle.
508 * @param uRva The image relative address to convert.
509 * @param poffSeg Where to return the segment offset. Optional.
510 */
511RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
512{
513 PRTDBGMODINT pDbgMod = hDbgMod;
514 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
515 RTDBGMOD_LOCK(pDbgMod);
516
517 RTDBGSEGIDX iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, uRva, poffSeg);
518
519 RTDBGMOD_UNLOCK(pDbgMod);
520 return iSeg;
521}
522RT_EXPORT_SYMBOL(RTDbgModRvaToSegOff);
523
524
525/**
526 * Image size when mapped if segments are mapped adjacently.
527 *
528 * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and
529 * NE and such it's a bit odder and the answer may not make much sense for them.
530 *
531 * @returns Image mapped size.
532 * RTUINTPTR_MAX is returned if the handle is invalid.
533 *
534 * @param hDbgMod The module handle.
535 */
536RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod)
537{
538 PRTDBGMODINT pDbgMod = hDbgMod;
539 RTDBGMOD_VALID_RETURN_RC(pDbgMod, RTUINTPTR_MAX);
540 RTDBGMOD_LOCK(pDbgMod);
541
542 RTUINTPTR cbImage = pDbgMod->pDbgVt->pfnImageSize(pDbgMod);
543
544 RTDBGMOD_UNLOCK(pDbgMod);
545 return cbImage;
546}
547RT_EXPORT_SYMBOL(RTDbgModImageSize);
548
549
550/**
551 * Gets the module tag value if any.
552 *
553 * @returns The tag. 0 if hDbgMod is invalid.
554 *
555 * @param hDbgMod The module handle.
556 */
557RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod)
558{
559 PRTDBGMODINT pDbgMod = hDbgMod;
560 RTDBGMOD_VALID_RETURN_RC(pDbgMod, 0);
561 return pDbgMod->uTag;
562}
563RT_EXPORT_SYMBOL(RTDbgModGetTag);
564
565
566/**
567 * Tags or untags the module.
568 *
569 * @returns IPRT status code.
570 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
571 *
572 * @param hDbgMod The module handle.
573 * @param uTag The tag value. The convention is that 0 is no tag
574 * and any other value means it's tagged. It's adviced
575 * to use some kind of unique number like an address
576 * (global or string cache for instance) to avoid
577 * collisions with other users
578 */
579RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag)
580{
581 PRTDBGMODINT pDbgMod = hDbgMod;
582 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
583 RTDBGMOD_LOCK(pDbgMod);
584
585 pDbgMod->uTag = uTag;
586
587 RTDBGMOD_UNLOCK(pDbgMod);
588 return VINF_SUCCESS;
589}
590RT_EXPORT_SYMBOL(RTDbgModSetTag);
591
592
593/**
594 * Adds a segment to the module. Optional feature.
595 *
596 * This method is intended used for manually constructing debug info for a
597 * module. The main usage is from other debug info interpreters that want to
598 * avoid writing a debug info database and instead uses the standard container
599 * behind the scenes.
600 *
601 * @returns IPRT status code.
602 * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info
603 * interpreter. This is a common return code.
604 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
605 * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around.
606 * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long.
607 * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags.
608 * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment.
609 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations.
610 *
611 * @param hDbgMod The module handle.
612 * @param uRva The image relative address of the segment.
613 * @param cb The size of the segment.
614 * @param pszName The segment name. Does not normally need to be
615 * unique, although this is somewhat up to the
616 * debug interpreter to decide.
617 * @param fFlags Segment flags. Reserved for future used, MBZ.
618 * @param piSeg The segment index or NIL_RTDBGSEGIDX on input.
619 * The assigned segment index on successful return.
620 * Optional.
621 */
622RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
623 uint32_t fFlags, PRTDBGSEGIDX piSeg)
624{
625 /*
626 * Validate input.
627 */
628 PRTDBGMODINT pDbgMod = hDbgMod;
629 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
630 AssertMsgReturn(uRva + cb >= uRva, ("uRva=%RTptr cb=%RTptr\n", uRva, cb), VERR_DBG_ADDRESS_WRAP);
631 Assert(*pszName);
632 size_t cchName = strlen(pszName);
633 AssertReturn(cchName > 0, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
634 AssertReturn(cchName < RTDBG_SEGMENT_NAME_LENGTH, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
635 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
636 AssertPtrNull(piSeg);
637 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg <= RTDBGSEGIDX_LAST, ("%#x\n", *piSeg), VERR_DBG_SPECIAL_SEGMENT);
638
639 /*
640 * Do the deed.
641 */
642 RTDBGMOD_LOCK(pDbgMod);
643 int rc = pDbgMod->pDbgVt->pfnSegmentAdd(pDbgMod, uRva, cb, pszName, cchName, fFlags, piSeg);
644 RTDBGMOD_UNLOCK(pDbgMod);
645
646 return rc;
647
648}
649RT_EXPORT_SYMBOL(RTDbgModSegmentAdd);
650
651
652/**
653 * Gets the number of segments in the module.
654 *
655 * This is can be used to determine the range which can be passed to
656 * RTDbgModSegmentByIndex and derivatives.
657 *
658 * @returns The segment relative address.
659 * NIL_RTDBGSEGIDX if the handle is invalid.
660 *
661 * @param hDbgMod The module handle.
662 */
663RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod)
664{
665 PRTDBGMODINT pDbgMod = hDbgMod;
666 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
667 RTDBGMOD_LOCK(pDbgMod);
668
669 RTDBGSEGIDX cSegs = pDbgMod->pDbgVt->pfnSegmentCount(pDbgMod);
670
671 RTDBGMOD_UNLOCK(pDbgMod);
672 return cSegs;
673}
674RT_EXPORT_SYMBOL(RTDbgModSegmentCount);
675
676
677/**
678 * Query information about a segment.
679 *
680 * This can be used together with RTDbgModSegmentCount to enumerate segments.
681 * The index starts a 0 and stops one below RTDbgModSegmentCount.
682 *
683 * @returns IPRT status code.
684 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high.
685 * @retval VERR_DBG_SPECIAL_SEGMENT if iSeg indicates a special segment.
686 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
687 *
688 * @param hDbgMod The module handle.
689 * @param iSeg The segment index. No special segments.
690 * @param pSegInfo Where to return the segment info. The
691 * RTDBGSEGMENT::Address member will be set to
692 * RTUINTPTR_MAX or the load address used at link time.
693 */
694RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
695{
696 AssertMsgReturn(iSeg <= RTDBGSEGIDX_LAST, ("%#x\n", iSeg), VERR_DBG_SPECIAL_SEGMENT);
697 PRTDBGMODINT pDbgMod = hDbgMod;
698 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
699 RTDBGMOD_LOCK(pDbgMod);
700
701 int rc = pDbgMod->pDbgVt->pfnSegmentByIndex(pDbgMod, iSeg, pSegInfo);
702
703 RTDBGMOD_UNLOCK(pDbgMod);
704 return rc;
705}
706RT_EXPORT_SYMBOL(RTDbgModSegmentByIndex);
707
708
709/**
710 * Gets the size of a segment.
711 *
712 * This is a just a wrapper around RTDbgModSegmentByIndex.
713 *
714 * @returns The segment size.
715 * RTUINTPTR_MAX is returned if either the handle and segment index are
716 * invalid.
717 *
718 * @param hDbgMod The module handle.
719 * @param iSeg The segment index. RTDBGSEGIDX_ABS is not allowed.
720 * If RTDBGSEGIDX_RVA is used, the functions returns
721 * the same value as RTDbgModImageSize.
722 */
723RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
724{
725 if (iSeg == RTDBGSEGIDX_RVA)
726 return RTDbgModImageSize(hDbgMod);
727 RTDBGSEGMENT SegInfo;
728 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
729 return RT_SUCCESS(rc) ? SegInfo.cb : RTUINTPTR_MAX;
730}
731RT_EXPORT_SYMBOL(RTDbgModSegmentSize);
732
733
734/**
735 * Gets the image relative address of a segment.
736 *
737 * This is a just a wrapper around RTDbgModSegmentByIndex.
738 *
739 * @returns The segment relative address.
740 * RTUINTPTR_MAX is returned if either the handle and segment index are
741 * invalid.
742 *
743 * @param hDbgMod The module handle.
744 * @param iSeg The segment index. No special segment indexes
745 * allowed (asserted).
746 */
747RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
748{
749 RTDBGSEGMENT SegInfo;
750 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
751 return RT_SUCCESS(rc) ? SegInfo.uRva : RTUINTPTR_MAX;
752}
753RT_EXPORT_SYMBOL(RTDbgModSegmentRva);
754
755
756/**
757 * Adds a line number to the module.
758 *
759 * @returns IPRT status code.
760 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
761 * custom symbols. This is a common place occurrence.
762 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
763 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
764 * short.
765 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
766 * it's not inside any of the segments defined by the module.
767 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
768 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
769 * end of the segment.
770 * @retval VERR_DBG_ADDRESS_WRAP if off+cb wraps around.
771 * @retval VERR_INVALID_PARAMETER if the symbol flags sets undefined bits.
772 *
773 * @param hDbgMod The module handle.
774 * @param pszSymbol The symbol name.
775 * @param iSeg The segment index.
776 * @param off The segment offset.
777 * @param cb The size of the symbol. Can be zero, although this
778 * may depend somewhat on the debug interpreter.
779 * @param fFlags Symbol flags. Reserved for the future, MBZ.
780 * @param piOrdinal Where to return the symbol ordinal on success. If
781 * the interpreter doesn't do ordinals, this will be set to
782 * UINT32_MAX. Optional.
783 */
784RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off,
785 RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
786{
787 /*
788 * Validate input.
789 */
790 PRTDBGMODINT pDbgMod = hDbgMod;
791 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
792 AssertPtr(pszSymbol);
793 size_t cchSymbol = strlen(pszSymbol);
794 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
795 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
796 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
797 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
798 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
799 ("%#x\n", iSeg),
800 VERR_DBG_INVALID_SEGMENT_INDEX);
801 AssertMsgReturn(off + cb >= off, ("off=%RTptr cb=%RTptr\n", off, cb), VERR_DBG_ADDRESS_WRAP);
802 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
803
804 RTDBGMOD_LOCK(pDbgMod);
805
806 /*
807 * Convert RVAs.
808 */
809 if (iSeg == RTDBGSEGIDX_RVA)
810 {
811 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
812 if (iSeg == NIL_RTDBGSEGIDX)
813 {
814 RTDBGMOD_UNLOCK(pDbgMod);
815 return VERR_DBG_INVALID_RVA;
816 }
817 }
818
819 /*
820 * Get down to business.
821 */
822 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
823
824 RTDBGMOD_UNLOCK(pDbgMod);
825 return rc;
826}
827RT_EXPORT_SYMBOL(RTDbgModSymbolAdd);
828
829
830/**
831 * Gets the symbol count.
832 *
833 * This can be used together wtih RTDbgModSymbolByOrdinal or
834 * RTDbgModSymbolByOrdinalA to enumerate all the symbols.
835 *
836 * @returns The number of symbols in the module.
837 * UINT32_MAX is returned if the module handle is invalid or some other
838 * error occurs.
839 *
840 * @param hDbgMod The module handle.
841 */
842RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
843{
844 PRTDBGMODINT pDbgMod = hDbgMod;
845 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
846 RTDBGMOD_LOCK(pDbgMod);
847
848 uint32_t cSymbols = pDbgMod->pDbgVt->pfnSymbolCount(pDbgMod);
849
850 RTDBGMOD_UNLOCK(pDbgMod);
851 return cSymbols;
852}
853RT_EXPORT_SYMBOL(RTDbgModSymbolCount);
854
855
856/**
857 * Queries symbol information by ordinal number.
858 *
859 * @returns IPRT status code.
860 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
861 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
862 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
863 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
864 *
865 * @param hDbgMod The module handle.
866 * @param iOrdinal The symbol ordinal number. 0-based. The highest
867 * number is RTDbgModSymbolCount() - 1.
868 * @param pSymInfo Where to store the symbol information.
869 */
870RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
871{
872 PRTDBGMODINT pDbgMod = hDbgMod;
873 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
874 RTDBGMOD_LOCK(pDbgMod);
875
876 int rc = pDbgMod->pDbgVt->pfnSymbolByOrdinal(pDbgMod, iOrdinal, pSymInfo);
877
878 RTDBGMOD_UNLOCK(pDbgMod);
879 return rc;
880}
881RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinal);
882
883
884/**
885 * Queries symbol information by ordinal number.
886 *
887 * @returns IPRT status code.
888 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
889 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
890 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
891 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
892 *
893 * @param hDbgMod The module handle.
894 * @param iOrdinal The symbol ordinal number. 0-based. The highest
895 * number is RTDbgModSymbolCount() - 1.
896 * @param ppSymInfo Where to store the pointer to the returned
897 * symbol information. Always set. Free with
898 * RTDbgSymbolFree.
899 */
900RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo)
901{
902 AssertPtr(ppSymInfo);
903 *ppSymInfo = NULL;
904
905 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
906 if (!pSymInfo)
907 return VERR_NO_MEMORY;
908
909 int rc = RTDbgModSymbolByOrdinal(hDbgMod, iOrdinal, pSymInfo);
910
911 if (RT_SUCCESS(rc))
912 *ppSymInfo = pSymInfo;
913 else
914 RTDbgSymbolFree(pSymInfo);
915 return rc;
916}
917RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinalA);
918
919
920/**
921 * Queries symbol information by address.
922 *
923 * The returned symbol is what the debug info interpreter considers the symbol
924 * most applicable to the specified address. This usually means a symbol with an
925 * address equal or lower than the requested.
926 *
927 * @returns IPRT status code.
928 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
929 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
930 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
931 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
932 * it's not inside any of the segments defined by the module.
933 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
934 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
935 * end of the segment.
936 *
937 * @param hDbgMod The module handle.
938 * @param iSeg The segment number.
939 * @param off The offset into the segment.
940 * @param poffDisp Where to store the distance between the
941 * specified address and the returned symbol.
942 * Optional.
943 * @param pSymInfo Where to store the symbol information.
944 */
945RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
946{
947 /*
948 * Validate input.
949 */
950 PRTDBGMODINT pDbgMod = hDbgMod;
951 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
952 AssertPtrNull(poffDisp);
953 AssertPtr(pSymInfo);
954
955 RTDBGMOD_LOCK(pDbgMod);
956
957 /*
958 * Convert RVAs.
959 */
960 if (iSeg == RTDBGSEGIDX_RVA)
961 {
962 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
963 if (iSeg == NIL_RTDBGSEGIDX)
964 {
965 RTDBGMOD_UNLOCK(pDbgMod);
966 return VERR_DBG_INVALID_RVA;
967 }
968 }
969
970 /*
971 * Get down to business.
972 */
973 int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, poffDisp, pSymInfo);
974
975 RTDBGMOD_UNLOCK(pDbgMod);
976 return rc;
977}
978RT_EXPORT_SYMBOL(RTDbgModSymbolByAddr);
979
980
981/**
982 * Queries symbol information by address.
983 *
984 * The returned symbol is what the debug info interpreter considers the symbol
985 * most applicable to the specified address. This usually means a symbol with an
986 * address equal or lower than the requested.
987 *
988 * @returns IPRT status code.
989 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
990 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
991 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
992 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
993 * it's not inside any of the segments defined by the module.
994 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
995 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
996 * end of the segment.
997 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
998 *
999 * @param hDbgMod The module handle.
1000 * @param iSeg The segment index.
1001 * @param off The offset into the segment.
1002 * @param poffDisp Where to store the distance between the
1003 * specified address and the returned symbol. Optional.
1004 * @param ppSymInfo Where to store the pointer to the returned
1005 * symbol information. Always set. Free with
1006 * RTDbgSymbolFree.
1007 */
1008RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo)
1009{
1010 AssertPtr(ppSymInfo);
1011 *ppSymInfo = NULL;
1012
1013 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1014 if (!pSymInfo)
1015 return VERR_NO_MEMORY;
1016
1017 int rc = RTDbgModSymbolByAddr(hDbgMod, iSeg, off, poffDisp, pSymInfo);
1018
1019 if (RT_SUCCESS(rc))
1020 *ppSymInfo = pSymInfo;
1021 else
1022 RTDbgSymbolFree(pSymInfo);
1023 return rc;
1024}
1025RT_EXPORT_SYMBOL(RTDbgModSymbolByAddrA);
1026
1027
1028/**
1029 * Queries symbol information by symbol name.
1030 *
1031 * @returns IPRT status code.
1032 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1033 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1034 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1035 * short.
1036 *
1037 * @param hDbgMod The module handle.
1038 * @param pszSymbol The symbol name.
1039 * @param pSymInfo Where to store the symbol information.
1040 */
1041RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo)
1042{
1043 /*
1044 * Validate input.
1045 */
1046 PRTDBGMODINT pDbgMod = hDbgMod;
1047 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1048 AssertPtr(pszSymbol);
1049 size_t cchSymbol = strlen(pszSymbol);
1050 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1051 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1052 AssertPtr(pSymInfo);
1053
1054 /*
1055 * Make the query.
1056 */
1057 RTDBGMOD_LOCK(pDbgMod);
1058 int rc = pDbgMod->pDbgVt->pfnSymbolByName(pDbgMod, pszSymbol, cchSymbol, pSymInfo);
1059 RTDBGMOD_UNLOCK(pDbgMod);
1060
1061 return rc;
1062}
1063RT_EXPORT_SYMBOL(RTDbgModSymbolByName);
1064
1065
1066/**
1067 * Queries symbol information by symbol name.
1068 *
1069 * @returns IPRT status code.
1070 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
1071 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
1072 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
1073 * short.
1074 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
1075 *
1076 * @param hDbgMod The module handle.
1077 * @param pszSymbol The symbol name.
1078 * @param ppSymInfo Where to store the pointer to the returned
1079 * symbol information. Always set. Free with
1080 * RTDbgSymbolFree.
1081 */
1082RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo)
1083{
1084 AssertPtr(ppSymInfo);
1085 *ppSymInfo = NULL;
1086
1087 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1088 if (!pSymInfo)
1089 return VERR_NO_MEMORY;
1090
1091 int rc = RTDbgModSymbolByName(hDbgMod, pszSymbol, pSymInfo);
1092
1093 if (RT_SUCCESS(rc))
1094 *ppSymInfo = pSymInfo;
1095 else
1096 RTDbgSymbolFree(pSymInfo);
1097 return rc;
1098}
1099RT_EXPORT_SYMBOL(RTDbgModSymbolByNameA);
1100
1101
1102/**
1103 * Adds a line number to the module.
1104 *
1105 * @returns IPRT status code.
1106 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
1107 * custom symbols. This should be consider a normal response.
1108 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1109 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE if the file name is too longer or
1110 * empty.
1111 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1112 * it's not inside any of the segments defined by the module.
1113 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1114 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1115 * end of the segment.
1116 * @retval VERR_INVALID_PARAMETER if the line number flags sets undefined bits.
1117 *
1118 * @param hDbgMod The module handle.
1119 * @param pszFile The file name.
1120 * @param uLineNo The line number.
1121 * @param iSeg The segment index.
1122 * @param off The segment offset.
1123 * @param piOrdinal Where to return the line number ordinal on
1124 * success. If the interpreter doesn't do ordinals,
1125 * this will be set to UINT32_MAX. Optional.
1126 */
1127RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo,
1128 RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
1129{
1130 /*
1131 * Validate input.
1132 */
1133 PRTDBGMODINT pDbgMod = hDbgMod;
1134 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1135 AssertPtr(pszFile);
1136 size_t cchFile = strlen(pszFile);
1137 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1138 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1139 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
1140 || iSeg == RTDBGSEGIDX_RVA,
1141 ("%#x\n", iSeg),
1142 VERR_DBG_INVALID_SEGMENT_INDEX);
1143 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, 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->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
1164
1165 RTDBGMOD_UNLOCK(pDbgMod);
1166 return rc;
1167}
1168RT_EXPORT_SYMBOL(RTDbgModLineAdd);
1169
1170
1171/**
1172 * Gets the line number count.
1173 *
1174 * This can be used together wtih RTDbgModLineByOrdinal or RTDbgModSymbolByLineA
1175 * to enumerate all the line number information.
1176 *
1177 * @returns The number of line numbers in the module.
1178 * UINT32_MAX is returned if the module handle is invalid or some other
1179 * error occurs.
1180 *
1181 * @param hDbgMod The module handle.
1182 */
1183RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod)
1184{
1185 PRTDBGMODINT pDbgMod = hDbgMod;
1186 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1187 RTDBGMOD_LOCK(pDbgMod);
1188
1189 uint32_t cLineNumbers = pDbgMod->pDbgVt->pfnLineCount(pDbgMod);
1190
1191 RTDBGMOD_UNLOCK(pDbgMod);
1192 return cLineNumbers;
1193}
1194RT_EXPORT_SYMBOL(RTDbgModLineCount);
1195
1196
1197/**
1198 * Queries line number information by ordinal number.
1199 *
1200 * This can be used to enumerate the line numbers for the module. Use
1201 * RTDbgModLineCount() to figure the end of the ordinals.
1202 *
1203 * @returns IPRT status code.
1204 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1205 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1206 * ordinal.
1207 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1208
1209 * @param hDbgMod The module handle.
1210 * @param iOrdinal The line number ordinal number.
1211 * @param pLineInfo Where to store the information about the line
1212 * number.
1213 */
1214RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
1215{
1216 PRTDBGMODINT pDbgMod = hDbgMod;
1217 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1218 RTDBGMOD_LOCK(pDbgMod);
1219
1220 int rc = pDbgMod->pDbgVt->pfnLineByOrdinal(pDbgMod, iOrdinal, pLineInfo);
1221
1222 RTDBGMOD_UNLOCK(pDbgMod);
1223 return rc;
1224}
1225RT_EXPORT_SYMBOL(RTDbgModLineByOrdinal);
1226
1227
1228/**
1229 * Queries line number information by ordinal number.
1230 *
1231 * This can be used to enumerate the line numbers for the module. Use
1232 * RTDbgModLineCount() to figure the end of the ordinals.
1233 *
1234 * @returns IPRT status code.
1235 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1236 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
1237 * ordinal.
1238 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1239 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1240 *
1241 * @param hDbgMod The module handle.
1242 * @param iOrdinal The line number ordinal number.
1243 * @param ppLineInfo Where to store the pointer to the returned line
1244 * number information. Always set. Free with
1245 * RTDbgLineFree.
1246 */
1247RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo)
1248{
1249 AssertPtr(ppLineInfo);
1250 *ppLineInfo = NULL;
1251
1252 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1253 if (!pLineInfo)
1254 return VERR_NO_MEMORY;
1255
1256 int rc = RTDbgModLineByOrdinal(hDbgMod, iOrdinal, pLineInfo);
1257
1258 if (RT_SUCCESS(rc))
1259 *ppLineInfo = pLineInfo;
1260 else
1261 RTDbgLineFree(pLineInfo);
1262 return rc;
1263}
1264RT_EXPORT_SYMBOL(RTDbgModLineByOrdinalA);
1265
1266
1267/**
1268 * Queries line number information by address.
1269 *
1270 * The returned line number is what the debug info interpreter considers the
1271 * one most applicable to the specified address. This usually means a line
1272 * number with an address equal or lower than the requested.
1273 *
1274 * @returns IPRT status code.
1275 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1276 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1277 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1278 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1279 * it's not inside any of the segments defined by the module.
1280 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1281 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1282 * end of the segment.
1283 *
1284 * @param hDbgMod The module handle.
1285 * @param iSeg The segment number.
1286 * @param off The offset into the segment.
1287 * @param poffDisp Where to store the distance between the
1288 * specified address and the returned symbol.
1289 * Optional.
1290 * @param pLineInfo Where to store the line number information.
1291 */
1292RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
1293{
1294 /*
1295 * Validate input.
1296 */
1297 PRTDBGMODINT pDbgMod = hDbgMod;
1298 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1299 RTDBGMOD_LOCK(pDbgMod);
1300 AssertPtrNull(poffDisp);
1301 AssertPtr(pLineInfo);
1302
1303 RTDBGMOD_LOCK(pDbgMod);
1304
1305 /*
1306 * Convert RVAs.
1307 */
1308 if (iSeg == RTDBGSEGIDX_RVA)
1309 {
1310 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1311 if (iSeg == NIL_RTDBGSEGIDX)
1312 {
1313 RTDBGMOD_UNLOCK(pDbgMod);
1314 return VERR_DBG_INVALID_RVA;
1315 }
1316 }
1317
1318 int rc = pDbgMod->pDbgVt->pfnLineByAddr(pDbgMod, iSeg, off, poffDisp, pLineInfo);
1319
1320 RTDBGMOD_UNLOCK(pDbgMod);
1321 return rc;
1322}
1323RT_EXPORT_SYMBOL(RTDbgModLineByAddr);
1324
1325
1326/**
1327 * Queries line number information by address.
1328 *
1329 * The returned line number is what the debug info interpreter considers the
1330 * one most applicable to the specified address. This usually means a line
1331 * number with an address equal or lower than the requested.
1332 *
1333 * @returns IPRT status code.
1334 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
1335 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
1336 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
1337 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
1338 * it's not inside any of the segments defined by the module.
1339 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
1340 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
1341 * end of the segment.
1342 * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
1343 *
1344 * @param hDbgMod The module handle.
1345 * @param iSeg The segment number.
1346 * @param off The offset into the segment.
1347 * @param poffDisp Where to store the distance between the
1348 * specified address and the returned symbol.
1349 * Optional.
1350 * @param ppLineInfo Where to store the pointer to the returned line
1351 * number information. Always set. Free with
1352 * RTDbgLineFree.
1353 */
1354RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo)
1355{
1356 AssertPtr(ppLineInfo);
1357 *ppLineInfo = NULL;
1358
1359 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1360 if (!pLineInfo)
1361 return VERR_NO_MEMORY;
1362
1363 int rc = RTDbgModLineByAddr(hDbgMod, iSeg, off, poffDisp, pLineInfo);
1364
1365 if (RT_SUCCESS(rc))
1366 *ppLineInfo = pLineInfo;
1367 else
1368 RTDbgLineFree(pLineInfo);
1369 return rc;
1370}
1371RT_EXPORT_SYMBOL(RTDbgModLineByAddrA);
1372
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