VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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