VirtualBox

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

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

IPRT: More RTDbgMod code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.4 KB
Line 
1/* $Id: dbgmod.cpp 20800 2009-06-22 23:47:37Z 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 pMod Pointer to the module structure.
754 * @param iSeg The segment number (0-based) or RTDBGSEGIDX_ABS.
755 * @param off The offset into the segment.
756 * @param poffDisp Where to store the distance between the specified address
757 * and the returned symbol. Optional.
758 * @param pSymInfo Where to store the symbol information.
759 */
760RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
761{
762 /*
763 * Validate input.
764 */
765 PRTDBGMODINT pDbgMod = hDbgMod;
766 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
767 AssertPtrNull(poffDisp);
768 AssertPtr(pSymInfo);
769
770 RTDBGMOD_LOCK(pDbgMod);
771
772 /*
773 * Convert RVAs.
774 */
775 if (iSeg == RTDBGSEGIDX_RVA)
776 {
777 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
778 if (iSeg == NIL_RTDBGSEGIDX)
779 {
780 RTDBGMOD_UNLOCK(pDbgMod);
781 return VERR_DBG_INVALID_RVA;
782 }
783 }
784
785 /*
786 * Get down to business.
787 */
788 int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, poffDisp, pSymInfo);
789
790 RTDBGMOD_UNLOCK(pDbgMod);
791 return rc;
792}
793
794
795/**
796 * Queries symbol information by address.
797 *
798 * The returned symbol is what the debug info interpreter consideres the symbol
799 * most applicable to the specified address. This usually means a symbol with an
800 * address equal or lower than the requested.
801 *
802 * @returns IPRT status code.
803 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
804 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
805 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
806 * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
807 * it's not inside any of the segments defined by the module.
808 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
809 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
810 * end of the segment.
811 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
812 *
813 * @param hDbgMod The module handle.
814 * @param iSeg The segment index.
815 * @param off The offset into the segment.
816 * @param poffDisp Where to store the distance between the
817 * specified address and the returned symbol. Optional.
818 * @param ppSymInfo Where to store the pointer to the returned
819 * symbol information. Always set. Free with
820 * RTDbgSymbolFree.
821 */
822RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo)
823{
824 AssertPtr(ppSymInfo);
825 *ppSymInfo = NULL;
826
827 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
828 if (!pSymInfo)
829 return VERR_NO_MEMORY;
830
831 int rc = RTDbgModSymbolByAddr(hDbgMod, iSeg, off, poffDisp, pSymInfo);
832
833 if (RT_SUCCESS(rc))
834 *ppSymInfo = pSymInfo;
835 else
836 RTDbgSymbolFree(pSymInfo);
837 return rc;
838}
839
840
841/**
842 * Queries symbol information by symbol name.
843 *
844 * @returns IPRT status code.
845 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
846 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
847 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
848 * short.
849 *
850 * @param hDbgMod The module handle.
851 * @param pszSymbol The symbol name.
852 * @param pSymInfo Where to store the symbol information.
853 */
854RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo)
855{
856 /*
857 * Validate input.
858 */
859 PRTDBGMODINT pDbgMod = hDbgMod;
860 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
861 AssertPtr(pszSymbol);
862 size_t cchSymbol = strlen(pszSymbol);
863 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
864 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
865 AssertPtr(pSymInfo);
866
867 /*
868 * Make the query.
869 */
870 RTDBGMOD_LOCK(pDbgMod);
871 int rc = pDbgMod->pDbgVt->pfnSymbolByName(pDbgMod, pszSymbol, cchSymbol, pSymInfo);
872 RTDBGMOD_UNLOCK(pDbgMod);
873
874 return rc;
875}
876
877
878/**
879 * Queries symbol information by symbol name.
880 *
881 * @returns IPRT status code.
882 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
883 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
884 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
885 * short.
886 *
887 * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
888 * @param hDbgMod The module handle.
889 * @param pszSymbol The symbol name.
890 * @param ppSymInfo Where to store the pointer to the returned
891 * symbol information. Always set. Free with
892 * RTDbgSymbolFree.
893 */
894RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo)
895{
896 AssertPtr(ppSymInfo);
897 *ppSymInfo = NULL;
898
899 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
900 if (!pSymInfo)
901 return VERR_NO_MEMORY;
902
903 int rc = RTDbgModSymbolByName(hDbgMod, pszSymbol, pSymInfo);
904
905 if (RT_SUCCESS(rc))
906 *ppSymInfo = pSymInfo;
907 else
908 RTDbgSymbolFree(pSymInfo);
909 return rc;
910}
911
912
913/**
914 * Adds a line number to the module.
915 *
916 * @returns IPRT status code.
917 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
918 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
919 * custom symbols.
920 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE
921 * @retval VERR_DBG_INVALID_RVA
922 * @retval VERR_DBG_INVALID_SEGMENT_INDEX
923 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET
924 * @retval VERR_INVALID_PARAMETER
925 *
926 * @param hDbgMod The module handle.
927 * @param pszFile The file name.
928 * @param uLineNo The line number.
929 * @param iSeg The segment index.
930 * @param off The segment offset.
931 * @param piOrdinal Where to return the line number ordinal on success.
932 * If the interpreter doesn't do ordinals, this will be
933 * set to UINT32_MAX. Optional.
934 */
935RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
936{
937 /*
938 * Validate input.
939 */
940 PRTDBGMODINT pDbgMod = hDbgMod;
941 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
942 AssertPtr(pszFile);
943 size_t cchFile = strlen(pszFile);
944 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
945 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
946 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
947 || iSeg == RTDBGSEGIDX_RVA,
948 ("%#x\n", iSeg),
949 VERR_DBG_INVALID_SEGMENT_INDEX);
950 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
951
952 RTDBGMOD_LOCK(pDbgMod);
953
954 /*
955 * Convert RVAs.
956 */
957 if (iSeg == RTDBGSEGIDX_RVA)
958 {
959 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
960 if (iSeg == NIL_RTDBGSEGIDX)
961 {
962 RTDBGMOD_UNLOCK(pDbgMod);
963 return VERR_DBG_INVALID_RVA;
964 }
965 }
966
967 /*
968 * Get down to business.
969 */
970 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
971
972 RTDBGMOD_UNLOCK(pDbgMod);
973 return rc;
974}
975
976
977RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLine)
978{
979 return VERR_NOT_IMPLEMENTED;
980}
981
982RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLine)
983{
984 return VERR_NOT_IMPLEMENTED;
985}
986
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