VirtualBox

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

Last change on this file since 21812 was 21337, checked in by vboxsync, 15 years ago

IPRT,HostDrv,AddDrv: Export public IPRT symbols for the linux kernel (pain).

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