dbgmodnm.cpp revision e64031e20c39650a7bc902a3e1aba613b9415dee
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * IPRT - Debug Map Reader For NM Like Mapfiles.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2009 Oracle Corporation
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * available from http://www.virtualbox.org. This file is free software;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * General Public License (GPL) as published by the Free Software
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * The contents of this file may alternatively be used under the terms
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * of the Common Development and Distribution License Version 1.0
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * VirtualBox OSE distribution, in which case the provisions of the
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * CDDL are applicable instead of those of the GPL.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * You may elect to license modified versions of this file under the
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * terms and conditions of either the GPL or the CDDL or both.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync/*******************************************************************************
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync* Header Files *
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync*******************************************************************************/
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync/*******************************************************************************
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync* Structures and Typedefs *
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync*******************************************************************************/
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Instance data.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsynctypedef struct RTDBGMODNM
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /** The debug container containing doing the real work. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync/** Pointer to instance data NM map reader. */
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(uint32_t) rtDbgModNm_LineCount(PRTDBGMODINT pMod)
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, poffDisp, pSymInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol, PRTDBGSYMBOL pSymInfo)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSymbolByName(pThis->hCnt, pszSymbol, pSymInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(uint32_t) rtDbgModNm_SymbolCount(PRTDBGMODINT pMod)
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(RTDBGSEGIDX) rtDbgModNm_SegmentCount(PRTDBGMODINT pMod)
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(RTUINTPTR) rtDbgModNm_ImageSize(PRTDBGMODINT pMod)
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(RTDBGSEGIDX) rtDbgModNm_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_Close(PRTDBGMODINT pMod)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Scans a NM-like map file.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * This implements both passes to avoid code duplication.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * @returns IPRT status code.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * @param pThis The instance data.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * @param pStrm The stream.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * @param fAddSymbols false in the first pass, true in the second.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic int rtDbgModNmScanFile(PRTDBGMODNM pThis, PRTSTREAM pStrm, bool fAddSymbols)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Try parse the stream.
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync RTUINTPTR SegZeroRva = fAddSymbols ? RTDbgModSegmentRva(pThis->hCnt, 0/*iSeg*/) : 0;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync unsigned cchAddr = 0;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync while (RT_SUCCESS(rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine))))
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * This is really what C was made for, string parsing.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* The the symbol value (address). */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* Check the address width. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* Get the type and check for single space before symbol. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* Find the end of the symbol name. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync while ((ch = *pszNameEnd) != '\0' && !RT_C_IS_SPACE(ch))
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* Any module name (linux /proc/kallsyms) following in brackets? */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync pszModNameEnd = pszModName = RTStrStripL(pszModName);
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync if ((size_t)(pszModNameEnd - pszModName) >= 128) /* lazy bird */
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync * Did the module change? Then update the symbol prefix.
fafed696393fa93dbeb0e4a40eb5e252ec4ad858vboxsync if ( cchMod != (size_t)(pszModNameEnd - pszModName)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Validate the type and add the symbol if it's a type we care for.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* absolute */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_COMMON;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_COMMON;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_CONST;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_CONST;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_TEXT;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_TEXT;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_WEAK | RTDBG_SYM_FLAGS_LOCAL; //???
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /// @todo fFlags |= RTDBG_SYM_FLAGS_WEAK | RTDBG_SYM_FLAGS_PUBLIC;
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync rc = RTDbgModSymbolAdd(pThis->hCnt, szSym, iSegSym, u64Addr - SegZeroRva, 0/*cb*/, fFlags, NULL);
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync rc = RTDbgModSymbolAdd(pThis->hCnt, szSym, iSegSym, u64Addr, 0/*cb*/, fFlags, NULL);
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync && rc != VERR_DBG_ADDRESS_CONFLICT) /* (don't be too strict) */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* Track segment span. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * This is either a blank line or a symbol without an address.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync cchAddr = cch < 16+3 || szLine[8+1] != ' ' ? 8 : 16;
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /* else: blank - ignored */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * The final segment.
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync rc = RTDbgModSegmentAdd(pThis->hCnt, u64Low, u64High - u64Low + 1, "main", 0, NULL);
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync else /* No sensible symbols... throw an error instead? */
b0408ca29e7865aa09db4b6bf5dbedd6ad27bf12vboxsync rc = RTDbgModSegmentAdd(pThis->hCnt, 0, 0, "main", 0, NULL);
1dcfc3175560423a364f8b3b15edfe8587981a38vboxsync/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsyncstatic DECLCALLBACK(int) rtDbgModNm_TryOpen(PRTDBGMODINT pMod)
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Try open the file and create an instance.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync int rc = RTStrmOpen(pMod->pszDbgFile, "r", &pStrm);
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync PRTDBGMODNM pThis = (PRTDBGMODNM)RTMemAlloc(sizeof(*pThis));
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * Scan the file twice, first to figure the segment
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync * sizes, then to add the symbol.
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync rc = rtDbgModNmScanFile(pThis, pStrm, false /*fAddSymbols*/);
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync rc = rtDbgModNmScanFile(pThis, pStrm, true /*fAddSymbols*/);
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync/** Virtual function table for the NM-like map file reader. */
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /*.pfnSegmentByIndex = */ rtDbgModNm_SegmentByIndex,
315c82bf68ba7cdefb15240bcaff386e300ff1c1vboxsync /*.pfnSymbolByOrdinal = */ rtDbgModNm_SymbolByOrdinal,