/* $Id: kDbgModule.cpp 3534 2007-08-23 00:28:15Z bird $ */ /** @file * kDbg - The Debug Info Reader, Module API. */ /* * Copyright (c) 2006-2007 knut st. osmundsen * * This file is part of kLIBC. * * kLIBC is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kLIBC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kLIBC; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "kDbg.h" #include "kLdr.h" #include "kDbgInternal.h" #include #include /******************************************************************************* * Global Variables * *******************************************************************************/ KDBG_DECL(int) kDbgModuleOpenFilePart(PKDBGHLPFILE pFile, int64_t off, int64_t cb, PKDBGMOD *ppDbgMod) { #if KOS_WINDOWS /* * If we're on Windows, let DbgHelp have a go first. */ if (!off) { int rc = kdbgModWinDbgHelpOpen(pFile, ppDbgMod); if (!rc) return 0; } #endif /* * Probe the file for signatures we recognize. */ int64_t offHdr = 0; union { uint32_t au32[4]; uint16_t au16[8]; uint8_t ab[16]; char } Buf; rc = kDbgHlpReadAt(pFile, &Buf, sizeof(Buf), off); } KDBG_DECL(int) kDbgModuleOpenFile(PKDBGHLPFILE pFile, PKDBGMOD *ppDbgMod) { return kDbgModuleOpenFilePart(pFile, 0, INT64_MAX, ppDbgMod); } KDBG_DECL(int) kDbgModuleOpenkLdrMod(PKLDRMOD pLdrMod, PKDBGMOD *ppDbgMod) { /* * Enumerate the debug info, if nothing found check for a matching .pdb, * .dbg, .sym or .map file. */ } /** * Opens the debug info for a specified executable module. * * @returns IPRT status code. * @param pszModulePath The path to the executable module. * @param ppDbgMod Where to store the debug module handle. */ KDBG_DECL(int) kDbgModuleOpen(const char *pszModulePath, PKDBGMOD *ppDbgMod) { /* * Validate input. */ kDbgAssertPtrReturn(pszModulePath, KDBG_ERR_INVALID_POINTER); kDbgAssertMsgReturn(*pszModulePath, ("%p\n", pszModulePath), KDBG_ERR_INVALID_PARAMETER); kDbgAssertPtrReturn(ppDbgMod, KDBG_ERR_INVALID_POINTER); *ppDbgMod = NULL; /* * Open the file and see if we can read it. */ PKDBGHLPFILE pFile; int rc = kDbgHlpOpenRO(pszModulePath, &pFile); if (rc) return rc; rc = kDbgModuleOpenFile(pFile, ppDbgMod); if (rc) { kDbgHlpClose(pFile); /* * Let kLdr have a shot at it, if it's a binary it may contain * some debug sections or a link to an external debug file. */ PKLDRMOD pLdrMod; int rc2 = kLdrModOpen(pszModulePath, *pLdrMod); if (!rc2) { rc = kDbgModuleOpenkLdrMod(pLdrMod, ppDbgMod); if (rc) kLdrModClose(pLdrMod); } } return rc; } /** * Validates a debug module handle. * All necessary asserting will be taken care of here. * * @returns True / false. * @param pMod The debug module handle. */ KDBG_INLINE(bool) kdbgModIsValid(PKDBGMOD pMod) { kDbgAssertPtrReturn(pMod, false); kDbgAssertMsgReturn(pMod->u32Magic == KDBGMOD_MAGIC, ("%#x", pMod->u32Magic), false); kDbgAssertPtrReturn(pMod->pOps, false); return true; } /** * Closes the module. * * @returns IPRT status code. * @param pMod The module handle. */ KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod) { if (!kdbgModIsValid(pMod)) return KDBG_ERR_INVALID_PARAMETER; int rc = pMod->pOps->pfnClose(pMod); if (!rc) kDbgHlpFree(pMod); return rc; } /** * Gets a symbol by segment:offset. * This will be approximated to the nearest symbol if there is no exact match. * * @returns IPRT status code. * @param pMod The module. * @param iSegment The segment this offset is relative to. * The -1 segment is special, it means that the addres is relative to * the image base. The image base is where the first bit of the image * is mapped during load. * @param off The offset into the segment. * @param pSym Where to store the symbol details. */ KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGSYMBOL pSym) { if (!kdbgModIsValid(pMod)) return KDBG_ERR_INVALID_PARAMETER; kDbgAssertPtrReturn(pSym, KDBG_ERR_INVALID_POINTER); return pMod->pOps->pfnQuerySymbol(pMod, iSegment, off, pSym); } /** * Gets & allocates a symbol by segment:offset. * This will be approximated to the nearest symbol if there is no exact match. * * @returns IPRT status code. * @param pMod The module. * @param iSegment The segment this offset is relative to. * The -1 segment is special, it means that the addres is relative to * the image base. The image base is where the first bit of the image * is mapped during load. * @param off The offset into the segment. * @param ppSym Where to store the pointer to the symbol info. * Free the returned symbol using kDbgSymbolFree(). */ KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym) { kDbgAssertPtrReturn(ppSym, KDBG_ERR_INVALID_POINTER); KDBGSYMBOL Sym; int rc = kDbgModuleQuerySymbol(pMod, iSegment, off, &Sym); if (!rc) { *ppSym = kDbgSymbolDup(&Sym); if (!*ppSym) rc = KDBG_ERR_NO_MEMORY; } else *ppSym = NULL; return rc; } /** * Gets a line number entry by segment:offset. * This will be approximated to the nearest line number there is no exact match. * * @returns IPRT status code. * @param pMod The module. * @param iSegment The segment this offset is relative to. * The -1 segment is special, it means that the addres is relative to * the image base. The image base is where the first bit of the image * is mapped during load. * @param off The offset into the segment. * @param pLine Where to store the line number details. */ KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PKDBGLINE pLine) { if (!kdbgModIsValid(pMod)) return KDBG_ERR_INVALID_PARAMETER; kDbgAssertPtrReturn(pLine, KDBG_ERR_INVALID_POINTER); return pMod->pOps->pfnQueryLine(pMod, iSegment, off, pLine); } /** * Gets & allocates a line number entry by segment:offset. * This will be approximated to the nearest line number there is no exact match. * * @returns IPRT status code. * @param pMod The module. * @param iSegment The segment this offset is relative to. * The -1 segment is special, it means that the addres is relative to * the image base. The image base is where the first bit of the image * is mapped during load. * @param off The offset into the segment. * @param ppLine Where to store the pointer to the line number info. * Free the returned line number using kDbgLineFree(). */ KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, int32_t iSegment, KDBGADDR off, PPKDBGLINE ppLine) { kDbgAssertPtrReturn(ppLine, KDBG_ERR_INVALID_POINTER); KDBGLINE Line; int rc = kDbgModuleQueryLine(pMod, iSegment, off, &Line); if (!rc) { *ppLine = kDbgLineDup(&Line); if (!*ppLine) rc = KDBG_ERR_NO_MEMORY; } else *ppLine = NULL; return rc; }