/* $Id: kLdr.c 2826 2006-10-22 15:58:55Z bird $ */ /** @file * * kLdr - The Dynamic Loader. * * 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 * */ /** @pg pg_kLdr kLdr - The Dynamic Loader * * The purpose of kLdr is to provide a generic interface for querying * information about and loading executable image modules. * * kLdr defines the term executable image to include all kinds of files that contains * binary code that can be executed on a CPU - linker objects (OBJs/Os), shared * objects (SOs), dynamic link libraries (DLLs), executables (EXEs), and all kinds * of kernel modules / device drivers (SYSs). * * kLdr provides two types of services: * -# Inspect or/and load individual modules (kLdrMod). * -# Work as a dynamic loader - construct and maintain an address space (kLdrDy). * * The kLdrMod API works on KLDRMOD structures where all the internals are exposed, while * the kLdrDy API works opque KLDRDY structures. KLDRDY are in reality simple wrappers * around KLDRMOD with some extra linking and attributes. * */ #include "kLdr.h" #include "kLdrHlp.h" #if 0 /******************************************************************************* * Global Variables * *******************************************************************************/ /** Pointer to the head module (the executable). * (This is exported, so no prefix.) */ PKLDRMOD kLdrModuleHead = NULL; /** Pointer to the tail module. * (This is exported, so no prefix.) */ PKLDRMOD kLdrModuleTail = NULL; /** The Library search path. */ char kLdrLibraryPath[4096]; /** The executable flags. */ uint32_t kLdrFlags; /** Bootstrap stack and temporary space. */ char abStack[8192]; /** Set if we've initialized the loader. */ int fInitialized = 0; /******************************************************************************* * Internal Functions * *******************************************************************************/ static int kldrInit(void); static int kldrTerm(void); /** * Initialize the loader. */ int kldrInit(void) { if (fInitialized) return 0; /** @todo */ return 0; } void kldrLoadExe(PKLDREXEARGS pArgs) { /* * Copy the arguments into the globals and do load init. */ kLdrFlags = pArgs->fFlags; kLdrMemCopy(kLdrLibraryPath, pArgs->szLibPath, KLDR_MIN(sizeof(pArgs->szLibPath), sizeof(kLdrLibraryPath))); int rc = kldrInit(); if (rc) kldrFailure(rc, "kLdr: Init failure, rc=%d\n", rc); /* * Open the executable module. */ PKLDRMOD pExe; kldrOpenExe(pArgs->szExecutable, &pExe); /* Map the segments. */ kldrModMapSegments(pExe); /* * This is the point where we switch to the executable * stack, allocating it if necessary. */ void *pvBottom; kldrModSetupStack(pExe, &pvBottom); kldrLoadExecSwitchStack(pvBottom); } void kldrLoadExeOnNewStack(void) { /* * Load all dependant modules. */ PKLDRMOD pCur; do for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) { if (pCur->enmState >= KLDRSTATE_DEPS) continue; kldrModLoadDeps(pCur); } while (pCur); /* * Do fixups (FIFO). */ for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) { if (pCur->enmState >= KLDRSTATE_FIXED) continue; kldrModFixup(pCur, 0); } /* * Do module initialization. */ for (pCur = kLdrModuleTail; pCur != kLdrModuleTail; pCur = pCur->pPrev) { if (pCur->enmState >= KLDRSTATE_INITED) continue; kldrModCallInit(pCur); } /* * Get the executable start address and commit the work that's been done. */ void *pvEntry; kldrModGetExeEntry(&pvEntry); for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext) if (pCur->enmState == KLDRSTATE_INITED) pCur->enmState = KLDRSTATE_LOADED; kldrSemRelease(); /* * We're now ready for starting the executable code. */ kldrOSStartExe(pLdrModuleHead, pvEntry); } int kLdrLoadDll(const char *pszFilename, unsigned fFlags, void *pvmod) { return -1; } /** * Panic / failure * * @returns rc if we're in a position where we can return. * @param rc Return code. * @param pszFormat Message string. Limited fprintf like formatted. * @param ... Message string arguments. */ int kldrFailure(int rc, const char *pszFormat, ...) { kldrExit(1); return rc; } #endif