VirtualBox

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

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

IPRT: Changed RTLDRSEG::pchName to pszName and make sure it's always set to something. Started on implementing a codeview reader.

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