VirtualBox

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

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

IPRT: More RTDbgMod code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 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 pSymInfo)
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, pSymInfo);
294}
295
296
297/** @copydoc RTDBGMODVTDBG::pfnSymbolByName */
298static DECLCALLBACK(int) rtDbgModContainer_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol, PRTDBGSYMBOL pSymInfo)
299{
300 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
301 NOREF(cchSymbol);
302
303 /*
304 * Look it up in the name space.
305 */
306 PRTSTRSPACECORE pStrCore = RTStrSpaceGet(&pThis->Names, pszSymbol);
307 if (!pStrCore)
308 return VERR_SYMBOL_NOT_FOUND;
309 PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pStrCore, RTDBGMODCTNSYMBOL const, NameCore);
310 return rtDbgModContainerReturnSymbol(pMySym, pSymInfo);
311}
312
313
314/** @copydoc RTDBGMODVTDBG::pfnSymbolByOrdinal */
315static DECLCALLBACK(int) rtDbgModContainer_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
316{
317 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
318
319 /*
320 * Look it up in the ordinal tree.
321 */
322 if (iOrdinal >= pThis->iNextSymbolOrdinal)
323 return pThis->iNextSymbolOrdinal
324 ? VERR_DBG_NO_SYMBOLS
325 : VERR_SYMBOL_NOT_FOUND;
326 PAVLU32NODECORE pAvlCore = RTAvlU32Get(&pThis->SymbolOrdinalTree, iOrdinal);
327 AssertReturn(pAvlCore, VERR_SYMBOL_NOT_FOUND);
328 PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pAvlCore, RTDBGMODCTNSYMBOL const, OrdinalCore);
329 return rtDbgModContainerReturnSymbol(pMySym, pSymInfo);
330}
331
332
333/** @copydoc RTDBGMODVTDBG::pfnSymbolCount */
334static DECLCALLBACK(uint32_t) rtDbgModContainer_SymbolCount(PRTDBGMODINT pMod)
335{
336 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
337
338 /* Note! The ordinal numbers are 0-based. */
339 return pThis->iNextSymbolOrdinal;
340}
341
342
343/** @copydoc RTDBGMODVTDBG::pfnSymbolAdd */
344static DECLCALLBACK(int) rtDbgModContainer_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
345 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
346 uint32_t *piOrdinal)
347{
348 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
349
350 /*
351 * Address validation. The other arguments have already been validated.
352 */
353 AssertMsgReturn( iSeg == RTDBGSEGIDX_ABS
354 || iSeg < pThis->cSegs,
355 ("iSeg=%#x cSegs=%#x\n", pThis->cSegs),
356 VERR_DBG_INVALID_SEGMENT_INDEX);
357 AssertMsgReturn( iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
358 || pThis->paSegs[iSeg].cb <= off + cb,
359 ("off=%RTptr cb=%RTptr cbSeg=%RTptr\n", off, cb, pThis->paSegs[iSeg].cb),
360 VERR_DBG_INVALID_SEGMENT_OFFSET);
361
362 /*
363 * Create a new entry.
364 */
365 PRTDBGMODCTNSYMBOL pSymbol = (PRTDBGMODCTNSYMBOL)RTMemAllocZ(sizeof(*pSymbol));
366 if (!pSymbol)
367 return VERR_NO_MEMORY;
368
369 pSymbol->AddrCore.Key = off;
370 pSymbol->AddrCore.KeyLast = off + RT_MAX(cb, 1);
371 pSymbol->OrdinalCore.Key = pThis->iNextSymbolOrdinal;
372 pSymbol->iSeg = iSeg;
373 pSymbol->cb = cb;
374 pSymbol->fFlags = fFlags;
375 pSymbol->NameCore.pszString = RTStrCacheEnter(g_hDbgModStrCache, pszSymbol);
376 int rc;
377 if (pSymbol->NameCore.pszString)
378 {
379 if (RTStrSpaceInsert(&pThis->Names, &pSymbol->NameCore))
380 {
381 PAVLRUINTPTRTREE pAddrTree = iSeg == RTDBGSEGIDX_ABS
382 ? &pThis->AbsAddrTree
383 : &pThis->paSegs[iSeg].SymAddrTree;
384 if (RTAvlrUIntPtrInsert(pAddrTree, &pSymbol->AddrCore))
385 {
386 if (RTAvlU32Insert(&pThis->LineOrdinalTree, &pSymbol->OrdinalCore))
387 {
388 if (piOrdinal)
389 *piOrdinal = pThis->iNextSymbolOrdinal;
390 pThis->iNextSymbolOrdinal++;
391 return VINF_SUCCESS;
392 }
393
394 /* bail out */
395 rc = VERR_INTERNAL_ERROR_5;
396 RTAvlrUIntPtrRemove(pAddrTree, pSymbol->AddrCore.Key);
397 }
398 else
399 rc = VERR_DBG_ADDRESS_CONFLICT;
400 RTStrSpaceRemove(&pThis->Names, pSymbol->NameCore.pszString);
401 }
402 else
403 rc = VERR_DBG_DUPLICATE_SYMBOL;
404 RTStrCacheRelease(g_hDbgModStrCache, pSymbol->NameCore.pszString);
405 }
406 else
407 rc = VERR_NO_MEMORY;
408 RTMemFree(pSymbol);
409 return rc;
410}
411
412
413/** @copydoc RTDBGMODVTDBG::pfnSegmentByIndex */
414static DECLCALLBACK(int) rtDbgModContainer_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
415{
416 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
417 if (iSeg >= pThis->cSegs)
418 return VERR_DBG_INVALID_SEGMENT_INDEX;
419 pSegInfo->Address = RTUINTPTR_MAX;
420 pSegInfo->uRva = pThis->paSegs[iSeg].off;
421 pSegInfo->cb = pThis->paSegs[iSeg].cb;
422 pSegInfo->fFlags = pThis->paSegs[iSeg].fFlags;
423 pSegInfo->iSeg = iSeg;
424 strcpy(pSegInfo->szName, pThis->paSegs[iSeg].pszName);
425 return VINF_SUCCESS;
426}
427
428
429/** @copydoc RTDBGMODVTDBG::pfnSegmentCount */
430static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_SegmentCount(PRTDBGMODINT pMod)
431{
432 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
433 return pThis->cSegs;
434}
435
436
437/** @copydoc RTDBGMODVTDBG::pfnSegmentAdd */
438static DECLCALLBACK(int) rtDbgModContainer_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
439 uint32_t fFlags, PRTDBGSEGIDX piSeg)
440{
441 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
442
443 /*
444 * Input validation (the bits the caller cannot do).
445 */
446 /* Overlapping segments are not yet supported. Will use flags to deal with it if it becomes necessary. */
447 RTUINTPTR uRvaLast = uRva + RT_MAX(cb, 1) - 1;
448 RTUINTPTR uRvaLastMax = uRvaLast;
449 RTDBGSEGIDX iSeg = pThis->cSegs;
450 while (iSeg-- > 0)
451 {
452 RTUINTPTR uCurRva = pThis->paSegs[iSeg].off;
453 RTUINTPTR uCurRvaLast = uCurRva + RT_MAX(pThis->paSegs[iSeg].cb, 1) - 1;
454 if ( uRva <= uCurRvaLast
455 && uRvaLast >= uCurRva)
456 AssertMsgFailedReturn(("uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\";\n"
457 "uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\" iSeg=%#x\n",
458 uRva, uRvaLast, cb, pszName,
459 uCurRva, uCurRvaLast, pThis->paSegs[iSeg].cb, pThis->paSegs[iSeg].pszName, iSeg),
460 VERR_DBG_SEGMENT_INDEX_CONFLICT);
461 if (uRvaLastMax < uCurRvaLast)
462 uRvaLastMax = uCurRvaLast;
463 }
464 /* Strict ordered segment addition at the moment. */
465 iSeg = pThis->cSegs;
466 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg == iSeg,
467 ("iSeg=%#x *piSeg=%#x\n", iSeg, *piSeg),
468 VERR_DBG_INVALID_SEGMENT_INDEX);
469
470 /*
471 * Add an entry to the segment table, extending it if necessary.
472 */
473 if (!(iSeg % 8))
474 {
475 void *pvSegs = RTMemRealloc(pThis->paSegs, sizeof(RTDBGMODCTNSEGMENT) * (iSeg + 8));
476 if (!pvSegs)
477 return VERR_NO_MEMORY;
478 pThis->paSegs = (PRTDBGMODCTNSEGMENT)pvSegs;
479 }
480
481 pThis->paSegs[iSeg].SymAddrTree = NULL;
482 pThis->paSegs[iSeg].LineAddrTree = NULL;
483 pThis->paSegs[iSeg].off = uRva;
484 pThis->paSegs[iSeg].cb = cb;
485 pThis->paSegs[iSeg].fFlags = fFlags;
486 pThis->paSegs[iSeg].pszName = RTStrCacheEnterN(g_hDbgModStrCache, pszName, cchName);
487 if (pThis->paSegs[iSeg].pszName)
488 {
489 if (piSeg)
490 *piSeg = iSeg;
491 pThis->cSegs++;
492 pThis->cb = uRvaLastMax + 1;
493 if (!pThis->cb)
494 pThis->cb = RTUINTPTR_MAX;
495 return VINF_SUCCESS;
496 }
497 return VERR_NO_MEMORY;
498}
499
500
501/** @copydoc RTDBGMODVTDBG::pfnRvaToSegOff */
502static DECLCALLBACK(RTUINTPTR) rtDbgModContainer_ImageSize(PRTDBGMODINT pMod)
503{
504 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
505 return pThis->cb;
506}
507
508
509/** @copydoc RTDBGMODVTDBG::pfnRvaToSegOff */
510static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
511{
512 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
513 PCRTDBGMODCTNSEGMENT paSeg = pThis->paSegs;
514 uint32_t const cSegs = pThis->cSegs;
515 if (cSegs <= 7)
516 {
517 /*
518 * Linear search.
519 */
520 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
521 {
522 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
523 if (offSeg < paSeg[iSeg].cb)
524 {
525 if (poffSeg)
526 *poffSeg = offSeg;
527 return iSeg;
528 }
529 }
530 }
531 else
532 {
533 /*
534 * Binary search.
535 */
536 uint32_t iFirst = 0;
537 uint32_t iLast = cSegs - 1;
538 for (;;)
539 {
540 uint32_t iSeg = iFirst + (iFirst - iLast) / 2;
541 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
542 if (offSeg < paSeg[iSeg].cb)
543 {
544 if (poffSeg)
545 *poffSeg = offSeg;
546 return iSeg;
547 }
548
549 /* advance */
550 if (uRva < paSeg[iSeg].off)
551 {
552 /* between iFirst and iSeg. */
553 if (iSeg == iFirst)
554 break;
555 iLast = iSeg - 1;
556 }
557 else
558 {
559 /* between iSeg and iLast. */
560 if (iSeg == iLast)
561 break;
562 iFirst = iSeg + 1;
563 }
564 }
565 }
566
567 /* Invalid. */
568 return NIL_RTDBGSEGIDX;
569}
570
571
572/** Destroy a symbol node. */
573static DECLCALLBACK(int) rtDbgModContainer_DestroyTreeNode(PAVLRUINTPTRNODECORE pNode, void *pvUser)
574{
575 PRTDBGMODCTNSYMBOL pSym = RT_FROM_MEMBER(pNode, RTDBGMODCTNSYMBOL, AddrCore);
576 RTStrCacheRelease(g_hDbgModStrCache, pSym->NameCore.pszString);
577 pSym->NameCore.pszString = NULL;
578 RTMemFree(pSym);
579 return 0;
580}
581
582
583/** @copydoc RTDBGMODVTDBG::pfnClose */
584static DECLCALLBACK(int) rtDbgModContainer_Close(PRTDBGMODINT pMod)
585{
586 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
587
588 /*
589 * Destroy the symbols and instance data.
590 */
591 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
592 {
593 RTAvlrUIntPtrDestroy(&pThis->paSegs[iSeg].SymAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
594 RTStrCacheRelease(g_hDbgModStrCache, pThis->paSegs[iSeg].pszName);
595 pThis->paSegs[iSeg].pszName = NULL;
596 }
597
598 RTAvlrUIntPtrDestroy(&pThis->AbsAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
599 pThis->Names = NULL;
600
601 RTMemFree(pThis->paSegs);
602 pThis->paSegs = NULL;
603
604 RTMemFree(pThis);
605
606 return VINF_SUCCESS;
607}
608
609
610/** @copydoc RTDBGMODVTDBG::pfnTryOpen */
611static DECLCALLBACK(int) rtDbgModContainer_TryOpen(PRTDBGMODINT pMod)
612{
613 return VERR_INTERNAL_ERROR_5;
614}
615
616
617
618/** Virtual function table for the debug info container. */
619static RTDBGMODVTDBG const g_rtDbgModVtDbgContainer =
620{
621 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
622 /*.fSupports = */ 0, /* (Don't call my TryOpen, please.) */
623 /*.pszName = */ "container",
624 /*.pfnTryOpen = */ rtDbgModContainer_TryOpen,
625 /*.pfnClose = */ rtDbgModContainer_Close,
626
627 /*.pfnRvaToSegOff = */ rtDbgModContainer_RvaToSegOff,
628 /*.pfnImageSize = */ rtDbgModContainer_ImageSize,
629
630 /*.pfnSegmentAdd = */ rtDbgModContainer_SegmentAdd,
631 /*.pfnSegmentCount = */ rtDbgModContainer_SegmentCount,
632 /*.pfnSegmentByIndex = */ rtDbgModContainer_SegmentByIndex,
633
634 /*.pfnSymbolAdd = */ rtDbgModContainer_SymbolAdd,
635 /*.pfnSymbolCount = */ rtDbgModContainer_SymbolCount,
636 /*.pfnSymbolByOrdinal = */ rtDbgModContainer_SymbolByOrdinal,
637 /*.pfnSymbolByName = */ rtDbgModContainer_SymbolByName,
638 /*.pfnSymbolByAddr = */ rtDbgModContainer_SymbolByAddr,
639
640 /*.pfnLineAdd = */ rtDbgModContainer_LineAdd,
641 /*.pfnLineCount = */ rtDbgModContainer_LineCount,
642 /*.pfnLineByOrdinal = */ rtDbgModContainer_LineByOrdinal,
643 /*.pfnLineByAddr = */ rtDbgModContainer_LineByAddr,
644
645 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
646};
647
648
649
650/**
651 * Creates a generic debug info container and associates it with the module.
652 *
653 * @returns IPRT status code.
654 * @param pMod The module instance.
655 * @param cbSeg The size of the initial segment. 0 if segments are to be
656 * created manually later on.
657 */
658int rtDbgModContainerCreate(PRTDBGMODINT pMod, RTUINTPTR cbSeg)
659{
660 PRTDBGMODCTN pThis = (PRTDBGMODCTN)RTMemAlloc(sizeof(*pThis));
661 if (!pThis)
662 return VERR_NO_MEMORY;
663
664 pThis->Names = NULL;
665 pThis->AbsAddrTree = NULL;
666 pThis->SymbolOrdinalTree = NULL;
667 pThis->LineOrdinalTree = NULL;
668 pThis->paSegs = NULL;
669 pThis->cSegs = 0;
670 pThis->cb = 0;
671 pThis->iNextSymbolOrdinal = 0;
672 pThis->iNextLineOrdinal = 0;
673
674 pMod->pDbgVt = &g_rtDbgModVtDbgContainer;
675 pMod->pvDbgPriv = pThis;
676
677 /*
678 * Add the initial segment.
679 */
680 if (cbSeg)
681 {
682 int rc = rtDbgModContainer_SegmentAdd(pMod, 0, cbSeg, "default", sizeof("default") - 1, 0, NULL);
683 if (RT_FAILURE(rc))
684 {
685 RTMemFree(pThis);
686 pMod->pDbgVt = NULL;
687 pMod->pvDbgPriv = NULL;
688 return rc;
689 }
690 }
691
692 return VINF_SUCCESS;
693}
694
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