VirtualBox

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

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

IPRT: More RTDbg coding - generic container is mostly done now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.4 KB
Line 
1
2/*******************************************************************************
3* Header Files *
4*******************************************************************************/
5#include <iprt/dbg.h>
6
7#include <iprt/avl.h>
8#include <iprt/err.h>
9#include <iprt/mem.h>
10#include <iprt/string.h>
11#include <iprt/strcache.h>
12#include "internal/dbgmod.h"
13
14
15/*******************************************************************************
16* Structures and Typedefs *
17*******************************************************************************/
18/**
19 * Symbol entry.
20 */
21typedef struct RTDBGMODCTNSYMBOL
22{
23 /** The address core. */
24 AVLRUINTPTRNODECORE AddrCore;
25 /** The name space core. */
26 RTSTRSPACECORE NameCore;
27 /** The ordinal number core. */
28 AVLU32NODECORE OrdinalCore;
29 /** The segment index. */
30 RTDBGSEGIDX iSeg;
31 /** The symbol flags. */
32 uint32_t fFlags;
33 /** The symbol size.
34 * This may be zero while the range in AddrCore indicates 0. */
35 RTUINTPTR cb;
36} RTDBGMODCTNSYMBOL;
37/** Pointer to a symbol entry in the debug info container. */
38typedef RTDBGMODCTNSYMBOL *PRTDBGMODCTNSYMBOL;
39/** Pointer to a const symbol entry in the debug info container. */
40typedef RTDBGMODCTNSYMBOL const *PCRTDBGMODCTNSYMBOL;
41
42/**
43 * Line number entry.
44 */
45typedef struct RTDBGMODCTNLINE
46{
47 /** The address core.
48 * The Key is the address of the line number. */
49 AVLUINTPTRNODECORE AddrCore;
50 /** The ordinal number core. */
51 AVLU32NODECORE OrdinalCore;
52 /** Pointer to the file name (in string cache). */
53 const char *pszFile;
54 /** The line number. */
55 uint32_t uLineNo;
56 /** The segment index. */
57 RTDBGSEGIDX iSeg;
58} RTDBGMODCTNLINE;
59/** Pointer to a line number entry. */
60typedef RTDBGMODCTNLINE *PRTDBGMODCTNLINE;
61/** Pointer to const a line number entry. */
62typedef RTDBGMODCTNLINE const *PCRTDBGMODCTNLINE;
63
64/**
65 * Segment entry.
66 */
67typedef struct RTDBGMODCTNSEGMENT
68{
69 /** The symbol address space tree. */
70 AVLRUINTPTRTREE SymAddrTree;
71 /** The line number address space tree. */
72 AVLUINTPTRTREE LineAddrTree;
73 /** The segment offset. */
74 RTUINTPTR off;
75 /** The segment size. */
76 RTUINTPTR cb;
77 /** The segment flags. */
78 uint32_t fFlags;
79 /** The segment name. */
80 const char *pszName;
81} RTDBGMODCTNSEGMENT;
82/** Pointer to a segment entry in the debug info container. */
83typedef RTDBGMODCTNSEGMENT *PRTDBGMODCTNSEGMENT;
84/** Pointer to a const segment entry in the debug info container. */
85typedef RTDBGMODCTNSEGMENT const *PCRTDBGMODCTNSEGMENT;
86
87/**
88 * Instance data.
89 */
90typedef struct RTDBGMODCTN
91{
92 /** The name space. */
93 RTSTRSPACE Names;
94 /** Tree containing any absolute addresses. */
95 AVLRUINTPTRTREE AbsAddrTree;
96 /** Tree organizing the symbols by ordinal number. */
97 AVLU32TREE SymbolOrdinalTree;
98 /** Tree organizing the line numbers by ordinal number. */
99 AVLU32TREE LineOrdinalTree;
100 /** Segment table. */
101 PRTDBGMODCTNSEGMENT paSegs;
102 /** The number of segments in the segment table. */
103 RTDBGSEGIDX cSegs;
104 /** The image size. 0 means unlimited. */
105 RTUINTPTR cb;
106 /** The next symbol ordinal. */
107 uint32_t iNextSymbolOrdinal;
108 /** The next line number ordinal. */
109 uint32_t iNextLineOrdinal;
110} RTDBGMODCTN;
111/** Pointer to instance data for the debug info container. */
112typedef RTDBGMODCTN *PRTDBGMODCTN;
113
114
115/**
116 * Fills in a RTDBGSYMBOL structure.
117 *
118 * @returns VINF_SUCCESS.
119 * @param pMySym Our internal symbol representation.
120 * @param pExtSym The external symbol representation.
121 */
122DECLINLINE(int) rtDbgModContainerReturnSymbol(PCRTDBGMODCTNSYMBOL pMySym, PRTDBGSYMBOL pExtSym)
123{
124 pExtSym->Value = pMySym->AddrCore.Key;
125 pExtSym->offSeg = pMySym->AddrCore.Key;
126 pExtSym->iSeg = pMySym->iSeg;
127 pExtSym->fFlags = pMySym->fFlags;
128 pExtSym->cb = pMySym->cb;
129 pExtSym->iOrdinal = pMySym->OrdinalCore.Key;
130 Assert(pMySym->NameCore.cchString < sizeof(pExtSym->szName));
131 memcpy(pExtSym->szName, pMySym->NameCore.pszString, pMySym->NameCore.cchString + 1);
132 return VINF_SUCCESS;
133}
134
135
136
137/** @copydoc RTDBGMODVTDBG::pfnLineByAddr */
138static DECLCALLBACK(int) rtDbgModContainer_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
139 PRTINTPTR poffDisp, PRTDBGLINE pLine)
140{
141 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
142
143 /*
144 * Validate the input address.
145 */
146 AssertMsgReturn(iSeg < pThis->cSegs,
147 ("iSeg=%#x cSegs=%#x\n", pThis->cSegs),
148 VERR_DBG_INVALID_SEGMENT_INDEX);
149 AssertMsgReturn(pThis->paSegs[iSeg].cb < off,
150 ("off=%RTptr cbSeg=%RTptr\n", off, pThis->paSegs[iSeg].cb),
151 VERR_DBG_INVALID_SEGMENT_OFFSET);
152
153 /*
154 * Lookup the nearest line number with an address less or equal to the specified address.
155 */
156 PAVLUINTPTRNODECORE pAvlCore = RTAvlUIntPtrGetBestFit(&pThis->paSegs[iSeg].LineAddrTree, off, false /*fAbove*/);
157 if (!pAvlCore)
158 return pThis->iNextLineOrdinal
159 ? VERR_DBG_LINE_NOT_FOUND
160 : VERR_DBG_NO_LINE_NUMBERS;
161 PCRTDBGMODCTNLINE pMyLine = RT_FROM_MEMBER(pAvlCore, RTDBGMODCTNLINE const, AddrCore);
162 pLine->Address = pMyLine->AddrCore.Key;
163 pLine->offSeg = pMyLine->AddrCore.Key;
164 pLine->iSeg = iSeg;
165 pLine->uLineNo = pMyLine->uLineNo;
166 pLine->iOrdinal = pMyLine->OrdinalCore.Key;
167 strcpy(pLine->szFilename, pMyLine->pszFile);
168 if (poffDisp)
169 *poffDisp = off - pMyLine->AddrCore.Key;
170 return VINF_SUCCESS;
171}
172
173
174/** @copydoc RTDBGMODVTDBG::pfnLineByOrdinal */
175static DECLCALLBACK(int) rtDbgModContainer_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLine)
176{
177 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
178
179 /*
180 * Look it up.
181 */
182 if (iOrdinal >= pThis->iNextLineOrdinal)
183 return pThis->iNextLineOrdinal
184 ? VERR_DBG_LINE_NOT_FOUND
185 : VERR_DBG_NO_LINE_NUMBERS;
186 PAVLU32NODECORE pAvlCore = RTAvlU32Get(&pThis->LineOrdinalTree, iOrdinal);
187 AssertReturn(pAvlCore, VERR_DBG_LINE_NOT_FOUND);
188 PCRTDBGMODCTNLINE pMyLine = RT_FROM_MEMBER(pAvlCore, RTDBGMODCTNLINE const, OrdinalCore);
189 pLine->Address = pMyLine->AddrCore.Key;
190 pLine->offSeg = pMyLine->AddrCore.Key;
191 pLine->iSeg = pMyLine->iSeg;
192 pLine->uLineNo = pMyLine->uLineNo;
193 pLine->iOrdinal = pMyLine->OrdinalCore.Key;
194 strcpy(pLine->szFilename, pMyLine->pszFile);
195 return VINF_SUCCESS;
196}
197
198
199/** @copydoc RTDBGMODVTDBG::pfnLineCount */
200static DECLCALLBACK(uint32_t) rtDbgModContainer_LineCount(PRTDBGMODINT pMod)
201{
202 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
203
204 /* Note! The ordinal numbers are 0-based. */
205 return pThis->iNextLineOrdinal;
206}
207
208
209/** @copydoc RTDBGMODVTDBG::pfnLineAdd */
210static DECLCALLBACK(int) rtDbgModContainer_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
211 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
212{
213 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
214
215 /*
216 * Validate the input address.
217 */
218 AssertMsgReturn(iSeg < pThis->cSegs, ("iSeg=%#x cSegs=%#x\n", pThis->cSegs),
219 VERR_DBG_INVALID_SEGMENT_INDEX);
220 AssertMsgReturn(pThis->paSegs[iSeg].cb < off, ("off=%RTptr cbSeg=%RTptr\n", off, pThis->paSegs[iSeg].cb),
221 VERR_DBG_INVALID_SEGMENT_OFFSET);
222
223 /*
224 * Create a new entry.
225 */
226 PRTDBGMODCTNLINE pLine = (PRTDBGMODCTNLINE)RTMemAllocZ(sizeof(*pLine));
227 if (!pLine)
228 return VERR_NO_MEMORY;
229 pLine->AddrCore.Key = off;
230 pLine->OrdinalCore.Key = pThis->iNextLineOrdinal;
231 pLine->uLineNo = uLineNo;
232 pLine->iSeg = iSeg;
233 pLine->pszFile = RTStrCacheEnterN(g_hDbgModStrCache, pszFile, cchFile);
234 int rc;
235 if (pLine->pszFile)
236 {
237 if (RTAvlUIntPtrInsert(&pThis->paSegs[iSeg].LineAddrTree, &pLine->AddrCore))
238 {
239 if (RTAvlU32Insert(&pThis->LineOrdinalTree, &pLine->OrdinalCore))
240 {
241 if (piOrdinal)
242 *piOrdinal = pThis->iNextLineOrdinal;
243 pThis->iNextLineOrdinal++;
244 return VINF_SUCCESS;
245 }
246
247 rc = VERR_INTERNAL_ERROR_5;
248 RTAvlUIntPtrRemove(&pThis->paSegs[iSeg].LineAddrTree, pLine->AddrCore.Key);
249 }
250
251 /* bail out */
252 rc = VERR_DBG_ADDRESS_CONFLICT;
253 RTStrCacheRelease(g_hDbgModStrCache, pLine->pszFile);
254 }
255 else
256 rc = VERR_NO_MEMORY;
257 RTMemFree(pLine);
258 return rc;
259}
260
261
262/** @copydoc RTDBGMODVTDBG::pfnSymbolByAddr */
263static DECLCALLBACK(int) rtDbgModContainer_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
264 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol)
265{
266 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
267
268 /*
269 * Validate the input address.
270 */
271 AssertMsgReturn( iSeg == RTDBGSEGIDX_ABS
272 || iSeg < pThis->cSegs,
273 ("iSeg=%#x cSegs=%#x\n", pThis->cSegs),
274 VERR_DBG_INVALID_SEGMENT_INDEX);
275 AssertMsgReturn( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
276 || pThis->paSegs[iSeg].cb <= off,
277 ("off=%RTptr cbSeg=%RTptr\n", off, pThis->paSegs[iSeg].cb),
278 VERR_DBG_INVALID_SEGMENT_OFFSET);
279
280 /*
281 * Lookup the nearest symbol with an address less or equal to the specified address.
282 */
283 PAVLRUINTPTRNODECORE pAvlCore = RTAvlrUIntPtrGetBestFit( iSeg == RTDBGSEGIDX_ABS
284 ? &pThis->AbsAddrTree
285 : &pThis->paSegs[iSeg].SymAddrTree,
286 off,
287 false /*fAbove*/);
288 if (!pAvlCore)
289 return VERR_SYMBOL_NOT_FOUND;
290 PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pAvlCore, RTDBGMODCTNSYMBOL const, AddrCore);
291 if (poffDisp)
292 *poffDisp = off - pMySym->AddrCore.Key;
293 return rtDbgModContainerReturnSymbol(pMySym, pSymbol);
294}
295
296
297/** @copydoc RTDBGMODVTDBG::pfnSymbolByName */
298static DECLCALLBACK(int) rtDbgModContainer_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, PRTDBGSYMBOL pSymbol)
299{
300 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
301
302 /*
303 * Look it up in the name space.
304 */
305 PRTSTRSPACECORE pStrCore = RTStrSpaceGet(&pThis->Names, pszSymbol);
306 if (!pStrCore)
307 return VERR_SYMBOL_NOT_FOUND;
308 PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pStrCore, RTDBGMODCTNSYMBOL const, NameCore);
309 return rtDbgModContainerReturnSymbol(pMySym, pSymbol);
310}
311
312
313/** @copydoc RTDBGMODVTDBG::pfnSymbolByOrdinal */
314static DECLCALLBACK(int) rtDbgModContainer_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymbol)
315{
316 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
317
318 /*
319 * Look it up in the ordinal tree.
320 */
321 if (iOrdinal >= pThis->iNextSymbolOrdinal)
322 return pThis->iNextSymbolOrdinal
323 ? VERR_DBG_NO_SYMBOLS
324 : VERR_SYMBOL_NOT_FOUND;
325 PAVLU32NODECORE pAvlCore = RTAvlU32Get(&pThis->SymbolOrdinalTree, iOrdinal);
326 AssertReturn(pAvlCore, VERR_SYMBOL_NOT_FOUND);
327 PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pAvlCore, RTDBGMODCTNSYMBOL const, OrdinalCore);
328 return rtDbgModContainerReturnSymbol(pMySym, pSymbol);
329}
330
331
332/** @copydoc RTDBGMODVTDBG::pfnSymbolCount */
333static DECLCALLBACK(uint32_t) rtDbgModContainer_SymbolCount(PRTDBGMODINT pMod)
334{
335 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
336
337 /* Note! The ordinal numbers are 0-based. */
338 return pThis->iNextSymbolOrdinal;
339}
340
341
342/** @copydoc RTDBGMODVTDBG::pfnSymbolAdd */
343static DECLCALLBACK(int) rtDbgModContainer_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
344 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
345 uint32_t *piOrdinal)
346{
347 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
348
349 /*
350 * Address validation. The other arguments have already been validated.
351 */
352 AssertMsgReturn( iSeg == RTDBGSEGIDX_ABS
353 || iSeg < pThis->cSegs,
354 ("iSeg=%#x cSegs=%#x\n", pThis->cSegs),
355 VERR_DBG_INVALID_SEGMENT_INDEX);
356 AssertMsgReturn( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
357 || pThis->paSegs[iSeg].cb <= off + cb,
358 ("off=%RTptr cb=%RTptr cbSeg=%RTptr\n", off, cb, pThis->paSegs[iSeg].cb),
359 VERR_DBG_INVALID_SEGMENT_OFFSET);
360
361 /*
362 * Create a new entry.
363 */
364 PRTDBGMODCTNSYMBOL pSymbol = (PRTDBGMODCTNSYMBOL)RTMemAllocZ(sizeof(*pSymbol));
365 if (!pSymbol)
366 return VERR_NO_MEMORY;
367
368 pSymbol->AddrCore.Key = off;
369 pSymbol->AddrCore.KeyLast = off + RT_MAX(cb, 1);
370 pSymbol->OrdinalCore.Key = pThis->iNextSymbolOrdinal;
371 pSymbol->iSeg = iSeg;
372 pSymbol->cb = cb;
373 pSymbol->fFlags = fFlags;
374 pSymbol->NameCore.pszString = RTStrCacheEnter(g_hDbgModStrCache, pszSymbol);
375 int rc;
376 if (pSymbol->NameCore.pszString)
377 {
378 if (RTStrSpaceInsert(&pThis->Names, &pSymbol->NameCore))
379 {
380 PAVLRUINTPTRTREE pAddrTree = iSeg == RTDBGSEGIDX_ABS
381 ? &pThis->AbsAddrTree
382 : &pThis->paSegs[iSeg].SymAddrTree;
383 if (RTAvlrUIntPtrInsert(pAddrTree, &pSymbol->AddrCore))
384 {
385 if (RTAvlU32Insert(&pThis->LineOrdinalTree, &pSymbol->OrdinalCore))
386 {
387 if (piOrdinal)
388 *piOrdinal = pThis->iNextSymbolOrdinal;
389 pThis->iNextSymbolOrdinal++;
390 return VINF_SUCCESS;
391 }
392
393 /* bail out */
394 rc = VERR_INTERNAL_ERROR_5;
395 RTAvlrUIntPtrRemove(pAddrTree, pSymbol->AddrCore.Key);
396 }
397 else
398 rc = VERR_DBG_ADDRESS_CONFLICT;
399 RTStrSpaceRemove(&pThis->Names, pSymbol->NameCore.pszString);
400 }
401 else
402 rc = VERR_DBG_DUPLICATE_SYMBOL;
403 RTStrCacheRelease(g_hDbgModStrCache, pSymbol->NameCore.pszString);
404 }
405 else
406 rc = VERR_NO_MEMORY;
407 RTMemFree(pSymbol);
408 return rc;
409}
410
411
412/** @copydoc RTDBGMODVTDBG::pfnSegmentByIndex */
413static DECLCALLBACK(int) rtDbgModContainer_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
414{
415 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
416 if (iSeg >= pThis->cSegs)
417 return VERR_DBG_INVALID_SEGMENT_INDEX;
418 pSegInfo->Address = RTUINTPTR_MAX;
419 pSegInfo->uRva = pThis->paSegs[iSeg].off;
420 pSegInfo->cb = pThis->paSegs[iSeg].cb;
421 pSegInfo->fFlags = pThis->paSegs[iSeg].fFlags;
422 pSegInfo->iSeg = iSeg;
423 strcpy(pSegInfo->szName, pThis->paSegs[iSeg].pszName);
424 return VINF_SUCCESS;
425}
426
427
428/** @copydoc RTDBGMODVTDBG::pfnSegmentCount */
429static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_SegmentCount(PRTDBGMODINT pMod)
430{
431 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
432 return pThis->cSegs;
433}
434
435
436/** @copydoc RTDBGMODVTDBG::pfnSegmentAdd */
437static DECLCALLBACK(int) rtDbgModContainer_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
438 uint32_t fFlags, PRTDBGSEGIDX piSeg)
439{
440 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
441
442 /*
443 * Input validation (the bits the caller cannot do).
444 */
445 /* Overlapping segments are not yet supported. Will use flags to deal with it if it becomes necessary. */
446 RTUINTPTR uRvaLast = uRva + RT_MAX(cb, 1) - 1;
447 RTUINTPTR uRvaLastMax = uRvaLast;
448 RTDBGSEGIDX iSeg = pThis->cSegs;
449 while (iSeg-- > 0)
450 {
451 RTUINTPTR uCurRva = pThis->paSegs[iSeg].off;
452 RTUINTPTR uCurRvaLast = uCurRva + RT_MAX(pThis->paSegs[iSeg].cb, 1) - 1;
453 if ( uRva <= uCurRvaLast
454 && uRvaLast >= uCurRva)
455 AssertMsgFailedReturn(("uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\";\n"
456 "uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\" iSeg=%#x\n",
457 uRva, uRvaLast, cb, pszName,
458 uCurRva, uCurRvaLast, pThis->paSegs[iSeg].cb, pThis->paSegs[iSeg].pszName, iSeg),
459 VERR_DBG_SEGMENT_INDEX_CONFLICT);
460 if (uRvaLastMax < uCurRvaLast)
461 uRvaLastMax = uCurRvaLast;
462 }
463 /* Strict ordered segment addition at the moment. */
464 iSeg = pThis->cSegs;
465 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg == iSeg,
466 ("iSeg=%#x *piSeg=%#x\n", iSeg, *piSeg),
467 VERR_DBG_INVALID_SEGMENT_INDEX);
468
469 /*
470 * Add an entry to the segment table, extending it if necessary.
471 */
472 if (!(iSeg % 8))
473 {
474 void *pvSegs = RTMemRealloc(pThis->paSegs, sizeof(RTDBGMODCTNSEGMENT) * (iSeg + 8));
475 if (!pvSegs)
476 return VERR_NO_MEMORY;
477 pThis->paSegs = (PRTDBGMODCTNSEGMENT)pvSegs;
478 }
479
480 pThis->paSegs[iSeg].SymAddrTree = NULL;
481 pThis->paSegs[iSeg].LineAddrTree = NULL;
482 pThis->paSegs[iSeg].off = uRva;
483 pThis->paSegs[iSeg].cb = cb;
484 pThis->paSegs[iSeg].fFlags = fFlags;
485 pThis->paSegs[iSeg].pszName = RTStrCacheEnterN(g_hDbgModStrCache, pszName, cchName);
486 if (pThis->paSegs[iSeg].pszName)
487 {
488 if (piSeg)
489 *piSeg = iSeg;
490 pThis->cSegs++;
491 pThis->cb = uRvaLastMax + 1;
492 if (!pThis->cb)
493 pThis->cb = RTUINTPTR_MAX;
494 return VINF_SUCCESS;
495 }
496 return VERR_NO_MEMORY;
497}
498
499
500/** @copydoc RTDBGMODVTDBG::pfnRvaToSegOff */
501static DECLCALLBACK(RTUINTPTR) rtDbgModContainer_ImageSize(PRTDBGMODINT pMod)
502{
503 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
504 return pThis->cb;
505}
506
507
508/** @copydoc RTDBGMODVTDBG::pfnRvaToSegOff */
509static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
510{
511 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
512 PCRTDBGMODCTNSEGMENT paSeg = pThis->paSegs;
513 uint32_t const cSegs = pThis->cSegs;
514 if (cSegs <= 7)
515 {
516 /*
517 * Linear search.
518 */
519 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
520 {
521 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
522 if (offSeg < paSeg[iSeg].cb)
523 {
524 if (poffSeg)
525 *poffSeg = offSeg;
526 return iSeg;
527 }
528 }
529 }
530 else
531 {
532 /*
533 * Binary search.
534 */
535 uint32_t iFirst = 0;
536 uint32_t iLast = cSegs - 1;
537 for (;;)
538 {
539 uint32_t iSeg = iFirst + (iFirst - iLast) / 2;
540 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
541 if (offSeg < paSeg[iSeg].cb)
542 {
543 if (poffSeg)
544 *poffSeg = offSeg;
545 return iSeg;
546 }
547
548 /* advance */
549 if (uRva < paSeg[iSeg].off)
550 {
551 /* between iFirst and iSeg. */
552 if (iSeg == iFirst)
553 break;
554 iLast = iSeg - 1;
555 }
556 else
557 {
558 /* between iSeg and iLast. */
559 if (iSeg == iLast)
560 break;
561 iFirst = iSeg + 1;
562 }
563 }
564 }
565
566 /* Invalid. */
567 return NIL_RTDBGSEGIDX;
568}
569
570
571/** Destroy a symbol node. */
572static DECLCALLBACK(int) rtDbgModContainer_DestroyTreeNode(PAVLRUINTPTRNODECORE pNode, void *pvUser)
573{
574 PRTDBGMODCTNSYMBOL pSym = RT_FROM_MEMBER(pNode, RTDBGMODCTNSYMBOL, AddrCore);
575 RTStrCacheRelease(g_hDbgModStrCache, pSym->NameCore.pszString);
576 pSym->NameCore.pszString = NULL;
577 RTMemFree(pSym);
578 return 0;
579}
580
581
582/** @copydoc RTDBGMODVTDBG::pfnClose */
583static DECLCALLBACK(int) rtDbgModContainer_Close(PRTDBGMODINT pMod)
584{
585 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
586
587 /*
588 * Destroy the symbols and instance data.
589 */
590 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
591 {
592 RTAvlrUIntPtrDestroy(&pThis->paSegs[iSeg].SymAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
593 RTStrCacheRelease(g_hDbgModStrCache, pThis->paSegs[iSeg].pszName);
594 pThis->paSegs[iSeg].pszName = NULL;
595 }
596 RTAvlrUIntPtrDestroy(&pThis->AbsAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
597 pThis->Names = NULL;
598
599 RTMemFree(pThis->paSegs);
600 pThis->paSegs = NULL;
601 RTMemFree(pThis);
602
603 return VINF_SUCCESS;
604}
605
606
607/** @copydoc RTDBGMODVTDBG::pfnTryOpen */
608static DECLCALLBACK(int) rtDbgModContainer_TryOpen(PRTDBGMODINT pMod)
609{
610 return VERR_INTERNAL_ERROR_5;
611}
612
613
614
615/** Virtual function table for the debug info container. */
616static RTDBGMODVTDBG const g_rtDbgModVtDbgContainer =
617{
618 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
619 /*.fSupports = */ 0, /* (Don't call my TryOpen, please.) */
620 /*.pszName = */ "container",
621 /*.pfnTryOpen = */ rtDbgModContainer_TryOpen,
622 /*.pfnClose = */ rtDbgModContainer_Close,
623
624 /*.pfnRvaToSegOff = */ rtDbgModContainer_RvaToSegOff,
625 /*.pfnImageSize = */ rtDbgModContainer_ImageSize,
626
627 /*.pfnSegmentAdd = */ rtDbgModContainer_SegmentAdd,
628 /*.pfnSegmentCount = */ rtDbgModContainer_SegmentCount,
629 /*.pfnSegmentByIndex = */ rtDbgModContainer_SegmentByIndex,
630
631 /*.pfnSymbolAdd = */ rtDbgModContainer_SymbolAdd,
632 /*.pfnSymbolCount = */ rtDbgModContainer_SymbolCount,
633 /*.pfnSymbolByOrdinal = */ rtDbgModContainer_SymbolByOrdinal,
634 /*.pfnSymbolByName = */ rtDbgModContainer_SymbolByName,
635 /*.pfnSymbolByAddr = */ rtDbgModContainer_SymbolByAddr,
636
637 /*.pfnLineAdd = */ rtDbgModContainer_LineAdd,
638 /*.pfnLineCount = */ rtDbgModContainer_LineCount,
639 /*.pfnLineByOrdinal = */ rtDbgModContainer_LineByOrdinal,
640 /*.pfnLineByAddr = */ rtDbgModContainer_LineByAddr,
641
642 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
643};
644
645
646
647/**
648 * Creates a generic debug info container and associates it with the module.
649 *
650 * @returns IPRT status code.
651 * @param pMod The module instance.
652 * @param cb The module size.
653 */
654int rtDbgModContainerCreate(PRTDBGMODINT pMod, RTUINTPTR cb)
655{
656 PRTDBGMODCTN pThis = (PRTDBGMODCTN)RTMemAlloc(sizeof(*pThis));
657 if (!pThis)
658 return VERR_NO_MEMORY;
659
660 pThis->Names = NULL;
661 pThis->AbsAddrTree = NULL;
662 pThis->SymbolOrdinalTree = NULL;
663 pThis->LineOrdinalTree = NULL;
664 pThis->paSegs = NULL;
665 pThis->cSegs = 0;
666 pThis->cb = cb; /** @todo the module size stuff doesn't quite make sense yet. Need to look at segments first, I guess. */
667 pThis->iNextSymbolOrdinal = 0;
668 pThis->iNextLineOrdinal = 0;
669
670 pMod->pDbgVt = &g_rtDbgModVtDbgContainer;
671 pMod->pvDbgPriv = pThis;
672 return VINF_SUCCESS;
673}
674
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