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

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

kRdr hacking.

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