Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

kLdrInternal.h

Go to the documentation of this file.
/* $Id: kLdrInternal.h 2 2007-11-16 16:07:14Z bird $ */
/** @file
 * kLdr - The Dynamic Loader, internal header.
 */

/*
 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kStuff-spam@anduin.net>
 *
 * This file is part of kStuff.
 *
 * kStuff is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * In addition to the permissions in the GNU Lesser General Public
 * License, you are granted unlimited permission to link the compiled
 * version of this file into combinations with other programs, and to
 * distribute those combinations without any restriction coming from
 * the use of this file.
 *
 * kStuff 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with kStuff; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#ifndef ___kLdrInternal_h___
#define ___kLdrInternal_h___

#include <k/kHlp.h>
#include <k/kRdr.h>

#ifdef __cplusplus
extern "C" {
#endif

#if !defined(__X86__) && !defined(__AMD64__)
# if defined(__i386__) || defined(_M_IX86)
#  define __X86__
# elif defined(__x86_64__) || defined(_M_X64) || defined(__AMD64__) || defined(_M_AMD64)
#  define __AMD64__
# else
#  error "can't figure out the target arch."
# endif
#endif

/* ignore definitions in winnt.h */
#undef IMAGE_DOS_SIGNATURE
#undef IMAGE_NT_SIGNATURE

/** @name Signatures we know
 * @{ */
/** ELF signature ("\x7fELF"). */
00060 #define IMAGE_ELF_SIGNATURE         K_LE2H_U32(0x7f | ('E' << 8) | ((KU32)'L' << 16) | ((KU32)'F' << 24))
/** PE signature ("PE\0\0"). */
00062 #define IMAGE_NT_SIGNATURE          K_LE2H_U32('P' | ('E' << 8))
/** LX signature ("LX") */
00064 #define IMAGE_LX_SIGNATURE          K_LE2H_U16('L' | ('X' << 8))
/** LE signature ("LE") */
00066 #define IMAGE_LE_SIGNATURE          K_LE2H_U16('L' | ('E' << 8))
/** NE signature ("NE") */
00068 #define IMAGE_NE_SIGNATURE          K_LE2H_U16('N' | ('E' << 8))
/** MZ signature ("MZ"). */
00070 #define IMAGE_DOS_SIGNATURE         K_LE2H_U16('M' | ('Z' << 8))
/** The FAT signature (universal binaries). */
00072 #define IMAGE_FAT_SIGNATURE         KU32_C(0xcafebabe)
/** The FAT signature (universal binaries), other endian. */
00074 #define IMAGE_FAT_SIGNATURE_OE      KU32_C(0xbebafeca)
/** The 32-bit Mach-O signature. */
00076 #define IMAGE_MACHO32_SIGNATURE     KU32_C(0xfeedface)
/** The 32-bit Mach-O signature, other endian. */
00078 #define IMAGE_MACHO32_SIGNATURE_OE  KU32_C(0xcefaedfe)
/** The 64-bit Mach-O signature. */
00080 #define IMAGE_MACHO64_SIGNATURE     KU32_C(0xfeedfacf)
/** The 64-bit Mach-O signature, other endian. */
00082 #define IMAGE_MACHO64_SIGNATURE_OE  KU32_C(0xfefaedfe)
/** @} */

/** @defgroup grp_kLdrInternal  Internals
 * @internal
 * @{
 */


/**
 * The state of a dynamic loader module.
 * @image html KLDRSTATE.gif "The state diagram"
 */
