VirtualBox

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

Last change on this file since 21292 was 21046, checked in by vboxsync, 15 years ago

IPRT: Added a reader of NM-style map files. (Mainly for linux /proc/kallsyms and System.map.)

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