From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/lib/kStuff/kLdr/kLdrInternal.h | 463 +++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 src/lib/kStuff/kLdr/kLdrInternal.h (limited to 'src/lib/kStuff/kLdr/kLdrInternal.h') diff --git a/src/lib/kStuff/kLdr/kLdrInternal.h b/src/lib/kStuff/kLdr/kLdrInternal.h new file mode 100644 index 0000000..c670a41 --- /dev/null +++ b/src/lib/kStuff/kLdr/kLdrInternal.h @@ -0,0 +1,463 @@ +/* $Id: kLdrInternal.h 117 2020-03-15 15:23:36Z bird $ */ +/** @file + * kLdr - The Dynamic Loader, internal header. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___kLdrInternal_h___ +#define ___kLdrInternal_h___ + +#include +#include + +#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"). */ +#define IMAGE_ELF_SIGNATURE K_LE2H_U32(0x7f | ('E' << 8) | ((KU32)'L' << 16) | ((KU32)'F' << 24)) +/** PE signature ("PE\0\0"). */ +#define IMAGE_NT_SIGNATURE K_LE2H_U32('P' | ('E' << 8)) +/** LX signature ("LX") */ +#define IMAGE_LX_SIGNATURE K_LE2H_U16('L' | ('X' << 8)) +/** LE signature ("LE") */ +#define IMAGE_LE_SIGNATURE K_LE2H_U16('L' | ('E' << 8)) +/** NE signature ("NE") */ +#define IMAGE_NE_SIGNATURE K_LE2H_U16('N' | ('E' << 8)) +/** MZ signature ("MZ"). */ +#define IMAGE_DOS_SIGNATURE K_LE2H_U16('M' | ('Z' << 8)) +/** The FAT signature (universal binaries). */ +#define IMAGE_FAT_SIGNATURE KU32_C(0xcafebabe) +/** The FAT signature (universal binaries), other endian. */ +#define IMAGE_FAT_SIGNATURE_OE KU32_C(0xbebafeca) +/** The 32-bit Mach-O signature. */ +#define IMAGE_MACHO32_SIGNATURE KU32_C(0xfeedface) +/** The 32-bit Mach-O signature, other endian. */ +#define IMAGE_MACHO32_SIGNATURE_OE KU32_C(0xcefaedfe) +/** The 64-bit Mach-O signature. */ +#define IMAGE_MACHO64_SIGNATURE KU32_C(0xfeedfacf) +/** The 64-bit Mach-O signature, other endian. */ +#define IMAGE_MACHO64_SIGNATURE_OE KU32_C(0xfefaedfe) +/** @} */ + +/** @defgroup grp_kLdrInternal Internals + * @internal + * @{ + */ + +KI32 kldrModLXDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved); +KI32 kldrModPEDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved); + +/** + * The state of a dynamic loader module. + * @image html KLDRSTATE.gif "The state diagram" + */ +typedef enum KLDRSTATE +{ + /** The usual invalid 0 enum. */ + KLDRSTATE_INVALID = 0, + + /** The module has just been opened and linked into the load list. + * + * Prev state: - + * Next state: MAPPED, PENDING_DESTROY + */ + KLDRSTATE_OPEN, + + /** The module segments has been mapped into the process memory. + * + * Prev state: OPEN + * Next state: LOADED_PREREQUISITES, PENDING_DESTROY + */ + 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 + */ + KLDRSTATE_RELOADED, + + /** The immediate prerequisites have been loaded. + * + * Prev state: MAPPED + * Next state: FIXED_UP, PENDING_DESTROY + */ + KLDRSTATE_LOADED_PREREQUISITES, + /** The immediate prerequisites have been loaded for a reloaded module. + * + * Prev state: RELOADED + * Next state: RELOADED_FIXED_UP, PENDING_GC + */ + KLDRSTATE_RELOADED_LOADED_PREREQUISITES, + + /** Fixups has been applied. + * + * Prev state: LOADED_PREREQUISITES + * Next state: PENDING_INITIALIZATION, PENDING_DESTROY + */ + KLDRSTATE_FIXED_UP, + /** Fixups has been applied. + * + * Prev state: RELOADED_LOADED_PREREQUISITES + * Next state: PENDING_INITIALIZATION, PENDING_GC + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + KLDRSTATE_PENDING_GC, + + /** Being garbage collected. + * + * Prev state: PENDING_GC, INITIALIZATION_FAILED + * Next state: PENDING_DESTROY, DESTROYED + */ + 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 + */ + 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 + */ + KLDRSTATE_DESTROYED, + + /** The end of valid states (exclusive) */ + KLDRSTATE_END = KLDRSTATE_DESTROYED, + /** The usual 32-bit blowup. */ + KLDRSTATE_32BIT_HACK = 0x7fffffff +} KLDRSTATE; + + +/** + * Dynamic loader module. + */ +typedef struct KLDRDYLDMOD +{ + /** Magic number. */ + KU32 u32MagicHead; + /** The module state. */ + KLDRSTATE enmState; + /** The module. */ + PKLDRMOD pMod; + /** The module handle. */ + HKLDRMOD hMod; + /** The total number of references. */ + KU32 cRefs; + /** The number of dependency references. */ + KU32 cDepRefs; + /** The number of dynamic load references. */ + KU32 cDynRefs; + /** Set if this is the executable module. + * When clear, the module is a shared object or relocatable object. */ + KU32 fExecutable : 1; + /** Global DLL (set) or specific DLL (clear). */ + KU32 fGlobalOrSpecific : 1; + /** Whether the module contains bindable symbols in the global unix namespace. */ + KU32 fBindable : 1; + /** Set if linked into the global init list. */ + 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. */ + KU32 fAlreadySeen : 1; + /** Set if the module is currently mapped. + * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */ + KU32 fMapped : 1; + /** Set if TLS allocation has been done. (part of the mapping). */ + KU32 fAllocatedTLS : 1; + /** Reserved for future use. */ + KU32 f25Reserved : 25; + /** The load list linkage. */ + struct + { + /** The next module in the list. */ + struct KLDRDYLDMOD *pNext; + /** The prev module in the list. */ + 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. */ + 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. + */ + struct KLDRDYLDMOD **papPrereqs; + + /** Magic number. */ + KU32 u32MagicTail; +} KLDRDYLDMOD, *PKLDRDYLDMOD, **PPKLDRDYLDMOD; + +/** KLDRDYLDMOD magic value. (Fuyumi Soryo) */ +#define KLDRDYMOD_MAGIC 0x19590106 + +/** Return / crash validation of a module handle argument. */ +#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 -- cgit v1.2.3