VirtualBox

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

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

iprt: More RTDbg coding; added a new AVL tree for RTUINPTR.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1/* $Id: dbgmod.cpp 20740 2009-06-21 02:09: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/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 */
408RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags)
409{
410 /*
411 * Validate input.
412 */
413 PRTDBGMODINT pDbgMod = hDbgMod;
414 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
415 AssertPtr(pszSymbol);
416 size_t cchSymbol = strlen(pszSymbol);
417 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
418 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
419 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
420 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
421 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
422 ("%#x\n", iSeg),
423 VERR_DBG_INVALID_SEGMENT_INDEX);
424 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
425
426 RTDBGMOD_LOCK(pDbgMod);
427
428 /*
429 * Convert RVAs.
430 */
431 if (iSeg == RTDBGSEGIDX_RVA)
432 {
433 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
434 if (iSeg == NIL_RTDBGSEGIDX)
435 {
436 RTDBGMOD_UNLOCK(pDbgMod);
437 return VERR_DBG_INVALID_RVA;
438 }
439 }
440
441 /*
442 * Get down to business.
443 */
444 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags);
445
446 RTDBGMOD_UNLOCK(pDbgMod);
447 return rc;
448}
449
450
451RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
452{
453 return 1;
454}
455
456RTDECL(int) RTDbgModSymbolByIndex(RTDBGMOD hDbgMod, uint32_t iSymbol, PRTDBGSYMBOL pSymbol)
457{
458 return VERR_NOT_IMPLEMENTED;
459}
460
461RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol)
462{
463 return VERR_NOT_IMPLEMENTED;
464}
465
466RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymbol)
467{
468 return VERR_NOT_IMPLEMENTED;
469}
470
471RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymbol)
472{
473 return VERR_NOT_IMPLEMENTED;
474}
475
476RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymbol)
477{
478 return VERR_NOT_IMPLEMENTED;
479}
480
481
482/**
483 * Adds a line number to the module.
484 *
485 * @returns IPRT status code.
486 * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
487 * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
488 * custom symbols.
489 * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE
490 * @retval VERR_DBG_INVALID_RVA
491 * @retval VERR_DBG_INVALID_SEGMENT_INDEX
492 * @retval VERR_DBG_INVALID_SEGMENT_OFFSET
493 * @retval VERR_INVALID_PARAMETER
494 *
495 * @param hDbgMod The module handle.
496 * @param pszFile The file name.
497 * @param uLineNo The line number.
498 * @param iSeg The segment index.
499 * @param off The segment offset.
500 */
501RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo, RTDBGSEGIDX iSeg, RTUINTPTR off)
502{
503 /*
504 * Validate input.
505 */
506 PRTDBGMODINT pDbgMod = hDbgMod;
507 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
508 AssertPtr(pszFile);
509 size_t cchFile = strlen(pszFile);
510 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
511 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
512 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
513 || iSeg == RTDBGSEGIDX_RVA,
514 ("%#x\n", iSeg),
515 VERR_DBG_INVALID_SEGMENT_INDEX);
516 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
517
518 RTDBGMOD_LOCK(pDbgMod);
519
520 /*
521 * Convert RVAs.
522 */
523 if (iSeg == RTDBGSEGIDX_RVA)
524 {
525 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
526 if (iSeg == NIL_RTDBGSEGIDX)
527 {
528 RTDBGMOD_UNLOCK(pDbgMod);
529 return VERR_DBG_INVALID_RVA;
530 }
531 }
532
533 /*
534 * Get down to business.
535 */
536 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off);
537
538 RTDBGMOD_UNLOCK(pDbgMod);
539 return rc;
540}
541
542
543RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLine)
544{
545 return VERR_NOT_IMPLEMENTED;
546}
547
548RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLine)
549{
550 return VERR_NOT_IMPLEMENTED;
551}
552
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