00095 typedef enum KLDRSTATE
{
    /** The usual invalid 0 enum. */
00098     KLDRSTATE_INVALID = 0,

    /** The module has just been opened and linked into the load list.
     *
     * Prev state: -
     * Next state: MAPPED, PENDING_DESTROY
     */
00105     KLDRSTATE_OPEN,

    /** The module segments has been mapped into the process memory.
     *
     * Prev state: OPEN
     * Next state: LOADED_PREREQUISITES, PENDING_DESTROY
     */
00112     KLDRSTATE_MAPPED,
    /** The module has been reloaded and needs to be fixed up again.
     * This can occure when the loader is called recursivly.
     *
     * The reason RELOADED modules must go back to the PENDING_GC state is
     * because we want to guard against uninit order issues, and therefore
     * doesn't unmap modules untill all pending termintation callbacks has
     * been executed.
     *
     * Prev state: PENDING_GC
     * Next state: RELOADED_LOADED_PREREQUISITES, PENDING_GC
     */
00124     KLDRSTATE_RELOADED,

    /** The immediate prerequisites have been loaded.
     *
     * Prev state: MAPPED
     * Next state: FIXED_UP, PENDING_DESTROY
     */
00131     KLDRSTATE_LOADED_PREREQUISITES,
    /** The immediate prerequisites have been loaded for a reloaded module.
     *
     * Prev state: RELOADED
     * Next state: RELOADED_FIXED_UP, PENDING_GC
     */
00137     KLDRSTATE_RELOADED_LOADED_PREREQUISITES,

    /** Fixups has been applied.
     *
     * Prev state: LOADED_PREREQUISITES
     * Next state: PENDING_INITIALIZATION, PENDING_DESTROY
     */
00144     KLDRSTATE_FIXED_UP,
    /** Fixups has been applied.
     *
     * Prev state: RELOADED_LOADED_PREREQUISITES
     * Next state: PENDING_INITIALIZATION, PENDING_GC
     */
00150     KLDRSTATE_RELOADED_FIXED_UP,

    /** Pending initialization.
     * While the module is in this state the loader is in reentrant mode.
     *
     * Prev state: FIXED_UP, RELOADED_FIXED_UP
     * Next state: INITIALIZATION, PENDING_GC
     */
00158     KLDRSTATE_PENDING_INITIALIZATION,

    /** Initializing.
     * While the module is in this state the loader is in reentrant mode.
     *
     * Prev state: PENDING_INITIALIZATION
     * Next state: GOOD, PENDING_GC
     */
00166     KLDRSTATE_INITIALIZING,

    /** Initialization failed.
     *
     * This is somewhat similar to PENDING_GC except that, a module
     * in this state cannot be reloaded untill we've done GC. This ensures
     * that a init failure during recursive loading is propagated up.
     *
     * While the module is in this state the loader is in reentrant mode.
     *
     * Prev state: INITIALIZING
     * Next state: GC
     */
00179     KLDRSTATE_INITIALIZATION_FAILED,

    /** The module has been successfully loaded and initialized.
     * While the module is in this state the loader can be in reentrant
     * or 'unused' mode.
     *
     * Prev state: INITIALIZING
     * Next state: PENDING_TERMINATION
     */
00188     KLDRSTATE_GOOD,

    /** Pending termination, reference count is 0.
     * While the module is in this state the loader is in reentrant mode.
     * Prerequisite modules are dropped when a module enters this state.
     *
     * Prev state: GOOD
     * Next state: TERMINATING, GOOD
     */
00197     KLDRSTATE_PENDING_TERMINATION,

    /** Terminating, reference count is still 0.
     * While the module is in this state the loader is in reentrant mode.
     *
     * Prev state: PENDING_TERMINATION
     * Next state: PENDING_GC
     */
00205     KLDRSTATE_TERMINATING,

    /** Pending garbage collection.
     * Prerequisite modules are dropped when a module enters this state (if not done already).
     *
     * Prev state: TERMINATING, PENDING_INITIALIZATION, INITIALIZATION_FAILED
     * Next state: GC, RELOADED
     */
00213     KLDRSTATE_PENDING_GC,

    /** Being garbage collected.
     *
     * Prev state: PENDING_GC, INITIALIZATION_FAILED
     * Next state: PENDING_DESTROY, DESTROYED
     */
00220     KLDRSTATE_GC,

    /** The module has be unlinked, but there are still stack references to it.
     *
     * Prev state: GC, FIXED_UP, LOADED_PREREQUISITES, MAPPED, OPEN
     * Next state: DESTROYED
     */
00227     KLDRSTATE_PENDING_DESTROY,

    /** The module has been destroyed but not freed yet.
     *
     * This happens when a module ends up being destroyed when cRefs > 0. The
     * module structure will be freed when cRefs reaches 0.
     *
     * Prev state: GC, PENDING_DESTROY
     */
00236     KLDRSTATE_DESTROYED,

    /** The end of valid states (exclusive) */
00239     KLDRSTATE_END = KLDRSTATE_DESTROYED,
    /** The usual 32-bit blowup. */
00241     KLDRSTATE_32BIT_HACK = 0x7fffffff
} KLDRSTATE;


