/* $Id: kLdrMod.c 2827 2006-10-22 18:05:28Z bird $ */ /** @file * * kLdr - The Dynamic Loader, The module interpreter. * * Copyright (c) 2006 knut st. osmundsen * * * This file is part of kLdr. * * kLdr 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. * * kLdr 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 kLdr; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include "kLdrHlp.h" #include "kLdrInternal.h" #include "kLdrModMZ.h" #if 1 /* testing headers */ # include "kLdrModPE.h" //# include "kLdrModLX.h" # include "kLdrModELF32.h" # include "kLdrModELF64.h" #endif /** * Open a executable image from a file provider instance. * * @returns 0 on success and *ppMod pointing to a module instance. * On failure, a non-zero OS specific error code is returned. * @param pRdr The file provider instance to use. * On success, the ownership of the instance is taken by the * module and the caller must not ever touch it again. * (The instance is not closed on failure, the call has to do that.) * @param ppMod Where to store the module handle. */ int kLdrModOpenFromRdr(PKLDRRDR pRdr, PPKLDRMOD ppMod) { union { uint32_t u32; uint16_t u16; uint16_t au16[2]; uint8_t au8[4]; } u; off_t offHdr = 0; int rc; /* * Try figure out what kind of image this is. * Always read the 'new header' if we encounter MZ. */ rc = kLdrRdrRead(pRdr, &u, sizeof(u), 0); if (rc) return rc; if ( u.u16 == IMAGE_DOS_SIGNATURE && kLdrRdrSize(pRdr) > sizeof(IMAGE_DOS_HEADER)) { rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), KLDR_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew)); if (rc) return rc; if ((off_t)u.u32 < kLdrRdrSize(pRdr)) { offHdr = u.u32; rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), offHdr); if (rc) return rc; } else u.u16 = IMAGE_DOS_SIGNATURE; } /* * Use the magic to select the appropriate image interpreter. */ if (u.u16 == IMAGE_DOS_SIGNATURE) return KLDR_ERR_MZ_NOT_SUPPORTED; else if (u.u16 == IMAGE_NE_SIGNATURE) return KLDR_ERR_NE_NOT_SUPPORTED; else if (u.u16 == IMAGE_LX_SIGNATURE) return KLDR_ERR_LX_NOT_SUPPORTED; else if (u.u16 == IMAGE_LE_SIGNATURE) return KLDR_ERR_LE_NOT_SUPPORTED; else if (u.u32 == IMAGE_NT_SIGNATURE) return KLDR_ERR_PE_NOT_SUPPORTED; else if (u.u32 == IMAGE_ELF_SIGNATURE) return KLDR_ERR_ELF_NOT_SUPPORTED; return KLDR_ERR_UNKNOWN_FORMAT; } /** * Open a executable image by file name. * * @returns 0 on success and *ppMod pointing to a module instance. * On failure, a non-zero OS specific error code is returned. * @param pszFilename The filename to open. * @param ppMod Where to store the module handle. */ int kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod) { /* * Open the file using a bit provider. */ PKLDRRDR pRdr; int rc = kLdrRdrOpen(&pRdr, pszFilename); if (!rc) { rc = kLdrModOpenFromRdr(pRdr, ppMod); if (!rc) return 0; kLdrRdrClose(pRdr); } return rc; }