VirtualBox

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

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

IPRT: Dwarf and ELF fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.2 KB
Line 
1/* $Id: dbgmodcontainer.cpp 46149 2013-05-17 17:21:23Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Container.
4 */
5
6/*
7 * Copyright (C) 2009-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#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, uint32_t fFlags,
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 fFlags == RTDBGSYMADDR_FLAGS_GREATER_OR_EQUAL /*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 <= 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 /* Be a little relaxed wrt to the symbol size. */
390 int rc = VINF_SUCCESS;
391 if (off + cb > pThis->paSegs[iSeg].cb)
392 {
393 cb = pThis->paSegs[iSeg].cb - off;
394 rc = VINF_DBG_ADJUSTED_SYM_SIZE;
395 }
396
397 /*
398 * Create a new entry.
399 */
400 PRTDBGMODCTNSYMBOL pSymbol = (PRTDBGMODCTNSYMBOL)RTMemAllocZ(sizeof(*pSymbol));
401 if (!pSymbol)
402 return VERR_NO_MEMORY;
403
404 pSymbol->AddrCore.Key = off;
405 pSymbol->AddrCore.KeyLast = off + (cb ? cb - 1 : 0);
406 pSymbol->OrdinalCore.Key = pThis->iNextSymbolOrdinal;
407 pSymbol->iSeg = iSeg;
408 pSymbol->cb = cb;
409 pSymbol->fFlags = fFlags;
410 pSymbol->NameCore.pszString = RTStrCacheEnterN(g_hDbgModStrCache, pszSymbol, cchSymbol);
411 if (pSymbol->NameCore.pszString)
412 {
413 if (RTStrSpaceInsert(&pThis->Names, &pSymbol->NameCore))
414 {
415 PAVLRUINTPTRTREE pAddrTree = iSeg == RTDBGSEGIDX_ABS
416 ? &pThis->AbsAddrTree
417 : &pThis->paSegs[iSeg].SymAddrTree;
418 if (RTAvlrUIntPtrInsert(pAddrTree, &pSymbol->AddrCore))
419 {
420 if (RTAvlU32Insert(&pThis->SymbolOrdinalTree, &pSymbol->OrdinalCore))
421 {
422 if (piOrdinal)
423 *piOrdinal = pThis->iNextSymbolOrdinal;
424 pThis->iNextSymbolOrdinal++;
425 return rc;
426 }
427
428 /* bail out */
429 rc = VERR_INTERNAL_ERROR_5;
430 RTAvlrUIntPtrRemove(pAddrTree, pSymbol->AddrCore.Key);
431 }
432 else
433 rc = VERR_DBG_ADDRESS_CONFLICT;
434 RTStrSpaceRemove(&pThis->Names, pSymbol->NameCore.pszString);
435 }
436 else
437 rc = VERR_DBG_DUPLICATE_SYMBOL;
438 RTStrCacheRelease(g_hDbgModStrCache, pSymbol->NameCore.pszString);
439 }
440 else
441 rc = VERR_NO_MEMORY;
442 RTMemFree(pSymbol);
443 return rc;
444}
445
446
447/** @copydoc RTDBGMODVTDBG::pfnSegmentByIndex */
448static DECLCALLBACK(int) rtDbgModContainer_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
449{
450 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
451 if (iSeg >= pThis->cSegs)
452 return VERR_DBG_INVALID_SEGMENT_INDEX;
453 pSegInfo->Address = RTUINTPTR_MAX;
454 pSegInfo->uRva = pThis->paSegs[iSeg].off;
455 pSegInfo->cb = pThis->paSegs[iSeg].cb;
456 pSegInfo->fFlags = pThis->paSegs[iSeg].fFlags;
457 pSegInfo->iSeg = iSeg;
458 strcpy(pSegInfo->szName, pThis->paSegs[iSeg].pszName);
459 return VINF_SUCCESS;
460}
461
462
463/** @copydoc RTDBGMODVTDBG::pfnSegmentCount */
464static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_SegmentCount(PRTDBGMODINT pMod)
465{
466 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
467 return pThis->cSegs;
468}
469
470
471/** @copydoc RTDBGMODVTDBG::pfnSegmentAdd */
472static DECLCALLBACK(int) rtDbgModContainer_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
473 uint32_t fFlags, PRTDBGSEGIDX piSeg)
474{
475 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
476
477 /*
478 * Input validation (the bits the caller cannot do).
479 */
480 /* Overlapping segments are not yet supported. Will use flags to deal with it if it becomes necessary. */
481 RTUINTPTR uRvaLast = uRva + RT_MAX(cb, 1) - 1;
482 RTUINTPTR uRvaLastMax = uRvaLast;
483 RTDBGSEGIDX iSeg = pThis->cSegs;
484 while (iSeg-- > 0)
485 {
486 RTUINTPTR uCurRva = pThis->paSegs[iSeg].off;
487 RTUINTPTR uCurRvaLast = uCurRva + RT_MAX(pThis->paSegs[iSeg].cb, 1) - 1;
488 if ( uRva <= uCurRvaLast
489 && uRvaLast >= uCurRva
490 && ( /* HACK ALERT! Allow empty segments to share space (bios/watcom, elf). */
491 (cb != 0 && pThis->paSegs[iSeg].cb != 0)
492 || ( cb == 0
493 && uRva != uCurRva
494 && uRva != uCurRvaLast)
495 || ( pThis->paSegs[iSeg].cb == 0
496 && uCurRva != uRva
497 && uCurRva != uRvaLast)
498 )
499 )
500 AssertMsgFailedReturn(("uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\";\n"
501 "uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\" iSeg=%#x\n",
502 uRva, uRvaLast, cb, pszName,
503 uCurRva, uCurRvaLast, pThis->paSegs[iSeg].cb, pThis->paSegs[iSeg].pszName, iSeg),
504 VERR_DBG_SEGMENT_INDEX_CONFLICT);
505 if (uRvaLastMax < uCurRvaLast)
506 uRvaLastMax = uCurRvaLast;
507 }
508 /* Strict ordered segment addition at the moment. */
509 iSeg = pThis->cSegs;
510 AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg == iSeg,
511 ("iSeg=%#x *piSeg=%#x\n", iSeg, *piSeg),
512 VERR_DBG_INVALID_SEGMENT_INDEX);
513
514 /*
515 * Add an entry to the segment table, extending it if necessary.
516 */
517 if (!(iSeg % 8))
518 {
519 void *pvSegs = RTMemRealloc(pThis->paSegs, sizeof(RTDBGMODCTNSEGMENT) * (iSeg + 8));
520 if (!pvSegs)
521 return VERR_NO_MEMORY;
522 pThis->paSegs = (PRTDBGMODCTNSEGMENT)pvSegs;
523 }
524
525 pThis->paSegs[iSeg].SymAddrTree = NULL;
526 pThis->paSegs[iSeg].LineAddrTree = NULL;
527 pThis->paSegs[iSeg].off = uRva;
528 pThis->paSegs[iSeg].cb = cb;
529 pThis->paSegs[iSeg].fFlags = fFlags;
530 pThis->paSegs[iSeg].pszName = RTStrCacheEnterN(g_hDbgModStrCache, pszName, cchName);
531 if (pThis->paSegs[iSeg].pszName)
532 {
533 if (piSeg)
534 *piSeg = iSeg;
535 pThis->cSegs++;
536 pThis->cb = uRvaLastMax + 1;
537 if (!pThis->cb)
538 pThis->cb = RTUINTPTR_MAX;
539 return VINF_SUCCESS;
540 }
541 return VERR_NO_MEMORY;
542}
543
544
545/** @copydoc RTDBGMODVTDBG::pfnImageSize */
546static DECLCALLBACK(RTUINTPTR) rtDbgModContainer_ImageSize(PRTDBGMODINT pMod)
547{
548 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
549 return pThis->cb;
550}
551
552
553/** @copydoc RTDBGMODVTDBG::pfnRvaToSegOff */
554static DECLCALLBACK(RTDBGSEGIDX) rtDbgModContainer_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
555{
556 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
557 PCRTDBGMODCTNSEGMENT paSeg = pThis->paSegs;
558 uint32_t const cSegs = pThis->cSegs;
559 if (cSegs <= 7)
560 {
561 /*
562 * Linear search.
563 */
564 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
565 {
566 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
567 if (offSeg < paSeg[iSeg].cb)
568 {
569 if (poffSeg)
570 *poffSeg = offSeg;
571 return iSeg;
572 }
573 }
574 }
575 else
576 {
577 /*
578 * Binary search.
579 */
580 uint32_t iFirst = 0;
581 uint32_t iLast = cSegs - 1;
582 for (;;)
583 {
584 uint32_t iSeg = iFirst + (iLast - iFirst) / 2;
585 RTUINTPTR offSeg = uRva - paSeg[iSeg].off;
586 if (offSeg < paSeg[iSeg].cb)
587 {
588#if 0 /* Enable if we change the above test. */
589 if (offSeg == 0 && paSeg[iSeg].cb == 0)
590 while ( iSeg > 0
591 && paSeg[iSeg - 1].cb == 0
592 && paSeg[iSeg - 1].off == uRva)
593 iSeg--;
594#endif
595
596 if (poffSeg)
597 *poffSeg = offSeg;
598 return iSeg;
599 }
600
601 /* advance */
602 if (uRva < paSeg[iSeg].off)
603 {
604 /* between iFirst and iSeg. */
605 if (iSeg == iFirst)
606 break;
607 iLast = iSeg - 1;
608 }
609 else
610 {
611 /* between iSeg and iLast. paSeg[iSeg].cb == 0 ends up here too. */
612 if (iSeg == iLast)
613 break;
614 iFirst = iSeg + 1;
615 }
616 }
617 }
618
619 /* Invalid. */
620 return NIL_RTDBGSEGIDX;
621}
622
623
624/** Destroy a line number node. */
625static DECLCALLBACK(int) rtDbgModContainer_DestroyTreeLineNode(PAVLU32NODECORE pNode, void *pvUser)
626{
627 PRTDBGMODCTNLINE pLine = RT_FROM_MEMBER(pNode, RTDBGMODCTNLINE, OrdinalCore);
628 RTStrCacheRelease(g_hDbgModStrCache, pLine->pszFile);
629 pLine->pszFile = NULL;
630 RTMemFree(pLine);
631 NOREF(pvUser);
632 return 0;
633}
634
635
636/** Destroy a symbol node. */
637static DECLCALLBACK(int) rtDbgModContainer_DestroyTreeNode(PAVLRUINTPTRNODECORE pNode, void *pvUser)
638{
639 PRTDBGMODCTNSYMBOL pSym = RT_FROM_MEMBER(pNode, RTDBGMODCTNSYMBOL, AddrCore);
640 RTStrCacheRelease(g_hDbgModStrCache, pSym->NameCore.pszString);
641 pSym->NameCore.pszString = NULL;
642 RTMemFree(pSym);
643 NOREF(pvUser);
644 return 0;
645}
646
647
648/** @copydoc RTDBGMODVTDBG::pfnClose */
649static DECLCALLBACK(int) rtDbgModContainer_Close(PRTDBGMODINT pMod)
650{
651 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
652
653 /*
654 * Destroy the symbols and instance data.
655 */
656 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
657 {
658 RTAvlrUIntPtrDestroy(&pThis->paSegs[iSeg].SymAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
659 RTStrCacheRelease(g_hDbgModStrCache, pThis->paSegs[iSeg].pszName);
660 pThis->paSegs[iSeg].pszName = NULL;
661 }
662
663 RTAvlrUIntPtrDestroy(&pThis->AbsAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
664 pThis->Names = NULL;
665
666 RTAvlU32Destroy(&pThis->LineOrdinalTree, rtDbgModContainer_DestroyTreeLineNode, NULL);
667
668 RTMemFree(pThis->paSegs);
669 pThis->paSegs = NULL;
670
671 RTMemFree(pThis);
672
673 return VINF_SUCCESS;
674}
675
676
677/** @copydoc RTDBGMODVTDBG::pfnTryOpen */
678static DECLCALLBACK(int) rtDbgModContainer_TryOpen(PRTDBGMODINT pMod)
679{
680 NOREF(pMod);
681 return VERR_INTERNAL_ERROR_5;
682}
683
684
685
686/** Virtual function table for the debug info container. */
687DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgContainer =
688{
689 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
690 /*.fSupports = */ 0, /* (Don't call my TryOpen, please.) */
691 /*.pszName = */ "container",
692 /*.pfnTryOpen = */ rtDbgModContainer_TryOpen,
693 /*.pfnClose = */ rtDbgModContainer_Close,
694
695 /*.pfnRvaToSegOff = */ rtDbgModContainer_RvaToSegOff,
696 /*.pfnImageSize = */ rtDbgModContainer_ImageSize,
697
698 /*.pfnSegmentAdd = */ rtDbgModContainer_SegmentAdd,
699 /*.pfnSegmentCount = */ rtDbgModContainer_SegmentCount,
700 /*.pfnSegmentByIndex = */ rtDbgModContainer_SegmentByIndex,
701
702 /*.pfnSymbolAdd = */ rtDbgModContainer_SymbolAdd,
703 /*.pfnSymbolCount = */ rtDbgModContainer_SymbolCount,
704 /*.pfnSymbolByOrdinal = */ rtDbgModContainer_SymbolByOrdinal,
705 /*.pfnSymbolByName = */ rtDbgModContainer_SymbolByName,
706 /*.pfnSymbolByAddr = */ rtDbgModContainer_SymbolByAddr,
707
708 /*.pfnLineAdd = */ rtDbgModContainer_LineAdd,
709 /*.pfnLineCount = */ rtDbgModContainer_LineCount,
710 /*.pfnLineByOrdinal = */ rtDbgModContainer_LineByOrdinal,
711 /*.pfnLineByAddr = */ rtDbgModContainer_LineByAddr,
712
713 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
714};
715
716
717
718/**
719 * Special container operation for removing all symbols.
720 *
721 * @returns IPRT status code.
722 * @param pMod The module instance.
723 */
724DECLHIDDEN(int) rtDbgModContainer_SymbolRemoveAll(PRTDBGMODINT pMod)
725{
726 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
727
728 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
729 {
730 RTAvlrUIntPtrDestroy(&pThis->paSegs[iSeg].SymAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
731 Assert(pThis->paSegs[iSeg].SymAddrTree == NULL);
732 }
733
734 RTAvlrUIntPtrDestroy(&pThis->AbsAddrTree, rtDbgModContainer_DestroyTreeNode, NULL);
735 Assert(pThis->AbsAddrTree == NULL);
736
737 pThis->Names = NULL;
738 pThis->iNextSymbolOrdinal = 0;
739
740 return VINF_SUCCESS;
741}
742
743
744/**
745 * Special container operation for removing all line numbers.
746 *
747 * @returns IPRT status code.
748 * @param pMod The module instance.
749 */
750DECLHIDDEN(int) rtDbgModContainer_LineRemoveAll(PRTDBGMODINT pMod)
751{
752 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
753
754 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
755 pThis->paSegs[iSeg].LineAddrTree = NULL;
756
757 RTAvlU32Destroy(&pThis->LineOrdinalTree, rtDbgModContainer_DestroyTreeLineNode, NULL);
758 Assert(pThis->LineOrdinalTree == NULL);
759
760 pThis->iNextLineOrdinal = 0;
761
762 return VINF_SUCCESS;
763}
764
765
766/**
767 * Special container operation for removing everything.
768 *
769 * @returns IPRT status code.
770 * @param pMod The module instance.
771 */
772DECLHIDDEN(int) rtDbgModContainer_RemoveAll(PRTDBGMODINT pMod)
773{
774 PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;
775
776 rtDbgModContainer_LineRemoveAll(pMod);
777 rtDbgModContainer_SymbolRemoveAll(pMod);
778
779 for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++)
780 {
781 RTStrCacheRelease(g_hDbgModStrCache, pThis->paSegs[iSeg].pszName);
782 pThis->paSegs[iSeg].pszName = NULL;
783 }
784
785 pThis->cSegs = 0;
786 pThis->cb = 0;
787
788 return VINF_SUCCESS;
789}
790
791
792/**
793 * Creates a generic debug info container and associates it with the module.
794 *
795 * @returns IPRT status code.
796 * @param pMod The module instance.
797 * @param cbSeg The size of the initial segment. 0 if segments are to be
798 * created manually later on.
799 */
800int rtDbgModContainerCreate(PRTDBGMODINT pMod, RTUINTPTR cbSeg)
801{
802 PRTDBGMODCTN pThis = (PRTDBGMODCTN)RTMemAlloc(sizeof(*pThis));
803 if (!pThis)
804 return VERR_NO_MEMORY;
805
806 pThis->Names = NULL;
807 pThis->AbsAddrTree = NULL;
808 pThis->SymbolOrdinalTree = NULL;
809 pThis->LineOrdinalTree = NULL;
810 pThis->paSegs = NULL;
811 pThis->cSegs = 0;
812 pThis->cb = 0;
813 pThis->iNextSymbolOrdinal = 0;
814 pThis->iNextLineOrdinal = 0;
815
816 pMod->pDbgVt = &g_rtDbgModVtDbgContainer;
817 pMod->pvDbgPriv = pThis;
818
819 /*
820 * Add the initial segment.
821 */
822 if (cbSeg)
823 {
824 int rc = rtDbgModContainer_SegmentAdd(pMod, 0, cbSeg, "default", sizeof("default") - 1, 0, NULL);
825 if (RT_FAILURE(rc))
826 {
827 RTMemFree(pThis);
828 pMod->pDbgVt = NULL;
829 pMod->pvDbgPriv = NULL;
830 return rc;
831 }
832 }
833
834 return VINF_SUCCESS;
835}
836
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