VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmoddeferred.cpp@ 75244

Last change on this file since 75244 was 73494, checked in by vboxsync, 6 years ago

IPRT: Added single stack frame unwind function to RTDbgMod and RTLdr, copying over the PoC from DBGFRStack.cpp. bugref:3897

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.2 KB
Line 
1/* $Id: dbgmoddeferred.cpp 73494 2018-08-04 19:41:30Z vboxsync $ */
2/** @file
3 * IPRT - Debug Module Deferred Loading Stub.
4 */
5
6/*
7 * Copyright (C) 2013-2017 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#include <iprt/dbg.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/mem.h>
38#include <iprt/param.h>
39#include <iprt/path.h>
40#include <iprt/string.h>
41#include "internal/dbgmod.h"
42#include "internal/magics.h"
43
44
45
46/**
47 * Releases the instance data.
48 *
49 * @param pThis The instance data.
50 */
51static void rtDbgModDeferredReleaseInstanceData(PRTDBGMODDEFERRED pThis)
52{
53 AssertPtr(pThis);
54 Assert(pThis->u32Magic == RTDBGMODDEFERRED_MAGIC);
55 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs); Assert(cRefs < 8);
56 if (!cRefs)
57 {
58 RTDbgCfgRelease(pThis->hDbgCfg);
59 pThis->hDbgCfg = NIL_RTDBGCFG;
60 pThis->u32Magic = RTDBGMODDEFERRED_MAGIC_DEAD;
61 RTMemFree(pThis);
62 }
63}
64
65
66/**
67 * Does the deferred loading of the real data (image and/or debug info).
68 *
69 * @returns VINF_SUCCESS or VERR_DBG_DEFERRED_LOAD_FAILED.
70 * @param pMod The generic module instance data.
71 * @param fForcedRetry Whether it's a forced retry by one of the
72 * pfnTryOpen methods.
73 */
74static int rtDbgModDeferredDoIt(PRTDBGMODINT pMod, bool fForcedRetry)
75{
76 RTCritSectEnter(&pMod->CritSect);
77
78 int rc;
79 if (!pMod->fDeferredFailed || fForcedRetry)
80 {
81 bool const fDbgVt = pMod->pDbgVt == &g_rtDbgModVtDbgDeferred;
82 bool const fImgVt = pMod->pImgVt == &g_rtDbgModVtImgDeferred;
83 AssertReturnStmt(fDbgVt || fImgVt, RTCritSectLeave(&pMod->CritSect), VERR_INTERNAL_ERROR_5);
84
85 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)(fDbgVt ? pMod->pvDbgPriv : pMod->pvImgPriv);
86
87 /* Reset the method tables and private data pointes so the deferred loading
88 procedure can figure out what to do and won't get confused. */
89 if (fDbgVt)
90 {
91 pMod->pvDbgPriv = NULL;
92 pMod->pDbgVt = NULL;
93 }
94
95 if (fImgVt)
96 {
97 pMod->pvImgPriv = NULL;
98 pMod->pImgVt = NULL;
99 }
100
101 /* Do the deferred loading. */
102 rc = pThis->pfnDeferred(pMod, pThis);
103 if (RT_SUCCESS(rc))
104 {
105 Assert(!fDbgVt || pMod->pDbgVt != NULL);
106 Assert(!fImgVt || pMod->pImgVt != NULL);
107
108 pMod->fDeferred = false;
109 pMod->fDeferredFailed = false;
110
111 rtDbgModDeferredReleaseInstanceData(pThis);
112 if (fImgVt && fDbgVt)
113 rtDbgModDeferredReleaseInstanceData(pThis);
114 }
115 else
116 {
117 /* Failed, bail out and restore the deferred setup. */
118 pMod->fDeferredFailed = true;
119
120 if (fDbgVt)
121 {
122 Assert(!pMod->pDbgVt);
123 pMod->pDbgVt = &g_rtDbgModVtDbgDeferred;
124 pMod->pvDbgPriv = pThis;
125 }
126
127 if (fImgVt)
128 {
129 Assert(!pMod->pImgVt);
130 pMod->pImgVt = &g_rtDbgModVtImgDeferred;
131 pMod->pvImgPriv = pThis;
132 }
133 }
134 }
135 else
136 rc = VERR_DBG_DEFERRED_LOAD_FAILED;
137
138 RTCritSectLeave(&pMod->CritSect);
139 return rc;
140}
141
142
143
144
145/*
146 *
147 * D e b u g I n f o M e t h o d s
148 * D e b u g I n f o M e t h o d s
149 * D e b u g I n f o M e t h o d s
150 *
151 */
152
153/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
154static DECLCALLBACK(int)
155rtDbgModDeferredDbg_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
156{
157 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
158 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
159 if (RT_SUCCESS(rc))
160 rc = pMod->pDbgVt->pfnUnwindFrame(pMod, iSeg, off, pState);
161 return rc;
162}
163
164
165/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
166static DECLCALLBACK(int) rtDbgModDeferredDbg_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
167 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
168{
169 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
170 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
171 if (RT_SUCCESS(rc))
172 rc = pMod->pDbgVt->pfnLineByAddr(pMod, iSeg, off, poffDisp, pLineInfo);
173 return rc;
174}
175
176
177/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
178static DECLCALLBACK(int) rtDbgModDeferredDbg_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
179{
180 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
181 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
182 if (RT_SUCCESS(rc))
183 rc = pMod->pDbgVt->pfnLineByOrdinal(pMod, iOrdinal, pLineInfo);
184 return rc;
185}
186
187
188/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
189static DECLCALLBACK(uint32_t) rtDbgModDeferredDbg_LineCount(PRTDBGMODINT pMod)
190{
191 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
192 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
193 if (RT_SUCCESS(rc))
194 return pMod->pDbgVt->pfnLineCount(pMod);
195 return 0;
196}
197
198
199/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
200static DECLCALLBACK(int) rtDbgModDeferredDbg_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
201 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
202{
203 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
204 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
205 if (RT_SUCCESS(rc))
206 rc = pMod->pDbgVt->pfnLineAdd(pMod, pszFile, cchFile, uLineNo, iSeg, off, piOrdinal);
207 return rc;
208}
209
210
211/**
212 * Fill in symbol info for the fake start symbol.
213 *
214 * @returns VINF_SUCCESS
215 * @param pThis The deferred load data.
216 * @param pSymInfo The output structure.
217 */
218static int rtDbgModDeferredDbgSymInfo_Start(PRTDBGMODDEFERRED pThis, PRTDBGSYMBOL pSymInfo)
219{
220 pSymInfo->Value = 0;
221 pSymInfo->cb = pThis->cbImage;
222 pSymInfo->offSeg = 0;
223 pSymInfo->iSeg = 0;
224 pSymInfo->fFlags = 0;
225 pSymInfo->iOrdinal = 0;
226 strcpy(pSymInfo->szName, "DeferredStart");
227 return VINF_SUCCESS;
228}
229
230
231/**
232 * Fill in symbol info for the fake last symbol.
233 *
234 * @returns VINF_SUCCESS
235 * @param pThis The deferred load data.
236 * @param pSymInfo The output structure.
237 */
238static int rtDbgModDeferredDbgSymInfo_Last(PRTDBGMODDEFERRED pThis, PRTDBGSYMBOL pSymInfo)
239{
240 pSymInfo->Value = pThis->cbImage - 1;
241 pSymInfo->cb = 0;
242 pSymInfo->offSeg = pThis->cbImage - 1;
243 pSymInfo->iSeg = 0;
244 pSymInfo->fFlags = 0;
245 pSymInfo->iOrdinal = 1;
246 strcpy(pSymInfo->szName, "DeferredLast");
247 return VINF_SUCCESS;
248}
249
250
251/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
252static DECLCALLBACK(int) rtDbgModDeferredDbg_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
253 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
254{
255 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
256 if ( (fFlags & RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED)
257 && iSeg == RTDBGSEGIDX_ABS)
258 return VERR_SYMBOL_NOT_FOUND;
259
260 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
261 if (RT_SUCCESS(rc))
262 rc = pMod->pDbgVt->pfnSymbolByAddr(pMod, iSeg, off, fFlags, poffDisp, pSymInfo);
263 else
264 {
265 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvDbgPriv;
266 if (off == 0)
267 rc = rtDbgModDeferredDbgSymInfo_Start(pThis, pSymInfo);
268 else if (off >= pThis->cbImage - 1 || (fFlags & RTDBGSYMADDR_FLAGS_GREATER_OR_EQUAL))
269 rc = rtDbgModDeferredDbgSymInfo_Last(pThis, pSymInfo);
270 else
271 rc = rtDbgModDeferredDbgSymInfo_Start(pThis, pSymInfo);
272 if (poffDisp)
273 *poffDisp = off - pSymInfo->offSeg;
274 }
275 return rc;
276}
277
278
279/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
280static DECLCALLBACK(int) rtDbgModDeferredDbg_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
281 PRTDBGSYMBOL pSymInfo)
282{
283 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
284 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
285 if (RT_SUCCESS(rc))
286 rc = pMod->pDbgVt->pfnSymbolByName(pMod, pszSymbol, cchSymbol, pSymInfo);
287 else
288 {
289 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvDbgPriv;
290 if ( cchSymbol == sizeof("DeferredStart") - 1
291 && !memcmp(pszSymbol, RT_STR_TUPLE("DeferredStart")))
292 rc = rtDbgModDeferredDbgSymInfo_Start(pThis, pSymInfo);
293 else if ( cchSymbol == sizeof("DeferredLast") - 1
294 && !memcmp(pszSymbol, RT_STR_TUPLE("DeferredLast")))
295 rc = rtDbgModDeferredDbgSymInfo_Last(pThis, pSymInfo);
296 else
297 rc = VERR_SYMBOL_NOT_FOUND;
298 }
299 return rc;
300}
301
302
303/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
304static DECLCALLBACK(int) rtDbgModDeferredDbg_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
305{
306 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
307 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
308 if (RT_SUCCESS(rc))
309 rc = pMod->pDbgVt->pfnSymbolByOrdinal(pMod, iOrdinal, pSymInfo);
310 else
311 {
312 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvDbgPriv;
313 if (iOrdinal == 0)
314 rc = rtDbgModDeferredDbgSymInfo_Start(pThis, pSymInfo);
315 else if (iOrdinal == 1)
316 rc = rtDbgModDeferredDbgSymInfo_Last(pThis, pSymInfo);
317 else
318 rc = VERR_SYMBOL_NOT_FOUND;
319 }
320 return rc;
321}
322
323
324/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
325static DECLCALLBACK(uint32_t) rtDbgModDeferredDbg_SymbolCount(PRTDBGMODINT pMod)
326{
327 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
328 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
329 if (RT_SUCCESS(rc))
330 return pMod->pDbgVt->pfnSymbolCount(pMod);
331 return 2;
332}
333
334
335/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
336static DECLCALLBACK(int) rtDbgModDeferredDbg_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
337 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
338 uint32_t *piOrdinal)
339{
340 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
341 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
342 if (RT_SUCCESS(rc))
343 rc = pMod->pDbgVt->pfnSymbolAdd(pMod, pszSymbol, cchSymbol, iSeg, off, cb, fFlags, piOrdinal);
344 return rc;
345}
346
347
348/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
349static DECLCALLBACK(int) rtDbgModDeferredDbg_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
350{
351 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
352 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
353 if (RT_SUCCESS(rc))
354 rc = pMod->pDbgVt->pfnSegmentByIndex(pMod, iSeg, pSegInfo);
355 else if (iSeg == 0)
356 {
357 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvDbgPriv;
358 pSegInfo->Address = 0;
359 pSegInfo->uRva = 0;
360 pSegInfo->cb = pThis->cbImage;
361 pSegInfo->fFlags = 0;
362 pSegInfo->iSeg = 0;
363 memcpy(pSegInfo->szName, RT_STR_TUPLE("LATER"));
364 rc = VINF_SUCCESS;
365 }
366 else
367 rc = VERR_DBG_INVALID_SEGMENT_INDEX;
368 return rc;
369}
370
371
372/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
373static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDeferredDbg_SegmentCount(PRTDBGMODINT pMod)
374{
375 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
376 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
377 if (RT_SUCCESS(rc))
378 return pMod->pDbgVt->pfnSegmentCount(pMod);
379 return 1;
380}
381
382
383/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
384static DECLCALLBACK(int) rtDbgModDeferredDbg_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
385 size_t cchName, uint32_t fFlags, PRTDBGSEGIDX piSeg)
386{
387 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
388 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
389 if (RT_SUCCESS(rc))
390 rc = pMod->pDbgVt->pfnSegmentAdd(pMod, uRva, cb, pszName, cchName, fFlags, piSeg);
391 return rc;
392}
393
394
395/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
396static DECLCALLBACK(RTUINTPTR) rtDbgModDeferredDbg_ImageSize(PRTDBGMODINT pMod)
397{
398 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvDbgPriv;
399 Assert(pThis->u32Magic == RTDBGMODDEFERRED_MAGIC);
400 return pThis->cbImage;
401}
402
403
404/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
405static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDeferredDbg_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
406{
407 Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
408 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
409 if (RT_SUCCESS(rc))
410 return pMod->pDbgVt->pfnRvaToSegOff(pMod, uRva, poffSeg);
411 return 0;
412}
413
414
415/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
416static DECLCALLBACK(int) rtDbgModDeferredDbg_Close(PRTDBGMODINT pMod)
417{
418 rtDbgModDeferredReleaseInstanceData((PRTDBGMODDEFERRED)pMod->pvDbgPriv);
419 return VINF_SUCCESS;
420}
421
422
423/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
424static DECLCALLBACK(int) rtDbgModDeferredDbg_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
425{
426 NOREF(enmArch);
427 return rtDbgModDeferredDoIt(pMod, true /*fForceRetry*/);
428}
429
430
431
432/** Virtual function table for the deferred debug info reader. */
433DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDeferred =
434{
435 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
436 /*.fSupports = */ RT_DBGTYPE_MAP,
437 /*.pszName = */ "deferred",
438 /*.pfnTryOpen = */ rtDbgModDeferredDbg_TryOpen,
439 /*.pfnClose = */ rtDbgModDeferredDbg_Close,
440
441 /*.pfnRvaToSegOff = */ rtDbgModDeferredDbg_RvaToSegOff,
442 /*.pfnImageSize = */ rtDbgModDeferredDbg_ImageSize,
443
444 /*.pfnSegmentAdd = */ rtDbgModDeferredDbg_SegmentAdd,
445 /*.pfnSegmentCount = */ rtDbgModDeferredDbg_SegmentCount,
446 /*.pfnSegmentByIndex = */ rtDbgModDeferredDbg_SegmentByIndex,
447
448 /*.pfnSymbolAdd = */ rtDbgModDeferredDbg_SymbolAdd,
449 /*.pfnSymbolCount = */ rtDbgModDeferredDbg_SymbolCount,
450 /*.pfnSymbolByOrdinal = */ rtDbgModDeferredDbg_SymbolByOrdinal,
451 /*.pfnSymbolByName = */ rtDbgModDeferredDbg_SymbolByName,
452 /*.pfnSymbolByAddr = */ rtDbgModDeferredDbg_SymbolByAddr,
453
454 /*.pfnLineAdd = */ rtDbgModDeferredDbg_LineAdd,
455 /*.pfnLineCount = */ rtDbgModDeferredDbg_LineCount,
456 /*.pfnLineByOrdinal = */ rtDbgModDeferredDbg_LineByOrdinal,
457 /*.pfnLineByAddr = */ rtDbgModDeferredDbg_LineByAddr,
458
459 /*.pfnUnwindFrame = */ rtDbgModDeferredDbg_UnwindFrame,
460
461 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
462};
463
464
465
466
467/*
468 *
469 * I m a g e M e t h o d s
470 * I m a g e M e t h o d s
471 * I m a g e M e t h o d s
472 *
473 */
474
475/** @interface_method_impl{RTDBGMODVTIMG,pfnUnwindFrame} */
476static DECLCALLBACK(int)
477rtDbgModDeferredImg_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
478{
479 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
480 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
481 if (RT_SUCCESS(rc))
482 rc = pMod->pImgVt->pfnUnwindFrame(pMod, iSeg, off, pState);
483 return rc;
484}
485
486
487/** @interface_method_impl{RTDBGMODVTIMG,pfnQueryProp} */
488static DECLCALLBACK(int)
489rtDbgModDeferredImg_QueryProp(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet)
490{
491 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
492 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
493 if (RT_SUCCESS(rc))
494 rc = pMod->pImgVt->pfnQueryProp(pMod, enmProp, pvBuf, cbBuf, pcbRet);
495 return rc;
496}
497
498
499/** @interface_method_impl{RTDBGMODVTIMG,pfnGetArch} */
500static DECLCALLBACK(RTLDRARCH) rtDbgModDeferredImg_GetArch(PRTDBGMODINT pMod)
501{
502 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
503
504 RTLDRARCH enmArch;
505 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
506 if (RT_SUCCESS(rc))
507 enmArch = pMod->pImgVt->pfnGetArch(pMod);
508 else
509 enmArch = RTLDRARCH_WHATEVER;
510 return enmArch;
511}
512
513
514/** @interface_method_impl{RTDBGMODVTIMG,pfnGetFormat} */
515static DECLCALLBACK(RTLDRFMT) rtDbgModDeferredImg_GetFormat(PRTDBGMODINT pMod)
516{
517 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
518
519 RTLDRFMT enmFmt;
520 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
521 if (RT_SUCCESS(rc))
522 enmFmt = pMod->pImgVt->pfnGetFormat(pMod);
523 else
524 enmFmt = RTLDRFMT_INVALID;
525 return enmFmt;
526}
527
528
529/** @interface_method_impl{RTDBGMODVTIMG,pfnReadAt} */
530static DECLCALLBACK(int) rtDbgModDeferredImg_ReadAt(PRTDBGMODINT pMod, uint32_t iDbgInfoHint, RTFOFF off, void *pvBuf, size_t cb)
531{
532 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
533 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
534 if (RT_SUCCESS(rc))
535 rc = pMod->pImgVt->pfnReadAt(pMod, iDbgInfoHint, off, pvBuf, cb);
536 return rc;
537}
538
539
540/** @interface_method_impl{RTDBGMODVTIMG,pfnUnmapPart} */
541static DECLCALLBACK(int) rtDbgModDeferredImg_UnmapPart(PRTDBGMODINT pMod, size_t cb, void const **ppvMap)
542{
543 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
544 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
545 if (RT_SUCCESS(rc))
546 rc = pMod->pImgVt->pfnUnmapPart(pMod, cb, ppvMap);
547 return rc;
548}
549
550
551/** @interface_method_impl{RTDBGMODVTIMG,pfnMapPart} */
552static DECLCALLBACK(int) rtDbgModDeferredImg_MapPart(PRTDBGMODINT pMod, uint32_t iDbgInfo, RTFOFF off, size_t cb, void const **ppvMap)
553{
554 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
555 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
556 if (RT_SUCCESS(rc))
557 rc = pMod->pImgVt->pfnMapPart(pMod, iDbgInfo, off, cb, ppvMap);
558 return rc;
559}
560
561
562/** @interface_method_impl{RTDBGMODVTIMG,pfnImageSize} */
563static DECLCALLBACK(RTUINTPTR) rtDbgModDeferredImg_ImageSize(PRTDBGMODINT pMod)
564{
565 PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)pMod->pvImgPriv;
566 Assert(pThis->u32Magic == RTDBGMODDEFERRED_MAGIC);
567 return pThis->cbImage;
568}
569
570
571/** @interface_method_impl{RTDBGMODVTIMG,pfnRvaToSegOffset} */
572static DECLCALLBACK(int) rtDbgModDeferredImg_RvaToSegOffset(PRTDBGMODINT pMod, RTLDRADDR Rva,
573 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg)
574{
575 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
576 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
577 if (RT_SUCCESS(rc))
578 rc = pMod->pImgVt->pfnRvaToSegOffset(pMod, Rva, piSeg, poffSeg);
579 return rc;
580}
581
582
583/** @interface_method_impl{RTDBGMODVTIMG,pfnLinkAddressToSegOffset} */
584static DECLCALLBACK(int) rtDbgModDeferredImg_LinkAddressToSegOffset(PRTDBGMODINT pMod, RTLDRADDR LinkAddress,
585 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg)
586{
587 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
588 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
589 if (RT_SUCCESS(rc))
590 rc = pMod->pImgVt->pfnLinkAddressToSegOffset(pMod, LinkAddress, piSeg, poffSeg);
591 return rc;
592}
593
594
595/** @interface_method_impl{RTDBGMODVTIMG,pfnEnumSymbols} */
596static DECLCALLBACK(int) rtDbgModDeferredImg_EnumSymbols(PRTDBGMODINT pMod, uint32_t fFlags, RTLDRADDR BaseAddress,
597 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
598{
599 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
600 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
601 if (RT_SUCCESS(rc))
602 rc = pMod->pImgVt->pfnEnumSymbols(pMod, fFlags, BaseAddress, pfnCallback, pvUser);
603 return rc;
604}
605
606
607/** @interface_method_impl{RTDBGMODVTIMG,pfnEnumSegments} */
608static DECLCALLBACK(int) rtDbgModDeferredImg_EnumSegments(PRTDBGMODINT pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
609{
610 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
611 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
612 if (RT_SUCCESS(rc))
613 rc = pMod->pImgVt->pfnEnumSegments(pMod, pfnCallback, pvUser);
614 return rc;
615}
616
617
618/** @interface_method_impl{RTDBGMODVTIMG,pfnEnumDbgInfo} */
619static DECLCALLBACK(int) rtDbgModDeferredImg_EnumDbgInfo(PRTDBGMODINT pMod, PFNRTLDRENUMDBG pfnCallback, void *pvUser)
620{
621 Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
622 int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
623 if (RT_SUCCESS(rc))
624 rc = pMod->pImgVt->pfnEnumDbgInfo(pMod, pfnCallback, pvUser);
625 return rc;
626}
627
628
629/** @interface_method_impl{RTDBGMODVTIMG,pfnClose} */
630static DECLCALLBACK(int) rtDbgModDeferredImg_Close(PRTDBGMODINT pMod)
631{
632 rtDbgModDeferredReleaseInstanceData((PRTDBGMODDEFERRED)pMod->pvImgPriv);
633 return VINF_SUCCESS;
634}
635
636
637/** @interface_method_impl{RTDBGMODVTIMG,pfnTryOpen} */
638static DECLCALLBACK(int) rtDbgModDeferredImg_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
639{
640 NOREF(enmArch);
641 return rtDbgModDeferredDoIt(pMod, true /*fForceRetry*/);
642}
643
644
645/** Virtual function table for the RTLdr based image reader. */
646DECL_HIDDEN_CONST(RTDBGMODVTIMG) const g_rtDbgModVtImgDeferred =
647{
648 /*.u32Magic = */ RTDBGMODVTIMG_MAGIC,
649 /*.fReserved = */ 0,
650 /*.pszName = */ "deferred",
651 /*.pfnTryOpen = */ rtDbgModDeferredImg_TryOpen,
652 /*.pfnClose = */ rtDbgModDeferredImg_Close,
653 /*.pfnEnumDbgInfo = */ rtDbgModDeferredImg_EnumDbgInfo,
654 /*.pfnEnumSegments = */ rtDbgModDeferredImg_EnumSegments,
655 /*.pfnEnumSymbols = */ rtDbgModDeferredImg_EnumSymbols,
656 /*.pfnGetLoadedSize = */ rtDbgModDeferredImg_ImageSize,
657 /*.pfnLinkAddressToSegOffset = */ rtDbgModDeferredImg_LinkAddressToSegOffset,
658 /*.pfnRvaToSegOffset = */ rtDbgModDeferredImg_RvaToSegOffset,
659 /*.pfnMapPart = */ rtDbgModDeferredImg_MapPart,
660 /*.pfnUnmapPart = */ rtDbgModDeferredImg_UnmapPart,
661 /*.pfnReadAt = */ rtDbgModDeferredImg_ReadAt,
662 /*.pfnGetFormat = */ rtDbgModDeferredImg_GetFormat,
663 /*.pfnGetArch = */ rtDbgModDeferredImg_GetArch,
664 /*.pfnQueryProp = */ rtDbgModDeferredImg_QueryProp,
665 /*.pfnUnwindFrame = */ rtDbgModDeferredImg_UnwindFrame,
666
667 /*.u32EndMagic = */ RTDBGMODVTIMG_MAGIC
668};
669
670
671/**
672 * Creates a deferred loading stub for both image and debug info.
673 *
674 * @returns IPRT status code.
675 * @param pDbgMod The debug module.
676 * @param pfnDeferred The callback that will try load the image and
677 * debug info.
678 * @param cbImage The size of the image.
679 * @param hDbgCfg The debug config handle. Can be NIL. A
680 * reference will be retained.
681 * @param cbDeferred The size of the deferred instance data, 0 if the
682 * default structure is good enough.
683 * @param ppDeferred Where to return the instance data. Can be NULL.
684 */
685DECLHIDDEN(int) rtDbgModDeferredCreate(PRTDBGMODINT pDbgMod, PFNRTDBGMODDEFERRED pfnDeferred, RTUINTPTR cbImage,
686 RTDBGCFG hDbgCfg, size_t cbDeferred, PRTDBGMODDEFERRED *ppDeferred)
687{
688 AssertReturn(!pDbgMod->pDbgVt, VERR_DBG_MOD_IPE);
689
690 if (cbDeferred < sizeof(RTDBGMODDEFERRED))
691 cbDeferred = sizeof(RTDBGMODDEFERRED);
692 PRTDBGMODDEFERRED pDeferred = (PRTDBGMODDEFERRED)RTMemAllocZ(cbDeferred);
693 if (!pDeferred)
694 return VERR_NO_MEMORY;
695
696 pDeferred->u32Magic = RTDBGMODDEFERRED_MAGIC;
697 pDeferred->cRefs = 1 + (pDbgMod->pImgVt == NULL);
698 pDeferred->cbImage = cbImage;
699 if (hDbgCfg != NIL_RTDBGCFG)
700 RTDbgCfgRetain(hDbgCfg);
701 pDeferred->hDbgCfg = hDbgCfg;
702 pDeferred->pfnDeferred = pfnDeferred;
703
704 pDbgMod->pDbgVt = &g_rtDbgModVtDbgDeferred;
705 pDbgMod->pvDbgPriv = pDeferred;
706 if (!pDbgMod->pImgVt)
707 {
708 pDbgMod->pImgVt = &g_rtDbgModVtImgDeferred;
709 pDbgMod->pvImgPriv = pDeferred;
710 }
711 pDbgMod->fDeferred = true;
712 pDbgMod->fDeferredFailed = false;
713
714 if (ppDeferred)
715 *ppDeferred = pDeferred;
716 return VINF_SUCCESS;
717}
718
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