/* $Id: $ */ /** @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 * */ #include "kLdr.h" /** memcpy */ #define kLdrMemCopy(a,b,c) __builtin_memcpy(a,b,c) /** Get the minimum of two values. */ #define KLDR_MIN(a, b) ((a) <= (b) ? (a) : (b)) /******************************************************************************* * 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; }