/**
 * Dynamic loader module.
 */
00248 typedef struct KLDRDYLDMOD
{
    /** Magic number. */
00251     KU32                u32MagicHead;
    /** The module state. */
00253     KLDRSTATE           enmState;
    /** The module. */
00255     PKLDRMOD            pMod;
    /** The module handle. */
00257     HKLDRMOD            hMod;
    /** The total number of references. */
00259     KU32                cRefs;
    /** The number of dependency references. */
00261     KU32                cDepRefs;
    /** The number of dynamic load references. */
00263     KU32                cDynRefs;
    /** Set if this is the executable module.
     * When clear, the module is a shared object or relocatable object. */
00266     KU32                fExecutable : 1;
    /** Global DLL (set) or specific DLL (clear). */
00268     KU32                fGlobalOrSpecific : 1;
    /** Whether the module contains bindable symbols in the global unix namespace. */
00270     KU32                fBindable : 1;
    /** Set if linked into the global init list. */
00272     KU32                fInitList : 1;
    /** Already loaded or checked prerequisites.
     * This flag is used when loading prerequisites, when set it means that
     * this module is already seen and shouldn't be processed again. */
00276     KU32                fAlreadySeen : 1;
    /** Set if the module is currently mapped.
     * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */
00279     KU32                fMapped : 1;
    /** Set if TLS allocation has been done. (part of the mapping). */
00281     KU32                fAllocatedTLS : 1;
    /** Reserved for future use. */
00283     KU32                f25Reserved : 25;
    /** The load list linkage. */
    struct
    {
        /** The next module in the list. */
00288         struct KLDRDYLDMOD *pNext;
        /** The prev module in the list. */
00290         struct KLDRDYLDMOD *pPrev;
    } Load;
    /** The initialization and termination list linkage.
     * If non-recursive initialization is used, the module will be pushed on
     * the initialization list.
     * A module will be linked into the termination list upon a successful
     * return from module initialization. */
    struct
    {
        /** The next module in the list. */
        struct KLDRDYLDMOD *pNext;
        /** The prev module in the list. */
        struct KLDRDYLDMOD *pPrev;
    } InitTerm;
    /** The bind order list linkage.
     * The module is not in this list when fBindable is clear. */
    struct
    {
        /** The next module in the list. */
        struct KLDRDYLDMOD *pNext;
        /** The prev module in the list. */
        struct KLDRDYLDMOD *pPrev;
    } Bind;

    /** The number of prerequisite modules in the prereq array. */
00315     KU32                cPrereqs;
    /** Pointer to an array of prerequisite module pointers.
     * This array is only filled when in the states starting with
     * KLDRSTATE_LOADED_PREREQUISITES thru KLDRSTATE_GOOD.
     */
00320     struct KLDRDYLDMOD **papPrereqs;

    /** Magic number. */
00323     KU32                u32MagicTail;
} KLDRDYLDMOD, *PKLDRDYLDMOD, **PPKLDRDYLDMOD;

/** KLDRDYLDMOD magic value. (Fuyumi Soryo) */
00327 #define KLDRDYMOD_MAGIC     0x19590106

/** Return / crash validation of a module handle argument. */
00330 #define KLDRDYLD_VALIDATE_HKLDRMOD(hMod) \
    do  { \
        if (    (hMod) == NIL_HKLDRMOD \
            ||  (hMod)->u32MagicHead != KLDRDYMOD_MAGIC \
            ||  (hMod)->u32MagicTail != KLDRDYMOD_MAGIC) \
        { \
            return KERR_INVALID_HANDLE; \
        } \
    } while (0)


int kldrInit(void);
void kldrTerm(void);

int kldrDyldInit(void);
void kldrDyldTerm(void);

