VirtualBox

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

Last change on this file since 2 was 2, checked in by bird, 17 years ago

Imported http://svn.netlabs.org/repos/libc/trunk/kStuff, revision 3612.

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