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

Last change on this file since 3541 was 3541, checked in by bird, 18 years ago

errors and stuff.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.0 KB
Line 
1/* $Id: kDbgModule.cpp 3541 2007-08-25 03:46:14Z bird $ */
2/** @file
3 * kDbg - The Debug Info Reader, Module API.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
8 *
9 *
10 * This file is part of kStuff.
11 *
12 * kStuff is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License as published
14 * by the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * kStuff is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with kStuff; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28
29
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include <k/kDbg.h>
34#include <k/kErrors.h>
35#include <string.h>
36#include "kDbgInternal.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 (strcmp(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 * Opens a debug module reader for the specified file or file section
158 *
159 * @returns kStuff status code.
160 * @param ppDbgMod Where to store the debug module reader handle.
161 * @param pFile The file reader.
162 * @param off The offset of the file section. If the entire file, pass 0.
163 * @param cb The size of the file section. If the entire file, pass KFOFF_MAX.
164 * @param pLdrMod Associated kLdr module that the kDbg component can use to
165 * verify and suplement the debug info found in the file specified
166 * by pszFilename. The module will be used by kDbg for as long as
167 * the returned kDbg module remains open.
168 * This is an optional parameter, pass NULL if no kLdr module at hand.
169 */
170KDBG_DECL(int) kDbgModuleOpenFilePart(PKDBGMOD *ppDbgMod, PKDBGHLPFILE pFile, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod)
171{
172 /*
173 * Validate input.
174 */
175 kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
176 kDbgAssertPtrReturn(pFile, KERR_INVALID_POINTER);
177 kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
178 kDbgAssertMsgReturn(off >= 0 && off < KFOFF_MAX, (KFOFF_PRI "\n", off), KERR_INVALID_OFFSET);
179 kDbgAssertMsgReturn(cb >= 0 && cb <= KFOFF_MAX, (KFOFF_PRI "\n", cb), KERR_INVALID_SIZE);
180 kDbgAssertMsgReturn(off + cb > off, ("off=" KFOFF_PRI " cb=" KFOFF_PRI "\n", off, cb), KERR_INVALID_RANGE);
181 *ppDbgMod = NULL;
182
183 /*
184 * Walk the built-in table and the list of registered readers
185 * and let each of them have a go at the file. Stop and return
186 * on the first one returning successfully.
187 */
188 int rc = KDBG_ERR_UNKOWN_FORMAT;
189 for (KSIZE i = 0; i < K_ELEMENTS(g_aBuiltIns); i++)
190 if (g_aBuiltIns[i]->pfnOpen)
191 {
192 int rc2 = g_aBuiltIns[i]->pfnOpen(ppDbgMod, pFile, off, cb, pLdrMod);
193 if (!rc)
194 return 0;
195 if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
196 rc = rc2;
197 }
198
199 for (PKDBGMODOPS pCur = g_pHead; pCur; pCur = pCur->pNext)
200 if (g_aBuiltIns[i]->pfnOpen)
201 {
202 int rc2 = g_aBuiltIns[i]->pfnOpen(ppDbgMod, pFile, off, cb, pLdrMod);
203 if (!rc)
204 return 0;
205 if (rc2 != KDBG_ERR_UNKOWN_FORMAT && rc == KDBG_ERR_UNKOWN_FORMAT)
206 rc = rc2;
207 }
208 return rc;
209}
210
211
212/**
213 * Opens a debug module reader for the specified file.
214 *
215 * @returns kStuff status code.
216 * @param ppDbgMod Where to store the debug module reader handle.
217 * @param pFile The file reader.
218 * @param pLdrMod Associated kLdr module that the kDbg component can use to
219 * verify and suplement the debug info found in the file specified
220 * by pszFilename. The module will be used by kDbg for as long as
221 * the returned kDbg module remains open.
222 * This is an optional parameter, pass NULL if no kLdr module at hand.
223 */
224KDBG_DECL(int) kDbgModuleOpenFile(PKDBGMOD *ppDbgMod, PKDBGHLPFILE pFile, struct KLDRMOD *pLdrMod)
225{
226 return kDbgModuleOpenFilePart(ppDbgMod, pFile, 0, KFOFF_MAX, pLdrMod);
227}
228
229
230/**
231 * Opens the debug info for a specified executable module.
232 *
233 * @returns kStuff status code.
234 * @param ppDbgMod Where to store the debug module handle.
235 * @param pszFilename The name of the file containing debug info and/or which
236 * debug info is wanted.
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) kDbgModuleOpen(PKDBGMOD *ppDbgMod, const char *pszFilename, struct KLDRMOD *pLdrMod)
244{
245 /*
246 * Validate input.
247 */
248 kDbgAssertPtrReturn(ppDbgMod, KERR_INVALID_POINTER);
249 kDbgAssertPtrReturn(pszFilename, KERR_INVALID_POINTER);
250 kDbgAssertMsgReturn(*pszFilename, ("%p\n", pszFilename), KERR_INVALID_PARAMETER);
251 kDbgAssertPtrNullReturn(pLdrMod, KERR_INVALID_POINTER);
252 *ppDbgMod = NULL;
253
254 /*
255 * Open the file and see if we can read it.
256 */
257 PKDBGHLPFILE pFile;
258 int rc = kDbgHlpOpenRO(pszFilename, &pFile);
259 if (rc)
260 return rc;
261 rc = kDbgModuleOpenFilePart(ppDbgMod, pFile, 0, KFOFF_MAX, pLdrMod);
262 if (rc)
263 kDbgHlpClose(pFile);
264 return rc;
265}
266
267
268/**
269 * Validates a debug module handle.
270 * All necessary asserting will be taken care of here.
271 *
272 * @returns True / false.
273 * @param pMod The debug module handle.
274 */
275KDBG_INLINE(bool) kdbgModIsValid(PKDBGMOD pMod)
276{
277 kDbgAssertPtrReturn(pMod, false);
278 kDbgAssertMsgReturn(pMod->u32Magic == KDBGMOD_MAGIC, ("%#x", pMod->u32Magic), false);
279 kDbgAssertPtrReturn(pMod->pOps, false);
280 return true;
281}
282
283
284/**
285 * Closes the module.
286 *
287 * @returns IPRT status code.
288 * @param pMod The module handle.
289 */
290KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod)
291{
292 if (!kdbgModIsValid(pMod))
293 return KERR_INVALID_PARAMETER;
294
295 int rc = pMod->pOps->pfnClose(pMod);
296 if (!rc)
297 kDbgHlpFree(pMod);
298 return rc;
299}
300
301
302/**
303 * Gets a symbol by segment:offset.
304 * This will be approximated to the nearest symbol if there is no exact match.
305 *
306 * @returns IPRT status code.
307 * @param pMod The module.
308 * @param iSegment The segment this offset is relative to.
309 * The -1 segment is special, it means that the addres is relative to
310 * the image base. The image base is where the first bit of the image
311 * is mapped during load.
312 * @param off The offset into the segment.
313 * @param pSym Where to store the symbol details.
314 */
315KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGSYMBOL pSym)
316{
317 if (!kdbgModIsValid(pMod))
318 return KERR_INVALID_PARAMETER;
319 kDbgAssertPtrReturn(pSym, KERR_INVALID_POINTER);
320
321 return pMod->pOps->pfnQuerySymbol(pMod, iSegment, off, pSym);
322}
323
324
325/**
326 * Gets & allocates a symbol by segment:offset.
327 * This will be approximated to the nearest symbol if there is no exact match.
328 *
329 * @returns IPRT status code.
330 * @param pMod The module.
331 * @param iSegment The segment this offset is relative to.
332 * The -1 segment is special, it means that the addres is relative to
333 * the image base. The image base is where the first bit of the image
334 * is mapped during load.
335 * @param off The offset into the segment.
336 * @param ppSym Where to store the pointer to the symbol info.
337 * Free the returned symbol using kDbgSymbolFree().
338 */
339KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym)
340{
341 kDbgAssertPtrReturn(ppSym, KERR_INVALID_POINTER);
342
343 KDBGSYMBOL Sym;
344 int rc = kDbgModuleQuerySymbol(pMod, iSegment, off, &Sym);
345 if (!rc)
346 {
347 *ppSym = kDbgSymbolDup(&Sym);
348 if (!*ppSym)
349 rc = KERR_NO_MEMORY;
350 }
351 else
352 *ppSym = NULL;
353 return rc;
354}
355
356
357/**
358 * Gets a line number entry by segment:offset.
359 * This will be approximated to the nearest line number 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 pLine Where to store the line number details.
369 */
370KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGLINE pLine)
371{
372 if (!kdbgModIsValid(pMod))
373 return KERR_INVALID_PARAMETER;
374 kDbgAssertPtrReturn(pLine, KERR_INVALID_POINTER);
375
376 return pMod->pOps->pfnQueryLine(pMod, iSegment, off, pLine);
377}
378
379
380/**
381 * Gets & allocates a line number entry by segment:offset.
382 * This will be approximated to the nearest line number there is no exact match.
383 *
384 * @returns IPRT status code.
385 * @param pMod The module.
386 * @param iSegment The segment this offset is relative to.
387 * The -1 segment is special, it means that the addres is relative to
388 * the image base. The image base is where the first bit of the image
389 * is mapped during load.
390 * @param off The offset into the segment.
391 * @param ppLine Where to store the pointer to the line number info.
392 * Free the returned line number using kDbgLineFree().
393 */
394KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PPKDBGLINE ppLine)
395{
396 kDbgAssertPtrReturn(ppLine, KERR_INVALID_POINTER);
397
398 KDBGLINE Line;
399 int rc = kDbgModuleQueryLine(pMod, iSegment, off, &Line);
400 if (!rc)
401 {
402 *ppLine = kDbgLineDup(&Line);
403 if (!*ppLine)
404 rc = KERR_NO_MEMORY;
405 }
406 else
407 *ppLine = NULL;
408 return rc;
409}
410
Note: See TracBrowser for help on using the repository browser.