void kldrDyldDoLoadExe(PKLDRDYLDMOD pExe);
int kldrDyldFailure(int rc, const char *pszFormat, ...);

int kldrDyldOSStartExe(KUPTR uMainEntrypoint, void *pvStack, KSIZE cbStack);
void *kldrDyldOSAllocStack(KSIZE cb);

int kldrDyldFindInit(void);
int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
                          KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
                               KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);

int kldrDyldGetPrerequisite(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
                            unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod);


int kldrDyldModCreate(PKRDR pRdr, KU32 fFlags, PPKLDRDYLDMOD ppMod);
void kldrDyldModDestroy(PKLDRDYLDMOD pMod);
void kldrDyldModAddRef(PKLDRDYLDMOD pMod);
void kldrDyldModDeref(PKLDRDYLDMOD pMod);
void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep);
void kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
int kldrDyldModMap(PKLDRDYLDMOD pMod);
int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags);
int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod);
void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod);
int kldrDyldModFixup(PKLDRDYLDMOD pMod);
int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
int kldrDyldModReload(PKLDRDYLDMOD pMod);
int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
void kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, KSIZE *pcbStack);
int kldrDyldModStartExe(PKLDRDYLDMOD pMod);

int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName);
int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename);
int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName, KUPTR *puValue, KU32 *pfKind);


/** Pointer to the head module (the executable).
 * (This is exported, so no prefix.) */
extern PKLDRDYLDMOD     kLdrDyldHead;
/** Pointer to the tail module.
 * (This is exported, so no prefix.) */
extern PKLDRDYLDMOD     kLdrDyldTail;
/** Pointer to the head module of the initialization list.
 * The outermost load call will pop elements from this list in LIFO order (i.e.
 * from the tail). The list is only used during non-recursive initialization
 * and may therefore share the pNext/pPrev members with the termination list
 * since we don't push a module onto the termination list untill it has been
 * successfully initialized. */
extern PKLDRDYLDMOD     g_pkLdrDyldInitHead;
/** Pointer to the tail module of the initalization list. */
extern PKLDRDYLDMOD     g_pkLdrDyldInitTail;
/** Pointer to the head module of the termination order list. */
extern PKLDRDYLDMOD     g_pkLdrDyldTermHead;
/** Pointer to the tail module of the termination order list. */
extern PKLDRDYLDMOD     g_pkLdrDyldTermTail;
/** Pointer to the head module of the bind order list.
 * The modules in this list makes up the global namespace used when binding symbol unix fashion. */
extern PKLDRDYLDMOD     g_pkLdrDyldBindHead;
/** Pointer to the tail module of the bind order list. */
extern PKLDRDYLDMOD     g_pkLdrDyldBindTail;

/** Indicates that the other MainStack globals have been filled in. */
extern unsigned         g_fkLdrDyldDoneMainStack;
/** Whether the stack was allocated seperatly or was part of the executable. */
extern unsigned         g_fkLdrDyldMainStackAllocated;
/** Pointer to the main stack object. */
extern void            *g_pvkLdrDyldMainStack;
/** The size of the main stack object. */
extern KSIZE            g_cbkLdrDyldMainStack;

/** The global error buffer. */
extern char             g_szkLdrDyldError[1024];

extern char             kLdrDyldExePath[8192];
extern char             kLdrDyldLibraryPath[8192];
extern char             kLdrDyldDefPrefix[16];
extern char             kLdrDyldDefSuffix[16];

extern int              g_fBootstrapping;


/** @name The Loader semaphore
 * @{ */
int     kLdrDyldSemInit(void);
void    kLdrDyldSemTerm(void);
int     kLdrDyldSemRequest(void);
void    kLdrDyldSemRelease(void);
/** @} */


/** @name Module interpreter method tables
 * @{ */
extern KLDRMODOPS       g_kLdrModLXOps;
extern KLDRMODOPS       g_kLdrModMachOOps;
extern KLDRMODOPS       g_kLdrModNativeOps;
extern KLDRMODOPS       g_kLdrModPEOps;
/** @} */


/** @} */
#ifdef __cplusplus
}
#endif

#endif

Generated by  Doxygen 1.6.0   Back to index