VirtualBox

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

Last change on this file since 20776 was 20744, checked in by vboxsync, 16 years ago

IPRT: RTDbg coding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
1/* $Id: dbgmod.cpp 20744 2009-06-21 15:43:57Z 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.
199 *
200 * @returns IPRT status code.
201 *
202 * @param phDbgMod Where to return the module handle.
203 * @param pszName The name of the module (mandatory).
204 * @param cb The size of the module. Must be greater than zero.
205 * @param fFlags Flags reserved for future extensions, MBZ for now.
206 */
207RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cb, uint32_t fFlags)
208{
209 /*
210 * Input validation and lazy initialization.
211 */
212 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
213 *phDbgMod = NIL_RTDBGMOD;
214 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
215 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
216 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
217 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
218
219 int rc = rtDbgModLazyInit();
220 if (RT_FAILURE(rc))
221 return rc;
222
223 /*
224 * Allocate a new module instance.
225 */
226 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
227 if (!pDbgMod)
228 return VERR_NO_MEMORY;
229 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
230 pDbgMod->cRefs = 1;
231 rc = RTCritSectInit(&pDbgMod->CritSect);
232 if (RT_SUCCESS(rc))
233 {
234 pDbgMod->pszName = RTStrDup(pszName);
235 if (pDbgMod->pszName)
236 {
237 rc = rtDbgModContainerCreate(pDbgMod, cb);
238 if (RT_SUCCESS(rc))
239 {
240 *phDbgMod = pDbgMod;
241 return rc;
242 }
243 RTStrFree(pDbgMod->pszName);
244 }
245 RTCritSectDelete(&pDbgMod->CritSect);
246 }
247
248 RTMemFree(pDbgMod);
249 return rc;
250}
251
252
253RTDECL(int) RTDbgModCreateDeferred(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR cb, uint32_t fFlags)
254{
255 return VERR_NOT_IMPLEMENTED;
256}
257
258
259RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags)
260{
261 return VERR_NOT_IMPLEMENTED;
262}
263
264RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags)
265{
266 return VERR_NOT_IMPLEMENTED;
267}
268
269
270/**
271 * Destroys an module after the reference count has reached zero.
272 *
273 * @param pDbgMod The module instance.
274 */
275static void rtDbgModDestroy(PRTDBGMODINT pDbgMod)
276{
277 /*
278 * Close the debug info interpreter first, then the image interpret.
279 */
280 RTCritSectEnter(&pDbgMod->CritSect); /* paranoia */
281
282 if (pDbgMod->pDbgVt)
283 {
284 pDbgMod->pDbgVt->pfnClose(pDbgMod);
285 pDbgMod->pDbgVt = NULL;
286 pDbgMod->pvDbgPriv = NULL;
287 }
288
289 if (pDbgMod->pImgVt)
290 {
291 pDbgMod->pImgVt->pfnClose(pDbgMod);
292 pDbgMod->pImgVt = NULL;
293 pDbgMod->pvImgPriv = NULL;
294 }
295
296 /*
297 * Free the resources.
298 */
299 ASMAtomicWriteU32(&pDbgMod->u32Magic, ~RTDBGMOD_MAGIC);
300 RTStrFree(pDbgMod->pszName);
301 RTStrFree(pDbgMod->pszImgFile);
302 RTStrFree(pDbgMod->pszDbgFile);
303 RTCritSectLeave(&pDbgMod->CritSect); /* paranoia */
304 RTCritSectDelete(&pDbgMod->CritSect);
305 RTMemFree(pDbgMod);
306}
307
308
309/**
310 * Retains another reference to the module.
311 *
312 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
313 *
314 * @param hDbgMod The module handle.
315 *
316 * @remarks Will not take any locks.
317 */
318RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod)
319{
320 PRTDBGMODINT pDbgMod = hDbgMod;
321 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
322 return ASMAtomicIncU32(&pDbgMod->cRefs);
323}
324
325
326/**
327 * Release a reference to the module.
328 *
329 * When the reference count reaches zero, the module is destroyed.
330 *
331 * @returns New reference count, UINT32_MAX on invalid handle (asserted).
332 *
333 * @param hDbgMod The module handle. The NIL handle is quietly ignored
334 * and 0 is returned.
335 *
336 * @remarks Will not take any locks.
337 */
338RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod)
339{
340 if (hDbgMod == NIL_RTDBGMOD)
341 return 0;
342 PRTDBGMODINT pDbgMod = hDbgMod;
343 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
344
345 uint32_t cRefs = ASMAtomicDecU32(&pDbgMod->cRefs);
346 if (!cRefs)
347 rtDbgModDestroy(pDbgMod);
348 return cRefs;
349}
350
351
352/**
353 * Gets the module name.
354 *
355 * @returns Pointer to a read only string containing the name.
356 *
357 * @param hDbgMod The module handle.
358 */
359RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod)
360{
361 PRTDBGMODINT pDbgMod = hDbgMod;
362 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
363 return pDbgMod->pszName;
364}
365
366
367RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod)
368{
369 return 1;
370}
371
372RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
373{
374 return 1;
375}
376
377RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
378{
379 return 0;
380}
381
382RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod)
383{
384 return 1;
385}
386
387
388/**
389 * Adds a line number to the module.
390 *
391 * @returns IPRT status code.
392 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
393 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
394 * custom symbols.
395 * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE
396 * @retval VERR_DBG_INVALID_RVA
397 * @retval VERR_DBG_INVALID_SEGMENT_INDEX
398 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET
399 * @retval VERR_INVALID_PARAMETER
400 *
401 * @param hDbgMod The module handle.
402 * @param pszSymbol The symbol name.
403 * @param iSeg The segment index.
404 * @param off The segment offset.
405 * @param cb The size of the symbol.
406 * @param fFlags Symbol flags.
407 * @param piOrdinal Where to return the symbol ordinal on success. If
408 * the interpreter doesn't do ordinals, this will be set to
409 * UINT32_MAX. Optional
410 */
411RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
412{
413 /*
414 * Validate input.
415 */
416 PRTDBGMODINT pDbgMod = hDbgMod;
417 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
418 AssertPtr(pszSymbol);
419 size_t cchSymbol = strlen(pszSymbol);
420 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
421 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
422 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
423 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
424 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
425 ("%#x\n", iSeg),
426 VERR_DBG_INVALID_SEGMENT_INDEX);
427 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
428
429 RTDBGMOD_LOCK(pDbgMod);
430
431 /*
432 * Convert RVAs.
433 */
434 if (iSeg == RTDBGSEGIDX_RVA)
435 {
436 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
437 if (iSeg == NIL_RTDBGSEGIDX)
438 {
439 RTDBGMOD_UNLOCK(pDbgMod);
440 return VERR_DBG_INVALID_RVA;
441 }
442 }
443
444 /*
445 * Get down to business.
446 */
447 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
448
449 RTDBGMOD_UNLOCK(pDbgMod);
450 return rc;
451}
452
453
454RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
455{
456 return 1;
457}
458
459RTDECL(int) RTDbgModSymbolByIndex(RTDBGMOD hDbgMod, uint32_t iSymbol, PRTDBGSYMBOL pSymbol)
460{
461 return VERR_NOT_IMPLEMENTED;
462}
463
464RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol)
465{
466 return VERR_NOT_IMPLEMENTED;
467}
468
469RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymbol)
470{
471 return VERR_NOT_IMPLEMENTED;
472}
473
474RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymbol)
475{
476 return VERR_NOT_IMPLEMENTED;
477}
478
479RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymbol)
480{
481 return VERR_NOT_IMPLEMENTED;
482}
483
484
485/**
486 * Adds a line number to the module.
487 *
488 * @returns IPRT status code.
489 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
490 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
491 * custom symbols.
492 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE
493 * @retval VERR_DBG_INVALID_RVA
494 * @retval VERR_DBG_INVALID_SEGMENT_INDEX
495 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET
496 * @retval VERR_INVALID_PARAMETER
497 *
498 * @param hDbgMod The module handle.
499 * @param pszFile The file name.
500 * @param uLineNo The line number.
501 * @param iSeg The segment index.
502 * @param off The segment offset.
503 * @param piOrdinal Where to return the line number ordinal on success.
504 * If the interpreter doesn't do ordinals, this will be
505 * set to UINT32_MAX. Optional.
506 */
507RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
508{
509 /*
510 * Validate input.
511 */
512 PRTDBGMODINT pDbgMod = hDbgMod;
513 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
514 AssertPtr(pszFile);
515 size_t cchFile = strlen(pszFile);
516 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
517 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
518 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
519 || iSeg == RTDBGSEGIDX_RVA,
520 ("%#x\n", iSeg),
521 VERR_DBG_INVALID_SEGMENT_INDEX);
522 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
523
524 RTDBGMOD_LOCK(pDbgMod);
525
526 /*
527 * Convert RVAs.
528 */
529 if (iSeg == RTDBGSEGIDX_RVA)
530 {
531 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
532 if (iSeg == NIL_RTDBGSEGIDX)
533 {
534 RTDBGMOD_UNLOCK(pDbgMod);
535 return VERR_DBG_INVALID_RVA;
536 }
537 }
538
539 /*
540 * Get down to business.
541 */
542 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
543
544 RTDBGMOD_UNLOCK(pDbgMod);
545 return rc;
546}
547
548
549RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLine)
550{
551 return VERR_NOT_IMPLEMENTED;
552}
553
554RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLine)
555{
556 return VERR_NOT_IMPLEMENTED;
557}
558
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