VirtualBox

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

Last change on this file since 20976 was 20801, checked in by vboxsync, 16 years ago

IPRT: The rest of the basic RTDbgMod code.

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