VirtualBox

source: kStuff/trunk/kDbg/kDbgModule.cpp@ 54

Last change on this file since 54 was 29, checked in by bird, 15 years ago

Finally got around execute the switch to the MIT license.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.6 KB
Line 
1/* $Id: kDbgModule.cpp 29 2009-07-01 20:30:29Z bird $ */
2/** @file
3 * kDbg - The Debug Info Reader, Module API.
4 */
5
6/*
7 * Copyright (c) 2006-2007 Knut St. Osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include "kDbgInternal.h"
35#include <k/kHlpString.h>
36#include <k/kHlpAlloc.h>
37
38
39/*******************************************************************************
40* Global Variables *
41*******************************************************************************/
42/**
43 * The built-in debug module readers.
44 */
45static PCKDBGMODOPS const g_aBuiltIns[] =
46{
47#if K_OS == K_OS_WINDOWS
48 &g_kDbgModWinDbgHelpOpen,
49#endif
50 &g_kDbgModLdr,
51// &g_kDbgModCv8,
52// &g_kDbgModDwarf,
53// &g_kDbgModHll,
54// &g_kDbgModStabs,
55// &g_kDbgModSym,
56// &g_kDbgModMapILink,
57// &g_kDbgModMapMSLink,
58// &g_kDbgModMapNm,
59// &g_kDbgModMapWLink
60};
61
62/**
63 * The debug module readers registered at runtime.
64 */
65static PKDBGMODOPS g_pHead = NULL;
66
67
68/**
69 * Register a debug module reader with the kDbgModule component.
70 *
71 * Dynamically registered readers are kept in FIFO order, and external
72 * readers will be tried after the builtin ones.
73 *
74 * Like all other kDbg APIs serializing is left to the caller.
75 *
76 * @returns 0 on success.
77 * @returns KERR_INVALID_POINTER if pOps is missing bits.
78 * @returns KERR_INVALID_PARAMETER if pOps is already in the list.
79 * @param pOps The reader method table, kDbg takes owner ship of
80 * this. This must be writeable as the pNext pointer
81 * will be update. It must also stick around for as
82 * long as kDbg is in use.
83 */
84KDBG_DECL(int) kDbgModuleRegisterReader(PKDBGMODOPS pOps)
85{
86 /*
87 * Validate input.
88 */
89 kDbgAssertPtrReturn(pOps, KERR_INVALID_POINTER);
90 kDbgAssertPtrReturn(pOps->pszName, KERR_INVALID_POINTER);
91 kDbgAssertPtrReturn(pOps->pfnOpen, KERR_INVALID_POINTER);
92 kDbgAssertPtrReturn(pOps->pfnClose, KERR_INVALID_POINTER);
93 kDbgAssertPtrReturn(pOps->pfnQuerySymbol, KERR_INVALID_POINTER);
94 kDbgAssertPtrReturn(pOps->pfnQueryLine, KERR_INVALID_POINTER);
95 kDbgAssertPtrReturn(pOps->pszName2, KERR_INVALID_POINTER);
96 if (kHlpStrComp(pOps->pszName, pOps->pszName2))
97 return KERR_INVALID_PARAMETER;
98 kDbgAssertReturn(pOps->pNext == NULL, KERR_INVALID_PARAMETER);
99
100 /*
101 * Link it into the list.
102 */
103 if (!g_pHead)
104 g_pHead = pOps;
105 else
106 {
107 PKDBGMODOPS pPrev = g_pHead;
108 while (pPrev->pNext)
109 pPrev = pPrev->pNext;
110 kDbgAssertReturn(pPrev != pOps, KERR_INVALID_PARAMETER);
111 pPrev->pNext = pOps;
112 }
113 return 0;
114}
115
116
117/**
118 * Deregister a debug module reader previously registered using
119 * the kDbgModuleRegisterReader API.
120 *
121 * Deregistering a reader does not mean that non of its functions
122 * will be called after successful return, it only means that it
123 * will no longer be subjected to new module.
124 *
125 * @returns 0 on success.
126 * @returns KERR_INVALID_POINTER if pOps isn't a valid pointer.
127 * @returns KERR_INVALID_PARAMETER if pOps wasn't registered.
128 * @param pOps The debug module method table to deregister.
129 */
130KDBG_DECL(int) kDbgModuleDeregisterReader(PKDBGMODOPS pOps)
131{
132 /*
133 * Validate the pointer.
134 */
135 kDbgAssertPtrReturn(pOps, KERR_INVALID_POINTER);
136
137 /*
138 * Find it in the list and unlink it.
139 */
140 if (g_pHead == pOps)
141 g_pHead = pOps->pNext;
142 else
143 {
144 PKDBGMODOPS pPrev = g_pHead;
145 while (pPrev && pPrev->pNext != pOps)
146 pPrev = pPrev->pNext;
147 if (!pPrev)
148 return KERR_INVALID_PARAMETER;
149 pPrev->pNext = pOps->pNext;
150 }
151 pOps->pNext = NULL;
152 return 0;
153}
154
155
156
157/**
158 * Worker for the kDbgModuleOpen* APIs.
159 *
160 * This will make sure the reader is buffered. I will also take care of
161 * closing the reader opened by kDbgModuleOpen on failure.
162 *
163 * @returns 0 on success. An appropriate kErrors status code on failure.
164 * @param ppDbgMod Where to store the new debug module reader instance.
165 * @param pRdr The file provider.
166 * @param fCloseRdr Whether pRdr should be close or not. This applies both
167 * to the failure path and to the success path, where it'll
168 * be close when the module is closed by kDbgModuleClose().
169 * @param off The offset into the file where the debug info is supposed
170 * to be found.
171 * This is 0 if the entire file is the subject.
172 * @param cb The size of the debug info part of the file.
173 * This is KFOFF_MAX if the entire file is the subject.
174 * @param pLdrMod An optional kLdrMod association.
175 */
176static int kdbgModuleOpenWorker(PPKDBGMOD ppDbgMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
177{
178 /*
179 * If the reader isn't buffered create a buffered wrapper for it.
180 */
181 int rc;
182 PKRDR pRdrWrapped = NULL;
183 if (!kRdrBufIsBuffered(pRdr))
184 {
185 rc = kRdrBufWrap(&pRdrWrapped, pRdr, fCloseRdr);
186 if (rc)
187 {
188 if (fCloseRdr)
189 kRdrClose(pRdr);
190 return rc;
191 }
192 pRdr = pRdrWrapped;
193 }
194
195 /*
196 * Walk the built-in table and the list of registered readers
197 * and let each of them have a go at the file. Stop and return
198 * on the first one returning successfully.
199 */
200 rc = KDBG_ERR_UNKOWN_FORMAT;
201 for (KSIZE i = 0; i < K_ELEMENTS(g_aBuiltIns); i++)
202 if (g_aBuiltIns[i]->pfnOpen)
203 {
204 int rc2 = g_aBuiltIns[i]->pfnOpen(ppDbgMod, pRdr, fCloseRdr, off, cb, pLdrMod);
205 if (!rc2)
206 return 0;
207 if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
208 rc = rc2;
209 }
210
211 for (PKDBGMODOPS pCur = g_pHead; pCur; pCur = pCur->pNext)
212 if (pCur->pfnOpen)
213 {
214 int rc2 = pCur->pfnOpen(ppDbgMod, pRdr, fCloseRdr, off, cb, pLdrMod);
215 if (!rc2)
216 return 0;
217 if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
218 rc = rc2;
219 }
220
221 if (pRdrWrapped)
222 kRdrClose(pRdrWrapped);
223 else if (fCloseRdr)
224 kRdrClose(pRdr);
225 return rc;
226}
227
228
229/**
230 * Opens a debug module reader for the specified file or file section
231 *
232 * @returns kStuff status code.
233 * @param ppDbgMod Where to store the debug module reader handle.
234 * @param pRdr The file reader.
235 * @param off The offset of the file section. If the entire file, pass 0.
236 * @param cb The size of the file section. If the entire file, pass KFOFF_MAX.
237 * @param pLdrMod Associated kLdr module that the kDbg component can use to
238 * verify and suplement the debug info found in the file specified
239 * by pszFilename. The module will be used by kDbg for as long as
240 * the returned kDbg module remains open.
241 * This is an optional parameter, pass NULL if no kLdr module at hand.
242 */
243KDBG_DECL(int) kDbgModuleOpenFilePart(PPKDBGMOD ppDbgMod, PKRDR pRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
244{
245 /*
246 * Validate input.
247 */
248 kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
249 kDbgAssertPtrReturn(pRdr, KERR_INVALID_POINTER);
250 kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
251 kDbgAssertMsgReturn(off >= 0 && off < KFOFF_MAX, (KFOFF_PRI "\n", off), KERR_INVALID_OFFSET);
252 kDbgAssertMsgReturn(cb >= 0 && cb <= KFOFF_MAX, (KFOFF_PRI "\n", cb), KERR_INVALID_SIZE);
253 kDbgAssertMsgReturn(off + cb > off, ("off=" KFOFF_PRI " cb=" KFOFF_PRI "\n", off, cb), KERR_INVALID_RANGE);
254 *ppDbgMod = NULL;
255
256 /*
257 * Hand it over to the internal worker.
258 */
259 return kdbgModuleOpenWorker(ppDbgMod, pRdr, K_FALSE /* fCloseRdr */, off, cb, pLdrMod);
260}
261
262
263/**
264 * Opens a debug module reader for the specified file.
265 *
266 * @returns kStuff status code.
267 * @param ppDbgMod Where to store the debug module reader handle.
268 * @param pRdr The file reader.
269 * @param pLdrMod Associated kLdr module that the kDbg component can use to
270 * verify and suplement the debug info found in the file specified
271 * by pszFilename. The module will be used by kDbg for as long as
272 * the returned kDbg module remains open.
273 * This is an optional parameter, pass NULL if no kLdr module at hand.
274 */
275KDBG_DECL(int) kDbgModuleOpenFile(PPKDBGMOD ppDbgMod, PKRDR pRdr, struct KLDRMOD *pLdrMod)
276{
277 return kDbgModuleOpenFilePart(ppDbgMod, pRdr, 0, KFOFF_MAX, pLdrMod);
278}
279
280
281/**
282 * Opens the debug info for a specified executable module.
283 *
284 * @returns kStuff status code.
285 * @param ppDbgMod Where to store the debug module handle.
286 * @param pszFilename The name of the file containing debug info and/or which
287 * debug info is wanted.
288 * @param pLdrMod Associated kLdr module that the kDbg component can use to
289 * verify and suplement the debug info found in the file specified
290 * by pszFilename. The module will be used by kDbg for as long as
291 * the returned kDbg module remains open.
292 * This is an optional parameter, pass NULL if no kLdr module at hand.
293 */
294KDBG_DECL(int) kDbgModuleOpen(PPKDBGMOD ppDbgMod, const char *pszFilename, struct KLDRMOD *pLdrMod)
295{
296 /*
297 * Validate input.
298 */
299 kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
300 kDbgAssertPtrReturn(pszFilename, KERR_INVALID_POINTER);
301 kDbgAssertMsgReturn(*pszFilename, ("%p\n", pszFilename), KERR_INVALID_PARAMETER);
302 kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
303 *ppDbgMod = NULL;
304
305 /*
306 * Open the file and see if we can read it.
307 */
308 PKRDR pRdr;
309 int rc = kRdrBufOpen(&pRdr, pszFilename);
310 if (rc)
311 return rc;
312 rc = kdbgModuleOpenWorker(ppDbgMod, pRdr, K_TRUE /* fCloseRdr */, 0, KFOFF_MAX, pLdrMod);
313 return rc;
314}
315
316
317/**
318 * Closes the module.
319 *
320 * @returns IPRT status code.
321 * @param pMod The module handle.
322 */
323KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod)
324{
325 KDBGMOD_VALIDATE(pMod);
326 int rc = pMod->pOps->pfnClose(pMod);
327 if (!rc)
328 {
329 pMod->u32Magic++;
330 kHlpFree(pMod);
331 }
332 return rc;
333}
334
335
336/**
337 * Gets a symbol by segment:offset.
338 * This will be approximated to the nearest symbol if there is no exact match.
339 *
340 * @returns IPRT status code.
341 * @param pMod The module.
342 * @param iSegment The segment this offset is relative to.
343 * The -1 segment is special, it means that the addres is relative to
344 * the image base. The image base is where the first bit of the image
345 * is mapped during load.
346 * @param off The offset into the segment.
347 * @param pSym Where to store the symbol details.
348 */
349KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
350{
351 KDBGMOD_VALIDATE(pMod);
352 kDbgAssertPtrReturn(pSym, KERR_INVALID_POINTER);
353 return pMod->pOps->pfnQuerySymbol(pMod, iSegment, off, pSym);
354}
355
356
357/**
358 * Gets & allocates a symbol by segment:offset.
359 * This will be approximated to the nearest symbol if there is no exact match.
360 *
361 * @returns IPRT status code.
362 * @param pMod The module.
363 * @param iSegment The segment this offset is relative to.
364 * The -1 segment is special, it means that the addres is relative to
365 * the image base. The image base is where the first bit of the image
366 * is mapped during load.
367 * @param off The offset into the segment.
368 * @param ppSym Where to store the pointer to the symbol info.
369 * Free the returned symbol using kDbgSymbolFree().
370 */
371KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym)
372{
373 kDbgAssertPtrReturn(ppSym, KERR_INVALID_POINTER);
374
375 KDBGSYMBOL Sym;
376 int rc = kDbgModuleQuerySymbol(pMod, iSegment, off, &Sym);
377 if (!rc)
378 {
379 *ppSym = kDbgSymbolDup(&Sym);
380 if (!*ppSym)
381 rc = KERR_NO_MEMORY;
382 }
383 else
384 *ppSym = NULL;
385 return rc;
386}
387
388
389/**
390 * Gets a line number entry by segment:offset.
391 * This will be approximated to the nearest line number there is no exact match.
392 *
393 * @returns IPRT status code.
394 * @param pMod The module.
395 * @param iSegment The segment this offset is relative to.
396 * The -1 segment is special, it means that the addres is relative to
397 * the image base. The image base is where the first bit of the image
398 * is mapped during load.
399 * @param off The offset into the segment.
400 * @param pLine Where to store the line number details.
401 */
402KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGLINE pLine)
403{
404 KDBGMOD_VALIDATE(pMod);
405 kDbgAssertPtrReturn(pLine, KERR_INVALID_POINTER);
406 return pMod->pOps->pfnQueryLine(pMod, iSegment, off, pLine);
407}
408
409
410/**
411 * Gets & allocates a line number entry by segment:offset.
412 * This will be approximated to the nearest line number there is no exact match.
413 *
414 * @returns IPRT status code.
415 * @param pMod The module.
416 * @param iSegment The segment this offset is relative to.
417 * The -1 segment is special, it means that the addres is relative to
418 * the image base. The image base is where the first bit of the image
419 * is mapped during load.
420 * @param off The offset into the segment.
421 * @param ppLine Where to store the pointer to the line number info.
422 * Free the returned line number using kDbgLineFree().
423 */
424KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGLINE ppLine)
425{
426 kDbgAssertPtrReturn(ppLine, KERR_INVALID_POINTER);
427
428 KDBGLINE Line;
429 int rc = kDbgModuleQueryLine(pMod, iSegment, off, &Line);
430 if (!rc)
431 {
432 *ppLine = kDbgLineDup(&Line);
433 if (!*ppLine)
434 rc = KERR_NO_MEMORY;
435 }
436 else
437 *ppLine = NULL;
438 return rc;
439}
440
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