VirtualBox

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

Last change on this file since 46106 was 46106, checked in by vboxsync, 12 years ago

Use DOS style path parsing when finding the default module name in RTDbgMod.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.5 KB
Line 
1/* $Id: dbgmod.cpp 46106 2013-05-15 17:48:51Z vboxsync $ */
2/** @file
3 * IPRT - Debug Module Interpreter.
4 */
5
6/*
7 * Copyright (C) 2009-2012 Oracle Corporation
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
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DBG
32#include <iprt/dbg.h>
33#include "internal/iprt.h"
34
35#include <iprt/alloca.h>
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/log.h>
42#include <iprt/mem.h>
43#include <iprt/once.h>
44#include <iprt/param.h>
45#include <iprt/path.h>
46#include <iprt/semaphore.h>
47#include <iprt/strcache.h>
48#include <iprt/string.h>
49#include "internal/dbgmod.h"
50#include "internal/magics.h"
51
52
53/*******************************************************************************
54* Structures and Typedefs *
55*******************************************************************************/
56/** Debug info interpreter registration record. */
57typedef struct RTDBGMODREGDBG
58{
59 /** Pointer to the next record. */
60 struct RTDBGMODREGDBG *pNext;
61 /** Pointer to the virtual function table for the interpreter. */
62 PCRTDBGMODVTDBG pVt;
63 /** Usage counter. */
64 uint32_t volatile cUsers;
65} RTDBGMODREGDBG;
66typedef RTDBGMODREGDBG *PRTDBGMODREGDBG;
67
68/** Image interpreter registration record. */
69typedef struct RTDBGMODREGIMG
70{
71 /** Pointer to the next record. */
72 struct RTDBGMODREGIMG *pNext;
73 /** Pointer to the virtual function table for the interpreter. */
74 PCRTDBGMODVTIMG pVt;
75 /** Usage counter. */
76 uint32_t volatile cUsers;
77} RTDBGMODREGIMG;
78typedef RTDBGMODREGIMG *PRTDBGMODREGIMG;
79
80
81/*******************************************************************************
82* Defined Constants And Macros *
83*******************************************************************************/
84/** Validates a debug module handle and returns rc if not valid. */
85#define RTDBGMOD_VALID_RETURN_RC(pDbgMod, rc) \
86 do { \
87 AssertPtrReturn((pDbgMod), (rc)); \
88 AssertReturn((pDbgMod)->u32Magic == RTDBGMOD_MAGIC, (rc)); \
89 AssertReturn((pDbgMod)->cRefs > 0, (rc)); \
90 } while (0)
91
92/** Locks the debug module. */
93#define RTDBGMOD_LOCK(pDbgMod) \
94 do { \
95 int rcLock = RTCritSectEnter(&(pDbgMod)->CritSect); \
96 AssertRC(rcLock); \
97 } while (0)
98
99/** Unlocks the debug module. */
100#define RTDBGMOD_UNLOCK(pDbgMod) \
101 do { \
102 int rcLock = RTCritSectLeave(&(pDbgMod)->CritSect); \
103 AssertRC(rcLock); \
104 } while (0)
105
106
107/*******************************************************************************
108* Global Variables *
109*******************************************************************************/
110/** Init once object for lazy registration of the built-in image and debug
111 * info interpreters. */
112static RTONCE g_rtDbgModOnce = RTONCE_INITIALIZER;
113/** Read/Write semaphore protecting the list of registered interpreters. */
114static RTSEMRW g_hDbgModRWSem = NIL_RTSEMRW;
115/** List of registered image interpreters. */
116static PRTDBGMODREGIMG g_pImgHead;
117/** List of registered debug infor interpreters. */
118static PRTDBGMODREGDBG g_pDbgHead;
119/** String cache for the debug info interpreters.
120 * RTSTRCACHE is thread safe. */
121DECLHIDDEN(RTSTRCACHE) g_hDbgModStrCache = NIL_RTSTRCACHE;
122
123
124
125/**
126 * Cleanup debug info interpreter globals.
127 *
128 * @param enmReason The cause of the termination.
129 * @param iStatus The meaning of this depends on enmReason.
130 * @param pvUser User argument, unused.
131 */
132static DECLCALLBACK(void) rtDbgModTermCallback(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
133{
134 NOREF(iStatus); NOREF(pvUser);
135 if (enmReason == RTTERMREASON_UNLOAD)
136 {
137 RTSemRWDestroy(g_hDbgModRWSem);
138 g_hDbgModRWSem = NIL_RTSEMRW;
139
140 RTStrCacheDestroy(g_hDbgModStrCache);
141 g_hDbgModStrCache = NIL_RTSTRCACHE;
142
143 PRTDBGMODREGDBG pDbg = g_pDbgHead;
144 g_pDbgHead = NULL;
145 while (pDbg)
146 {
147 PRTDBGMODREGDBG pNext = pDbg->pNext;
148 AssertMsg(pDbg->cUsers == 0, ("%#x %s\n", pDbg->cUsers, pDbg->pVt->pszName));
149 RTMemFree(pDbg);
150 pDbg = pNext;
151 }
152
153 PRTDBGMODREGIMG pImg = g_pImgHead;
154 g_pImgHead = NULL;
155 while (pImg)
156 {
157 PRTDBGMODREGIMG pNext = pImg->pNext;
158 AssertMsg(pImg->cUsers == 0, ("%#x %s\n", pImg->cUsers, pImg->pVt->pszName));
159 RTMemFree(pImg);
160 pImg = pNext;
161 }
162 }
163}
164
165
166/**
167 * Internal worker for register a debug interpreter.
168 *
169 * Called while owning the write lock or when locking isn't required.
170 *
171 * @returns IPRT status code.
172 * @retval VERR_NO_MEMORY
173 * @retval VERR_ALREADY_EXISTS
174 *
175 * @param pVt The virtual function table of the debug
176 * module interpreter.
177 */
178static int rtDbgModDebugInterpreterRegister(PCRTDBGMODVTDBG pVt)
179{
180 /*
181 * Search or duplicate registration.
182 */
183 PRTDBGMODREGDBG pPrev = NULL;
184 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
185 {
186 if (pCur->pVt == pVt)
187 return VERR_ALREADY_EXISTS;
188 if (!strcmp(pCur->pVt->pszName, pVt->pszName))
189 return VERR_ALREADY_EXISTS;
190 pPrev = pCur;
191 }
192
193 /*
194 * Create a new record and add it to the end of the list.
195 */
196 PRTDBGMODREGDBG pReg = (PRTDBGMODREGDBG)RTMemAlloc(sizeof(*pReg));
197 if (!pReg)
198 return VERR_NO_MEMORY;
199 pReg->pVt = pVt;
200 pReg->cUsers = 0;
201 pReg->pNext = NULL;
202 if (pPrev)
203 pPrev->pNext = pReg;
204 else
205 g_pDbgHead = pReg;
206 return VINF_SUCCESS;
207}
208
209
210/**
211 * Internal worker for register a image interpreter.
212 *
213 * Called while owning the write lock or when locking isn't required.
214 *
215 * @returns IPRT status code.
216 * @retval VERR_NO_MEMORY
217 * @retval VERR_ALREADY_EXISTS
218 *
219 * @param pVt The virtual function table of the image
220 * interpreter.
221 */
222static int rtDbgModImageInterpreterRegister(PCRTDBGMODVTIMG pVt)
223{
224 /*
225 * Search or duplicate registration.
226 */
227 PRTDBGMODREGIMG pPrev = NULL;
228 for (PRTDBGMODREGIMG pCur = g_pImgHead; pCur; pCur = pCur->pNext)
229 {
230 if (pCur->pVt == pVt)
231 return VERR_ALREADY_EXISTS;
232 if (!strcmp(pCur->pVt->pszName, pVt->pszName))
233 return VERR_ALREADY_EXISTS;
234 pPrev = pCur;
235 }
236
237 /*
238 * Create a new record and add it to the end of the list.
239 */
240 PRTDBGMODREGIMG pReg = (PRTDBGMODREGIMG)RTMemAlloc(sizeof(*pReg));
241 if (!pReg)
242 return VERR_NO_MEMORY;
243 pReg->pVt = pVt;
244 pReg->cUsers = 0;
245 pReg->pNext = NULL;
246 if (pPrev)
247 pPrev->pNext = pReg;
248 else
249 g_pImgHead = pReg;
250 return VINF_SUCCESS;
251}
252
253
254/**
255 * Do-once callback that initializes the read/write semaphore and registers
256 * the built-in interpreters.
257 *
258 * @returns IPRT status code.
259 * @param pvUser NULL.
260 */
261static DECLCALLBACK(int) rtDbgModInitOnce(void *pvUser)
262{
263 NOREF(pvUser);
264
265 /*
266 * Create the semaphore and string cache.
267 */
268 int rc = RTSemRWCreate(&g_hDbgModRWSem);
269 AssertRCReturn(rc, rc);
270
271 rc = RTStrCacheCreate(&g_hDbgModStrCache, "RTDBGMOD");
272 if (RT_SUCCESS(rc))
273 {
274 /*
275 * Register the interpreters.
276 */
277 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgNm);
278 if (RT_SUCCESS(rc))
279 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgDwarf);
280#ifdef RT_OS_WINDOWS
281 if (RT_SUCCESS(rc))
282 rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgDbgHelp);
283#endif
284 if (RT_SUCCESS(rc))
285 rc = rtDbgModImageInterpreterRegister(&g_rtDbgModVtImgLdr);
286 if (RT_SUCCESS(rc))
287 {
288 /*
289 * Finally, register the IPRT cleanup callback.
290 */
291 rc = RTTermRegisterCallback(rtDbgModTermCallback, NULL);
292 if (RT_SUCCESS(rc))
293 return VINF_SUCCESS;
294
295 /* bail out: use the termination callback. */
296 }
297 }
298 else
299 g_hDbgModStrCache = NIL_RTSTRCACHE;
300 rtDbgModTermCallback(RTTERMREASON_UNLOAD, 0, NULL);
301 return rc;
302}
303
304
305/**
306 * Performs lazy init of our global variables.
307 * @returns IPRT status code.
308 */
309DECLINLINE(int) rtDbgModLazyInit(void)
310{
311 return RTOnce(&g_rtDbgModOnce, rtDbgModInitOnce, NULL);
312}
313
314
315RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cbSeg, uint32_t fFlags)
316{
317 /*
318 * Input validation and lazy initialization.
319 */
320 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
321 *phDbgMod = NIL_RTDBGMOD;
322 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
323 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
324 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
325
326 int rc = rtDbgModLazyInit();
327 if (RT_FAILURE(rc))
328 return rc;
329
330 /*
331 * Allocate a new module instance.
332 */
333 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
334 if (!pDbgMod)
335 return VERR_NO_MEMORY;
336 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
337 pDbgMod->cRefs = 1;
338 rc = RTCritSectInit(&pDbgMod->CritSect);
339 if (RT_SUCCESS(rc))
340 {
341 pDbgMod->pszImgFileSpecified = RTStrCacheEnter(g_hDbgModStrCache, pszName);
342 pDbgMod->pszName = RTStrCacheEnterLower(g_hDbgModStrCache, RTPathFilenameEx(pszName, RTPATH_STR_F_STYLE_DOS));
343 if (pDbgMod->pszName)
344 {
345 rc = rtDbgModContainerCreate(pDbgMod, cbSeg);
346 if (RT_SUCCESS(rc))
347 {
348 *phDbgMod = pDbgMod;
349 return rc;
350 }
351 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
352 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
353 }
354 RTCritSectDelete(&pDbgMod->CritSect);
355 }
356
357 RTMemFree(pDbgMod);
358 return rc;
359}
360RT_EXPORT_SYMBOL(RTDbgModCreate);
361
362
363RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTDBGCFG hDbgCfg)
364{
365 /*
366 * Input validation and lazy initialization.
367 */
368 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
369 *phDbgMod = NIL_RTDBGMOD;
370 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
371 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
372 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
373
374 int rc = rtDbgModLazyInit();
375 if (RT_FAILURE(rc))
376 return rc;
377
378 if (!pszName)
379 pszName = RTPathFilenameEx(pszFilename, RTPATH_STR_F_STYLE_DOS);
380
381 /*
382 * Allocate a new module instance.
383 */
384 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
385 if (!pDbgMod)
386 return VERR_NO_MEMORY;
387 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
388 pDbgMod->cRefs = 1;
389 rc = RTCritSectInit(&pDbgMod->CritSect);
390 if (RT_SUCCESS(rc))
391 {
392 pDbgMod->pszName = RTStrCacheEnterLower(g_hDbgModStrCache, pszName);
393 if (pDbgMod->pszName)
394 {
395 pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
396 if (pDbgMod->pszImgFile)
397 {
398 RTStrCacheRetain(pDbgMod->pszImgFile);
399 pDbgMod->pszImgFileSpecified = pDbgMod->pszImgFile;
400
401 /*
402 * Find an image reader which groks the file.
403 */
404 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
405 if (RT_SUCCESS(rc))
406 {
407 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
408 PRTDBGMODREGIMG pImg;
409 for (pImg = g_pImgHead; pImg; pImg = pImg->pNext)
410 {
411 pDbgMod->pImgVt = pImg->pVt;
412 pDbgMod->pvImgPriv = NULL;
413 rc = pImg->pVt->pfnTryOpen(pDbgMod);
414 if (RT_SUCCESS(rc))
415 {
416 /*
417 * Find a debug info interpreter.
418 */
419 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
420 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
421 {
422 pDbgMod->pDbgVt = pDbg->pVt;
423 pDbgMod->pvDbgPriv = NULL;
424 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
425 if (RT_SUCCESS(rc))
426 {
427 /*
428 * That's it!
429 */
430 ASMAtomicIncU32(&pDbg->cUsers);
431 ASMAtomicIncU32(&pImg->cUsers);
432 RTSemRWReleaseRead(g_hDbgModRWSem);
433
434 *phDbgMod = pDbgMod;
435 return rc;
436 }
437 }
438
439 /*
440 * Image detected, but found no debug info we were
441 * able to understand.
442 */
443 /** @todo Fall back on exported symbols! */
444 pDbgMod->pImgVt->pfnClose(pDbgMod);
445 break;
446 }
447 }
448
449 /*
450 * Could it be a file containing raw debug info?
451 */
452 if (!pImg)
453 {
454 pDbgMod->pImgVt = NULL;
455 pDbgMod->pvImgPriv = NULL;
456 pDbgMod->pszDbgFile = pDbgMod->pszImgFile;
457 pDbgMod->pszImgFile = NULL;
458
459 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
460 {
461 pDbgMod->pDbgVt = pDbg->pVt;
462 pDbgMod->pvDbgPriv = NULL;
463 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
464 if (RT_SUCCESS(rc))
465 {
466 /*
467 * That's it!
468 */
469 ASMAtomicIncU32(&pDbg->cUsers);
470 RTSemRWReleaseRead(g_hDbgModRWSem);
471
472 *phDbgMod = pDbgMod;
473 return rc;
474 }
475 }
476
477 pDbgMod->pszImgFile = pDbgMod->pszDbgFile;
478 pDbgMod->pszDbgFile = NULL;
479 }
480
481 /* bail out */
482 RTSemRWReleaseRead(g_hDbgModRWSem);
483 }
484 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFileSpecified);
485 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
486 }
487 else
488 rc = VERR_NO_STR_MEMORY;
489 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
490 }
491 else
492 rc = VERR_NO_STR_MEMORY;
493 RTCritSectDelete(&pDbgMod->CritSect);
494 }
495
496 RTMemFree(pDbgMod);
497 return rc;
498}
499RT_EXPORT_SYMBOL(RTDbgModCreateFromImage);
500
501
502
503RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
504 RTUINTPTR uSubtrahend, RTDBGCFG hDbgCfg)
505{
506 /*
507 * Input validation and lazy initialization.
508 */
509 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
510 *phDbgMod = NIL_RTDBGMOD;
511 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
512 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
513 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
514 AssertReturn(uSubtrahend == 0, VERR_NOT_IMPLEMENTED); /** @todo implement uSubtrahend. */
515
516 int rc = rtDbgModLazyInit();
517 if (RT_FAILURE(rc))
518 return rc;
519
520 if (!pszName)
521 pszName = RTPathFilenameEx(pszFilename, RTPATH_STR_F_STYLE_DOS);
522
523 /*
524 * Allocate a new module instance.
525 */
526 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
527 if (!pDbgMod)
528 return VERR_NO_MEMORY;
529 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
530 pDbgMod->cRefs = 1;
531 rc = RTCritSectInit(&pDbgMod->CritSect);
532 if (RT_SUCCESS(rc))
533 {
534 pDbgMod->pszName = RTStrCacheEnterLower(g_hDbgModStrCache, pszName);
535 if (pDbgMod->pszName)
536 {
537 pDbgMod->pszDbgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
538 if (pDbgMod->pszDbgFile)
539 {
540 /*
541 * Try the map file readers.
542 */
543 rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
544 if (RT_SUCCESS(rc))
545 {
546 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
547 for (PRTDBGMODREGDBG pCur = g_pDbgHead; pCur; pCur = pCur->pNext)
548 {
549 if (pCur->pVt->fSupports & RT_DBGTYPE_MAP)
550 {
551 pDbgMod->pDbgVt = pCur->pVt;
552 pDbgMod->pvDbgPriv = NULL;
553 rc = pCur->pVt->pfnTryOpen(pDbgMod);
554 if (RT_SUCCESS(rc))
555 {
556 ASMAtomicIncU32(&pCur->cUsers);
557 RTSemRWReleaseRead(g_hDbgModRWSem);
558
559 *phDbgMod = pDbgMod;
560 return rc;
561 }
562 }
563 }
564
565 /* bail out */
566 RTSemRWReleaseRead(g_hDbgModRWSem);
567 }
568 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
569 }
570 else
571 rc = VERR_NO_STR_MEMORY;
572 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
573 }
574 else
575 rc = VERR_NO_STR_MEMORY;
576 RTCritSectDelete(&pDbgMod->CritSect);
577 }
578
579 RTMemFree(pDbgMod);
580 return rc;
581}
582RT_EXPORT_SYMBOL(RTDbgModCreateFromMap);
583
584
585
586
587/*
588 *
589 * P E I M A G E
590 * P E I M A G E
591 * P E I M A G E
592 *
593 */
594
595
596/**
597 * Opens debug information for an image.
598 *
599 * @returns IPRT status code
600 * @param pDbgMod The debug module structure.
601 *
602 * @note This will generally not look for debug info stored in external
603 * files. rtDbgModFromPeImageExtDbgInfoCallback can help with that.
604 */
605static int rtDbgModOpenDebugInfoInsideImage(PRTDBGMODINT pDbgMod)
606{
607 AssertReturn(!pDbgMod->pDbgVt, VERR_DBG_MOD_IPE);
608 AssertReturn(pDbgMod->pImgVt, VERR_DBG_MOD_IPE);
609
610 int rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
611 if (RT_SUCCESS(rc))
612 {
613 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
614 {
615 pDbgMod->pDbgVt = pDbg->pVt;
616 pDbgMod->pvDbgPriv = NULL;
617 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
618 if (RT_SUCCESS(rc))
619 {
620 /*
621 * That's it!
622 */
623 ASMAtomicIncU32(&pDbg->cUsers);
624 RTSemRWReleaseRead(g_hDbgModRWSem);
625 return VINF_SUCCESS;
626 }
627 pDbgMod->pDbgVt = NULL;
628 Assert(pDbgMod->pvDbgPriv == NULL);
629 }
630 RTSemRWReleaseRead(g_hDbgModRWSem);
631 }
632
633 return VERR_DBG_NO_MATCHING_INTERPRETER;
634}
635
636
637/** @callback_method_impl{FNRTDBGCFGOPEN} */
638static DECLCALLBACK(int) rtDbgModExtDbgInfoOpenCallback(RTDBGCFG hDbgCfg, const char *pszFilename, void *pvUser1, void *pvUser2)
639{
640 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)pvUser1;
641 PCRTLDRDBGINFO pDbgInfo = (PCRTLDRDBGINFO)pvUser2;
642 NOREF(pDbgInfo); /** @todo consider a more direct search for a interpreter. */
643
644 Assert(!pDbgMod->pDbgVt);
645 Assert(!pDbgMod->pvDbgPriv);
646 Assert(!pDbgMod->pszDbgFile);
647
648 /*
649 * Set the debug file name and try possible interpreters.
650 */
651 pDbgMod->pszDbgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
652
653 int rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
654 if (RT_SUCCESS(rc))
655 {
656 for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
657 {
658 pDbgMod->pDbgVt = pDbg->pVt;
659 pDbgMod->pvDbgPriv = NULL;
660 rc = pDbg->pVt->pfnTryOpen(pDbgMod);
661 if (RT_SUCCESS(rc))
662 {
663 /*
664 * Got it!
665 */
666 ASMAtomicIncU32(&pDbg->cUsers);
667 RTSemRWReleaseRead(g_hDbgModRWSem);
668 return VINF_CALLBACK_RETURN;
669 }
670 pDbgMod->pDbgVt = NULL;
671 Assert(pDbgMod->pvDbgPriv == NULL);
672 }
673 }
674
675 /* No joy. */
676 RTSemRWReleaseRead(g_hDbgModRWSem);
677 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
678 pDbgMod->pszDbgFile = NULL;
679 return rc;
680}
681
682
683/**
684 * Argument package used by rtDbgModOpenDebugInfoExternalToImage.
685 */
686typedef struct RTDBGMODOPENDIETI
687{
688 PRTDBGMODINT pDbgMod;
689 RTDBGCFG hDbgCfg;
690} RTDBGMODOPENDIETI;
691
692
693/** @callback_method_impl{FNRTLDRENUMDBG} */
694static DECLCALLBACK(int)
695rtDbgModOpenDebugInfoExternalToImageCallback(RTLDRMOD hLdrMod, PCRTLDRDBGINFO pDbgInfo, void *pvUser)
696{
697 RTDBGMODOPENDIETI *pArgs = (RTDBGMODOPENDIETI *)pvUser;
698
699 Assert(pDbgInfo->enmType > RTLDRDBGINFOTYPE_INVALID && pDbgInfo->enmType < RTLDRDBGINFOTYPE_END);
700 const char *pszExtFile = pDbgInfo->pszExtFile;
701 if (!pszExtFile)
702 {
703 /*
704 * If a external debug type comes without a file name, calculate a
705 * likely debug filename for it. (Hack for NT4 drivers.)
706 */
707 const char *pszExt = NULL;
708 if (pDbgInfo->enmType == RTLDRDBGINFOTYPE_CODEVIEW_DBG)
709 pszExt = ".dbg";
710 else if ( pDbgInfo->enmType == RTLDRDBGINFOTYPE_CODEVIEW_PDB20
711 || pDbgInfo->enmType == RTLDRDBGINFOTYPE_CODEVIEW_PDB70)
712 pszExt = ".pdb";
713 if (pszExt && pArgs->pDbgMod->pszName)
714 {
715 size_t cchName = strlen(pArgs->pDbgMod->pszName);
716 char *psz = (char *)alloca(cchName + strlen(pszExt) + 1);
717 if (psz)
718 {
719 memcpy(psz, pArgs->pDbgMod->pszName, cchName + 1);
720 RTPathStripExt(psz);
721 pszExtFile = strcat(psz, pszExt);
722 }
723 }
724
725 if (!pszExtFile)
726 {
727 Log2(("rtDbgModOpenDebugInfoExternalToImageCallback: enmType=%d\n", pDbgInfo->enmType));
728 return VINF_SUCCESS;
729 }
730 }
731
732 /*
733 * Switch on type and call the appropriate search function.
734 */
735 int rc;
736 switch (pDbgInfo->enmType)
737 {
738 case RTLDRDBGINFOTYPE_CODEVIEW_PDB70:
739 rc = RTDbgCfgOpenPdb70(pArgs->hDbgCfg, pszExtFile,
740 &pDbgInfo->u.Pdb70.Uuid,
741 pDbgInfo->u.Pdb70.uAge,
742 rtDbgModExtDbgInfoOpenCallback, pArgs->pDbgMod, (void *)pDbgInfo);
743 break;
744
745 case RTLDRDBGINFOTYPE_CODEVIEW_PDB20:
746 rc = RTDbgCfgOpenPdb20(pArgs->hDbgCfg, pszExtFile,
747 pDbgInfo->u.Pdb20.cbImage,
748 pDbgInfo->u.Pdb20.uTimestamp,
749 pDbgInfo->u.Pdb20.uAge,
750 rtDbgModExtDbgInfoOpenCallback, pArgs->pDbgMod, (void *)pDbgInfo);
751 break;
752
753 case RTLDRDBGINFOTYPE_CODEVIEW_DBG:
754 rc = RTDbgCfgOpenDbg(pArgs->hDbgCfg, pszExtFile,
755 pDbgInfo->u.Dbg.cbImage,
756 pDbgInfo->u.Dbg.uTimestamp,
757 rtDbgModExtDbgInfoOpenCallback, pArgs->pDbgMod, (void *)pDbgInfo);
758 break;
759
760 case RTLDRDBGINFOTYPE_DWARF_DWO:
761 rc = RTDbgCfgOpenDwo(pArgs->hDbgCfg, pszExtFile,
762 pDbgInfo->u.Dwo.uCrc32,
763 rtDbgModExtDbgInfoOpenCallback, pArgs->pDbgMod, (void *)pDbgInfo);
764 break;
765
766 default:
767 Log(("rtDbgModOpenDebugInfoExternalToImageCallback: Don't know how to handle enmType=%d and pszFileExt=%s\n",
768 pDbgInfo->enmType, pszExtFile));
769 return VERR_DBG_TODO;
770 }
771 if (RT_SUCCESS(rc))
772 {
773 LogFlow(("RTDbgMod: Successfully opened external debug info '%s' for '%s'\n",
774 pArgs->pDbgMod->pszDbgFile, pArgs->pDbgMod->pszImgFile));
775 return VINF_CALLBACK_RETURN;
776 }
777 Log(("rtDbgModOpenDebugInfoExternalToImageCallback: '%s' (enmType=%d) for '%s' -> %Rrc\n",
778 pszExtFile, pDbgInfo->enmType, pArgs->pDbgMod->pszImgFile, rc));
779 return rc;
780}
781
782
783/**
784 * Opens debug info listed in the image that is stored in a separate file.
785 *
786 * @returns IPRT status code
787 * @param pDbgMod The debug module.
788 * @param hDbgCfg The debug config. Can be NIL.
789 */
790static int rtDbgModOpenDebugInfoExternalToImage(PRTDBGMODINT pDbgMod, RTDBGCFG hDbgCfg)
791{
792 Assert(!pDbgMod->pDbgVt);
793
794 RTDBGMODOPENDIETI Args;
795 Args.pDbgMod = pDbgMod;
796 Args.hDbgCfg = hDbgCfg;
797 int rc = pDbgMod->pImgVt->pfnEnumDbgInfo(pDbgMod, rtDbgModOpenDebugInfoExternalToImageCallback, &Args);
798 if (RT_SUCCESS(rc) && pDbgMod->pDbgVt)
799 return VINF_SUCCESS;
800
801 LogFlow(("rtDbgModOpenDebugInfoExternalToImage: rc=%Rrc\n", rc));
802 return VERR_NOT_FOUND;
803}
804
805
806
807/** @callback_method_impl{FNRTDBGCFGOPEN} */
808static DECLCALLBACK(int) rtDbgModFromPeImageOpenCallback(RTDBGCFG hDbgCfg, const char *pszFilename, void *pvUser1, void *pvUser2)
809{
810 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)pvUser1;
811 PRTDBGMODDEFERRED pDeferred = (PRTDBGMODDEFERRED)pvUser2;
812 LogFlow(("rtDbgModFromPeImageOpenCallback: %s\n", pszFilename));
813
814 Assert(pDbgMod->pImgVt == NULL);
815 Assert(pDbgMod->pvImgPriv == NULL);
816 Assert(pDbgMod->pDbgVt == NULL);
817 Assert(pDbgMod->pvDbgPriv == NULL);
818
819 /*
820 * Replace the image file name while probing it.
821 */
822 const char *pszNewImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
823 if (!pszNewImgFile)
824 return VERR_NO_STR_MEMORY;
825 const char *pszOldImgFile = pDbgMod->pszImgFile;
826 pDbgMod->pszImgFile = pszNewImgFile;
827
828 /*
829 * Find an image reader which groks the file.
830 */
831 int rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
832 if (RT_SUCCESS(rc))
833 {
834 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
835 PRTDBGMODREGIMG pImg;
836 for (pImg = g_pImgHead; pImg; pImg = pImg->pNext)
837 {
838 pDbgMod->pImgVt = pImg->pVt;
839 pDbgMod->pvImgPriv = NULL;
840 rc = pImg->pVt->pfnTryOpen(pDbgMod);
841 if (RT_SUCCESS(rc))
842 break;
843 pDbgMod->pImgVt = NULL;
844 Assert(pDbgMod->pvImgPriv == NULL);
845 }
846 RTSemRWReleaseRead(g_hDbgModRWSem);
847 if (RT_SUCCESS(rc))
848 {
849 /*
850 * Check the deferred info.
851 */
852 RTUINTPTR cbImage = pDbgMod->pImgVt->pfnImageSize(pDbgMod);
853 if ( pDeferred->cbImage == 0
854 || pDeferred->cbImage == cbImage)
855 {
856 uint32_t uTimestamp = pDeferred->u.PeImage.uTimestamp; /** @todo add method for getting the timestamp. */
857 if ( pDeferred->u.PeImage.uTimestamp == 0
858 || pDeferred->u.PeImage.uTimestamp == uTimestamp)
859 {
860 Log(("RTDbgMod: Found matching PE image '%s'\n", pszFilename));
861
862 /*
863 * We found the executable image we need, now go find any
864 * debug info associated with it. For PE images, this is
865 * generally found in an external file, so we do a sweep
866 * for that first.
867 *
868 * Then try open debug inside the module, and finally
869 * falling back on exports.
870 */
871 rc = rtDbgModOpenDebugInfoExternalToImage(pDbgMod, pDeferred->hDbgCfg);
872 if (RT_FAILURE(rc))
873 rc = rtDbgModOpenDebugInfoInsideImage(pDbgMod);
874 if (RT_FAILURE(rc))
875 rc = rtDbgModCreateForExports(pDbgMod);
876 if (RT_SUCCESS(rc))
877 {
878 RTStrCacheRelease(g_hDbgModStrCache, pszOldImgFile);
879 return VINF_CALLBACK_RETURN;
880 }
881
882 /* Something bad happened, just give up. */
883 Log(("rtDbgModFromPeImageOpenCallback: rtDbgModCreateForExports failed: %Rrc\n", rc));
884 }
885 else
886 {
887 LogFlow(("rtDbgModFromPeImageOpenCallback: uTimestamp mismatch (found %#x, expected %#x) - %s\n",
888 uTimestamp, pDeferred->u.PeImage.uTimestamp, pszFilename));
889 rc = VERR_DBG_FILE_MISMATCH;
890 }
891 }
892 else
893 {
894 LogFlow(("rtDbgModFromPeImageOpenCallback: cbImage mismatch (found %#x, expected %#x) - %s\n",
895 cbImage, pDeferred->cbImage, pszFilename));
896 rc = VERR_DBG_FILE_MISMATCH;
897 }
898
899 pDbgMod->pImgVt->pfnClose(pDbgMod);
900 pDbgMod->pImgVt = NULL;
901 pDbgMod->pvImgPriv = NULL;
902 }
903 else
904 LogFlow(("rtDbgModFromPeImageOpenCallback: Failed %Rrc - %s\n", rc, pszFilename));
905 }
906
907 /* Restore image name. */
908 pDbgMod->pszImgFile = pszOldImgFile;
909 RTStrCacheRelease(g_hDbgModStrCache, pszNewImgFile);
910 return rc;
911}
912
913
914/** @callback_method_impl{FNRTDBGMODDEFERRED} */
915static DECLCALLBACK(int) rtDbgModFromPeImageDeferredCallback(PRTDBGMODINT pDbgMod, PRTDBGMODDEFERRED pDeferred)
916{
917 int rc;
918
919 Assert(pDbgMod->pszImgFile);
920 if (!pDbgMod->pImgVt)
921 rc = RTDbgCfgOpenPeImage(pDeferred->hDbgCfg, pDbgMod->pszImgFile,
922 pDeferred->cbImage, pDeferred->u.PeImage.uTimestamp,
923 rtDbgModFromPeImageOpenCallback, pDbgMod, pDeferred);
924 else
925 {
926 rc = rtDbgModOpenDebugInfoExternalToImage(pDbgMod, pDeferred->hDbgCfg);
927 if (RT_FAILURE(rc))
928 rc = rtDbgModOpenDebugInfoInsideImage(pDbgMod);
929 if (RT_FAILURE(rc))
930 rc = rtDbgModCreateForExports(pDbgMod);
931 }
932 return rc;
933}
934
935
936RTDECL(int) RTDbgModCreateFromPeImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTLDRMOD hLdrMod,
937 uint32_t cbImage, uint32_t uTimestamp, RTDBGCFG hDbgCfg)
938{
939 /*
940 * Input validation and lazy initialization.
941 */
942 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
943 *phDbgMod = NIL_RTDBGMOD;
944 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
945 AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
946 if (!pszName)
947 pszName = RTPathFilenameEx(pszFilename, RTPATH_STR_F_STYLE_DOS);
948 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
949 AssertReturn(hLdrMod == NIL_RTLDRMOD || RTLdrSize(hLdrMod) != ~(size_t)0, VERR_INVALID_HANDLE);
950
951 int rc = rtDbgModLazyInit();
952 if (RT_FAILURE(rc))
953 return rc;
954
955 uint64_t fDbgCfg = 0;
956 if (hDbgCfg)
957 {
958 rc = RTDbgCfgQueryUInt(hDbgCfg, RTDBGCFGPROP_FLAGS, &fDbgCfg);
959 AssertRCReturn(rc, rc);
960 }
961
962 /*
963 * Allocate a new module instance.
964 */
965 PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
966 if (!pDbgMod)
967 return VERR_NO_MEMORY;
968 pDbgMod->u32Magic = RTDBGMOD_MAGIC;
969 pDbgMod->cRefs = 1;
970 rc = RTCritSectInit(&pDbgMod->CritSect);
971 if (RT_SUCCESS(rc))
972 {
973 pDbgMod->pszName = RTStrCacheEnter(g_hDbgModStrCache, pszName);
974 if (pDbgMod->pszName)
975 {
976 pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
977 if (pDbgMod->pszImgFile)
978 {
979 RTStrCacheRetain(pDbgMod->pszImgFile);
980 pDbgMod->pszImgFileSpecified = pDbgMod->pszImgFile;
981
982 /*
983 * If we have a loader module, we must instantiate the loader
984 * side of things regardless of the deferred setting.
985 */
986 if (hLdrMod != NIL_RTLDRMOD)
987 {
988 if (!cbImage)
989 cbImage = (uint32_t)RTLdrSize(hLdrMod);
990 pDbgMod->pImgVt = &g_rtDbgModVtImgLdr;
991
992 rc = rtDbgModLdrOpenFromHandle(pDbgMod, hLdrMod);
993 }
994 if (RT_SUCCESS(rc))
995 {
996 /*
997 * Do it now or procrastinate?
998 */
999 if (!(fDbgCfg & RTDBGCFG_FLAGS_DEFERRED) || !cbImage)
1000 {
1001 RTDBGMODDEFERRED Deferred;
1002 Deferred.cbImage = cbImage;
1003 Deferred.hDbgCfg = hDbgCfg;
1004 Deferred.u.PeImage.uTimestamp = uTimestamp;
1005 rc = rtDbgModFromPeImageDeferredCallback(pDbgMod, &Deferred);
1006 }
1007 else
1008 {
1009 PRTDBGMODDEFERRED pDeferred;
1010 rc = rtDbgModDeferredCreate(pDbgMod, rtDbgModFromPeImageDeferredCallback, cbImage, hDbgCfg, &pDeferred);
1011 if (RT_SUCCESS(rc))
1012 pDeferred->u.PeImage.uTimestamp = uTimestamp;
1013 }
1014 if (RT_SUCCESS(rc))
1015 {
1016 *phDbgMod = pDbgMod;
1017 return VINF_SUCCESS;
1018 }
1019
1020 /* Failed, bail out. */
1021 if (hLdrMod != NIL_RTLDRMOD)
1022 {
1023 Assert(pDbgMod->pImgVt);
1024 pDbgMod->pImgVt->pfnClose(pDbgMod);
1025 }
1026 }
1027 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
1028 }
1029 else
1030 rc = VERR_NO_STR_MEMORY;
1031 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFileSpecified);
1032 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
1033 }
1034 else
1035 rc = VERR_NO_STR_MEMORY;
1036 RTCritSectDelete(&pDbgMod->CritSect);
1037 }
1038
1039 RTMemFree(pDbgMod);
1040 return rc;
1041}
1042RT_EXPORT_SYMBOL(RTDbgModCreateFromImage);
1043
1044
1045/**
1046 * Destroys an module after the reference count has reached zero.
1047 *
1048 * @param pDbgMod The module instance.
1049 */
1050static void rtDbgModDestroy(PRTDBGMODINT pDbgMod)
1051{
1052 /*
1053 * Close the debug info interpreter first, then the image interpret.
1054 */
1055 RTCritSectEnter(&pDbgMod->CritSect); /* paranoia */
1056
1057 if (pDbgMod->pDbgVt)
1058 {
1059 pDbgMod->pDbgVt->pfnClose(pDbgMod);
1060 pDbgMod->pDbgVt = NULL;
1061 pDbgMod->pvDbgPriv = NULL;
1062 }
1063
1064 if (pDbgMod->pImgVt)
1065 {
1066 pDbgMod->pImgVt->pfnClose(pDbgMod);
1067 pDbgMod->pImgVt = NULL;
1068 pDbgMod->pvImgPriv = NULL;
1069 }
1070
1071 /*
1072 * Free the resources.
1073 */
1074 ASMAtomicWriteU32(&pDbgMod->u32Magic, ~RTDBGMOD_MAGIC);
1075 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
1076 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
1077 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFileSpecified);
1078 RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
1079 RTCritSectLeave(&pDbgMod->CritSect); /* paranoia */
1080 RTCritSectDelete(&pDbgMod->CritSect);
1081 RTMemFree(pDbgMod);
1082}
1083
1084
1085RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod)
1086{
1087 PRTDBGMODINT pDbgMod = hDbgMod;
1088 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1089 return ASMAtomicIncU32(&pDbgMod->cRefs);
1090}
1091RT_EXPORT_SYMBOL(RTDbgModRetain);
1092
1093
1094RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod)
1095{
1096 if (hDbgMod == NIL_RTDBGMOD)
1097 return 0;
1098 PRTDBGMODINT pDbgMod = hDbgMod;
1099 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1100
1101 uint32_t cRefs = ASMAtomicDecU32(&pDbgMod->cRefs);
1102 if (!cRefs)
1103 rtDbgModDestroy(pDbgMod);
1104 return cRefs;
1105}
1106RT_EXPORT_SYMBOL(RTDbgModRelease);
1107
1108
1109RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod)
1110{
1111 PRTDBGMODINT pDbgMod = hDbgMod;
1112 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
1113 return pDbgMod->pszName;
1114}
1115RT_EXPORT_SYMBOL(RTDbgModName);
1116
1117
1118RTDECL(const char *) RTDbgModDebugFile(RTDBGMOD hDbgMod)
1119{
1120 PRTDBGMODINT pDbgMod = hDbgMod;
1121 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
1122 if (pDbgMod->fDeferred || pDbgMod->fExports)
1123 return NULL;
1124 return pDbgMod->pszDbgFile;
1125}
1126RT_EXPORT_SYMBOL(RTDbgModDebugFile);
1127
1128
1129RTDECL(const char *) RTDbgModImageFile(RTDBGMOD hDbgMod)
1130{
1131 PRTDBGMODINT pDbgMod = hDbgMod;
1132 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
1133 return pDbgMod->pszImgFileSpecified;
1134}
1135RT_EXPORT_SYMBOL(RTDbgModImageFile);
1136
1137
1138RTDECL(const char *) RTDbgModImageFileUsed(RTDBGMOD hDbgMod)
1139{
1140 PRTDBGMODINT pDbgMod = hDbgMod;
1141 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NULL);
1142 return pDbgMod->pszImgFile == pDbgMod->pszImgFileSpecified ? NULL : pDbgMod->pszImgFile;
1143}
1144RT_EXPORT_SYMBOL(RTDbgModImageFileUsed);
1145
1146
1147RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
1148{
1149 PRTDBGMODINT pDbgMod = hDbgMod;
1150 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
1151 RTDBGMOD_LOCK(pDbgMod);
1152
1153 RTDBGSEGIDX iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, uRva, poffSeg);
1154
1155 RTDBGMOD_UNLOCK(pDbgMod);
1156 return iSeg;
1157}
1158RT_EXPORT_SYMBOL(RTDbgModRvaToSegOff);
1159
1160
1161RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod)
1162{
1163 PRTDBGMODINT pDbgMod = hDbgMod;
1164 RTDBGMOD_VALID_RETURN_RC(pDbgMod, RTUINTPTR_MAX);
1165 RTDBGMOD_LOCK(pDbgMod);
1166
1167 RTUINTPTR cbImage = pDbgMod->pDbgVt->pfnImageSize(pDbgMod);
1168
1169 RTDBGMOD_UNLOCK(pDbgMod);
1170 return cbImage;
1171}
1172RT_EXPORT_SYMBOL(RTDbgModImageSize);
1173
1174
1175RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod)
1176{
1177 PRTDBGMODINT pDbgMod = hDbgMod;
1178 RTDBGMOD_VALID_RETURN_RC(pDbgMod, 0);
1179 return pDbgMod->uTag;
1180}
1181RT_EXPORT_SYMBOL(RTDbgModGetTag);
1182
1183
1184RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag)
1185{
1186 PRTDBGMODINT pDbgMod = hDbgMod;
1187 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1188 RTDBGMOD_LOCK(pDbgMod);
1189
1190 pDbgMod->uTag = uTag;
1191
1192 RTDBGMOD_UNLOCK(pDbgMod);
1193 return VINF_SUCCESS;
1194}
1195RT_EXPORT_SYMBOL(RTDbgModSetTag);
1196
1197
1198RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
1199 uint32_t fFlags, PRTDBGSEGIDX piSeg)
1200{
1201 /*
1202 * Validate input.
1203 */
1204 PRTDBGMODINT pDbgMod = hDbgMod;
1205 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1206 AssertMsgReturn(uRva + cb >= uRva, ("uRva=%RTptr cb=%RTptr\n", uRva, cb), VERR_DBG_ADDRESS_WRAP);
1207 Assert(*pszName);
1208 size_t cchName = strlen(pszName);
1209 AssertReturn(cchName > 0, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
1210 AssertReturn(cchName < RTDBG_SEGMENT_NAME_LENGTH, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE);
1211 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
1212 AssertPtrNull(piSeg);
1213 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg <= RTDBGSEGIDX_LAST, ("%#x\n", *piSeg), VERR_DBG_SPECIAL_SEGMENT);
1214
1215 /*
1216 * Do the deed.
1217 */
1218 RTDBGMOD_LOCK(pDbgMod);
1219 int rc = pDbgMod->pDbgVt->pfnSegmentAdd(pDbgMod, uRva, cb, pszName, cchName, fFlags, piSeg);
1220 RTDBGMOD_UNLOCK(pDbgMod);
1221
1222 return rc;
1223
1224}
1225RT_EXPORT_SYMBOL(RTDbgModSegmentAdd);
1226
1227
1228RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod)
1229{
1230 PRTDBGMODINT pDbgMod = hDbgMod;
1231 RTDBGMOD_VALID_RETURN_RC(pDbgMod, NIL_RTDBGSEGIDX);
1232 RTDBGMOD_LOCK(pDbgMod);
1233
1234 RTDBGSEGIDX cSegs = pDbgMod->pDbgVt->pfnSegmentCount(pDbgMod);
1235
1236 RTDBGMOD_UNLOCK(pDbgMod);
1237 return cSegs;
1238}
1239RT_EXPORT_SYMBOL(RTDbgModSegmentCount);
1240
1241
1242RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
1243{
1244 AssertMsgReturn(iSeg <= RTDBGSEGIDX_LAST, ("%#x\n", iSeg), VERR_DBG_SPECIAL_SEGMENT);
1245 PRTDBGMODINT pDbgMod = hDbgMod;
1246 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1247 RTDBGMOD_LOCK(pDbgMod);
1248
1249 int rc = pDbgMod->pDbgVt->pfnSegmentByIndex(pDbgMod, iSeg, pSegInfo);
1250
1251 RTDBGMOD_UNLOCK(pDbgMod);
1252 return rc;
1253}
1254RT_EXPORT_SYMBOL(RTDbgModSegmentByIndex);
1255
1256
1257RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
1258{
1259 if (iSeg == RTDBGSEGIDX_RVA)
1260 return RTDbgModImageSize(hDbgMod);
1261 RTDBGSEGMENT SegInfo;
1262 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
1263 return RT_SUCCESS(rc) ? SegInfo.cb : RTUINTPTR_MAX;
1264}
1265RT_EXPORT_SYMBOL(RTDbgModSegmentSize);
1266
1267
1268RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg)
1269{
1270 RTDBGSEGMENT SegInfo;
1271 int rc = RTDbgModSegmentByIndex(hDbgMod, iSeg, &SegInfo);
1272 return RT_SUCCESS(rc) ? SegInfo.uRva : RTUINTPTR_MAX;
1273}
1274RT_EXPORT_SYMBOL(RTDbgModSegmentRva);
1275
1276
1277RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off,
1278 RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal)
1279{
1280 /*
1281 * Validate input.
1282 */
1283 PRTDBGMODINT pDbgMod = hDbgMod;
1284 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1285 AssertPtr(pszSymbol);
1286 size_t cchSymbol = strlen(pszSymbol);
1287 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1288 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1289 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
1290 || ( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
1291 && iSeg <= RTDBGSEGIDX_SPECIAL_LAST),
1292 ("%#x\n", iSeg),
1293 VERR_DBG_INVALID_SEGMENT_INDEX);
1294 AssertMsgReturn(off + cb >= off, ("off=%RTptr cb=%RTptr\n", off, cb), VERR_DBG_ADDRESS_WRAP);
1295 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* currently reserved. */
1296
1297 RTDBGMOD_LOCK(pDbgMod);
1298
1299 /*
1300 * Convert RVAs.
1301 */
1302 if (iSeg == RTDBGSEGIDX_RVA)
1303 {
1304 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1305 if (iSeg == NIL_RTDBGSEGIDX)
1306 {
1307 RTDBGMOD_UNLOCK(pDbgMod);
1308 return VERR_DBG_INVALID_RVA;
1309 }
1310 }
1311
1312 /*
1313 * Get down to business.
1314 */
1315 int rc = pDbgMod->pDbgVt->pfnSymbolAdd(pDbgMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
1316
1317 RTDBGMOD_UNLOCK(pDbgMod);
1318 return rc;
1319}
1320RT_EXPORT_SYMBOL(RTDbgModSymbolAdd);
1321
1322
1323RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod)
1324{
1325 PRTDBGMODINT pDbgMod = hDbgMod;
1326 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1327 RTDBGMOD_LOCK(pDbgMod);
1328
1329 uint32_t cSymbols = pDbgMod->pDbgVt->pfnSymbolCount(pDbgMod);
1330
1331 RTDBGMOD_UNLOCK(pDbgMod);
1332 return cSymbols;
1333}
1334RT_EXPORT_SYMBOL(RTDbgModSymbolCount);
1335
1336
1337RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
1338{
1339 PRTDBGMODINT pDbgMod = hDbgMod;
1340 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1341 RTDBGMOD_LOCK(pDbgMod);
1342
1343 int rc = pDbgMod->pDbgVt->pfnSymbolByOrdinal(pDbgMod, iOrdinal, pSymInfo);
1344
1345 RTDBGMOD_UNLOCK(pDbgMod);
1346 return rc;
1347}
1348RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinal);
1349
1350
1351RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo)
1352{
1353 AssertPtr(ppSymInfo);
1354 *ppSymInfo = NULL;
1355
1356 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1357 if (!pSymInfo)
1358 return VERR_NO_MEMORY;
1359
1360 int rc = RTDbgModSymbolByOrdinal(hDbgMod, iOrdinal, pSymInfo);
1361
1362 if (RT_SUCCESS(rc))
1363 *ppSymInfo = pSymInfo;
1364 else
1365 RTDbgSymbolFree(pSymInfo);
1366 return rc;
1367}
1368RT_EXPORT_SYMBOL(RTDbgModSymbolByOrdinalA);
1369
1370
1371RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1372 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
1373{
1374 /*
1375 * Validate input.
1376 */
1377 PRTDBGMODINT pDbgMod = hDbgMod;
1378 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1379 AssertPtrNull(poffDisp);
1380 AssertPtr(pSymInfo);
1381 AssertReturn(!(fFlags & ~RTDBGSYMADDR_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
1382
1383 RTDBGMOD_LOCK(pDbgMod);
1384
1385 /*
1386 * Convert RVAs.
1387 */
1388 if (iSeg == RTDBGSEGIDX_RVA)
1389 {
1390 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1391 if (iSeg == NIL_RTDBGSEGIDX)
1392 {
1393 RTDBGMOD_UNLOCK(pDbgMod);
1394 return VERR_DBG_INVALID_RVA;
1395 }
1396 }
1397
1398 /*
1399 * Get down to business.
1400 */
1401 int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1402
1403 RTDBGMOD_UNLOCK(pDbgMod);
1404 return rc;
1405}
1406RT_EXPORT_SYMBOL(RTDbgModSymbolByAddr);
1407
1408
1409RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
1410 PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo)
1411{
1412 AssertPtr(ppSymInfo);
1413 *ppSymInfo = NULL;
1414
1415 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1416 if (!pSymInfo)
1417 return VERR_NO_MEMORY;
1418
1419 int rc = RTDbgModSymbolByAddr(hDbgMod, iSeg, off, fFlags, poffDisp, pSymInfo);
1420
1421 if (RT_SUCCESS(rc))
1422 *ppSymInfo = pSymInfo;
1423 else
1424 RTDbgSymbolFree(pSymInfo);
1425 return rc;
1426}
1427RT_EXPORT_SYMBOL(RTDbgModSymbolByAddrA);
1428
1429
1430RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo)
1431{
1432 /*
1433 * Validate input.
1434 */
1435 PRTDBGMODINT pDbgMod = hDbgMod;
1436 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1437 AssertPtr(pszSymbol);
1438 size_t cchSymbol = strlen(pszSymbol);
1439 AssertReturn(cchSymbol, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1440 AssertReturn(cchSymbol < RTDBG_SYMBOL_NAME_LENGTH, VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE);
1441 AssertPtr(pSymInfo);
1442
1443 /*
1444 * Make the query.
1445 */
1446 RTDBGMOD_LOCK(pDbgMod);
1447 int rc = pDbgMod->pDbgVt->pfnSymbolByName(pDbgMod, pszSymbol, cchSymbol, pSymInfo);
1448 RTDBGMOD_UNLOCK(pDbgMod);
1449
1450 return rc;
1451}
1452RT_EXPORT_SYMBOL(RTDbgModSymbolByName);
1453
1454
1455RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo)
1456{
1457 AssertPtr(ppSymInfo);
1458 *ppSymInfo = NULL;
1459
1460 PRTDBGSYMBOL pSymInfo = RTDbgSymbolAlloc();
1461 if (!pSymInfo)
1462 return VERR_NO_MEMORY;
1463
1464 int rc = RTDbgModSymbolByName(hDbgMod, pszSymbol, pSymInfo);
1465
1466 if (RT_SUCCESS(rc))
1467 *ppSymInfo = pSymInfo;
1468 else
1469 RTDbgSymbolFree(pSymInfo);
1470 return rc;
1471}
1472RT_EXPORT_SYMBOL(RTDbgModSymbolByNameA);
1473
1474
1475RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo,
1476 RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal)
1477{
1478 /*
1479 * Validate input.
1480 */
1481 PRTDBGMODINT pDbgMod = hDbgMod;
1482 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1483 AssertPtr(pszFile);
1484 size_t cchFile = strlen(pszFile);
1485 AssertReturn(cchFile, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1486 AssertReturn(cchFile < RTDBG_FILE_NAME_LENGTH, VERR_DBG_FILE_NAME_OUT_OF_RANGE);
1487 AssertMsgReturn( iSeg <= RTDBGSEGIDX_LAST
1488 || iSeg == RTDBGSEGIDX_RVA,
1489 ("%#x\n", iSeg),
1490 VERR_DBG_INVALID_SEGMENT_INDEX);
1491 AssertReturn(uLineNo > 0 && uLineNo < UINT32_MAX, VERR_INVALID_PARAMETER);
1492
1493 RTDBGMOD_LOCK(pDbgMod);
1494
1495 /*
1496 * Convert RVAs.
1497 */
1498 if (iSeg == RTDBGSEGIDX_RVA)
1499 {
1500 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1501 if (iSeg == NIL_RTDBGSEGIDX)
1502 {
1503 RTDBGMOD_UNLOCK(pDbgMod);
1504 return VERR_DBG_INVALID_RVA;
1505 }
1506 }
1507
1508 /*
1509 * Get down to business.
1510 */
1511 int rc = pDbgMod->pDbgVt->pfnLineAdd(pDbgMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
1512
1513 RTDBGMOD_UNLOCK(pDbgMod);
1514 return rc;
1515}
1516RT_EXPORT_SYMBOL(RTDbgModLineAdd);
1517
1518
1519RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod)
1520{
1521 PRTDBGMODINT pDbgMod = hDbgMod;
1522 RTDBGMOD_VALID_RETURN_RC(pDbgMod, UINT32_MAX);
1523 RTDBGMOD_LOCK(pDbgMod);
1524
1525 uint32_t cLineNumbers = pDbgMod->pDbgVt->pfnLineCount(pDbgMod);
1526
1527 RTDBGMOD_UNLOCK(pDbgMod);
1528 return cLineNumbers;
1529}
1530RT_EXPORT_SYMBOL(RTDbgModLineCount);
1531
1532
1533RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
1534{
1535 PRTDBGMODINT pDbgMod = hDbgMod;
1536 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1537 RTDBGMOD_LOCK(pDbgMod);
1538
1539 int rc = pDbgMod->pDbgVt->pfnLineByOrdinal(pDbgMod, iOrdinal, pLineInfo);
1540
1541 RTDBGMOD_UNLOCK(pDbgMod);
1542 return rc;
1543}
1544RT_EXPORT_SYMBOL(RTDbgModLineByOrdinal);
1545
1546
1547RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo)
1548{
1549 AssertPtr(ppLineInfo);
1550 *ppLineInfo = NULL;
1551
1552 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1553 if (!pLineInfo)
1554 return VERR_NO_MEMORY;
1555
1556 int rc = RTDbgModLineByOrdinal(hDbgMod, iOrdinal, pLineInfo);
1557
1558 if (RT_SUCCESS(rc))
1559 *ppLineInfo = pLineInfo;
1560 else
1561 RTDbgLineFree(pLineInfo);
1562 return rc;
1563}
1564RT_EXPORT_SYMBOL(RTDbgModLineByOrdinalA);
1565
1566
1567RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
1568{
1569 /*
1570 * Validate input.
1571 */
1572 PRTDBGMODINT pDbgMod = hDbgMod;
1573 RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
1574 AssertPtrNull(poffDisp);
1575 AssertPtr(pLineInfo);
1576
1577 RTDBGMOD_LOCK(pDbgMod);
1578
1579 /*
1580 * Convert RVAs.
1581 */
1582 if (iSeg == RTDBGSEGIDX_RVA)
1583 {
1584 iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
1585 if (iSeg == NIL_RTDBGSEGIDX)
1586 {
1587 RTDBGMOD_UNLOCK(pDbgMod);
1588 return VERR_DBG_INVALID_RVA;
1589 }
1590 }
1591
1592 int rc = pDbgMod->pDbgVt->pfnLineByAddr(pDbgMod, iSeg, off, poffDisp, pLineInfo);
1593
1594 RTDBGMOD_UNLOCK(pDbgMod);
1595 return rc;
1596}
1597RT_EXPORT_SYMBOL(RTDbgModLineByAddr);
1598
1599
1600RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo)
1601{
1602 AssertPtr(ppLineInfo);
1603 *ppLineInfo = NULL;
1604
1605 PRTDBGLINE pLineInfo = RTDbgLineAlloc();
1606 if (!pLineInfo)
1607 return VERR_NO_MEMORY;
1608
1609 int rc = RTDbgModLineByAddr(hDbgMod, iSeg, off, poffDisp, pLineInfo);
1610
1611 if (RT_SUCCESS(rc))
1612 *ppLineInfo = pLineInfo;
1613 else
1614 RTDbgLineFree(pLineInfo);
1615 return rc;
1616}
1617RT_EXPORT_SYMBOL(RTDbgModLineByAddrA);
1618
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