source: trunk/kStuff/kLdr/kLdrInternal.h

Last change on this file was 3601, checked in by bird, 18 years ago

license update.

  • Property svn:keywords set to Id
File size: 16.4 KB
RevLine 
[2826]1/* $Id: kLdrInternal.h 3601 2007-10-29 00:21:13Z bird $ */
[2825]2/** @file
3 * kLdr - The Dynamic Loader, internal header.
[3601]4 */
5
6/*
7 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kStuff-spam@anduin.net>
[2825]8 *
[3601]9 * This file is part of kStuff.
[2825]10 *
[3601]11 * kStuff is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
[2825]15 *
[3601]16 * In addition to the permissions in the GNU Lesser General Public
17 * License, you are granted unlimited permission to link the compiled
18 * version of this file into combinations with other programs, and to
19 * distribute those combinations without any restriction coming from
20 * the use of this file.
[2825]21 *
[3601]22 * kStuff is distributed in the hope that it will be useful,
[2825]23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[3601]24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
[2825]26 *
[3601]27 * You should have received a copy of the GNU Lesser General Public
28 * License along with kStuff; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA
[2825]31 */
32
[3573]33#ifndef ___kLdrInternal_h___
34#define ___kLdrInternal_h___
[2825]35
[3573]36#include <k/kHlp.h>
[3578]37#include <k/kRdr.h>
[3573]38
[2825]39#ifdef __cplusplus
40extern "C" {
41#endif
42
[2944]43#if !defined(__X86__) && !defined(__AMD64__)
[2883]44# if defined(__i386__) || defined(_M_IX86)
45# define __X86__
46# elif defined(__x86_64__) || defined(_M_X64) || defined(__AMD64__) || defined(_M_AMD64)
47# define __AMD64__
48# else
49# error "can't figure out the target arch."
50# endif
51#endif
52
[2827]53/* ignore definitions in winnt.h */
54#undef IMAGE_DOS_SIGNATURE
55#undef IMAGE_NT_SIGNATURE
56
57/** @name Signatures we know
58 * @{ */
59/** ELF signature ("\x7fELF"). */
[3569]60#define IMAGE_ELF_SIGNATURE K_LE2H_U32(0x7f | ('E' << 8) | ((KU32)'L' << 16) | ((KU32)'F' << 24))
[2827]61/** PE signature ("PE\0\0"). */
[3569]62#define IMAGE_NT_SIGNATURE K_LE2H_U32('P' | ('E' << 8))
[2827]63/** LX signature ("LX") */
[3569]64#define IMAGE_LX_SIGNATURE K_LE2H_U16('L' | ('X' << 8))
[2827]65/** LE signature ("LE") */
[3569]66#define IMAGE_LE_SIGNATURE K_LE2H_U16('L' | ('E' << 8))
[2827]67/** NE signature ("NE") */
[3569]68#define IMAGE_NE_SIGNATURE K_LE2H_U16('N' | ('E' << 8))
[2827]69/** MZ signature ("MZ"). */
[3569]70#define IMAGE_DOS_SIGNATURE K_LE2H_U16('M' | ('Z' << 8))
[2954]71/** The FAT signature (universal binaries). */
[3567]72#define IMAGE_FAT_SIGNATURE KU32_C(0xcafebabe)
[2954]73/** The FAT signature (universal binaries), other endian. */
[3567]74#define IMAGE_FAT_SIGNATURE_OE KU32_C(0xbebafeca)
[2954]75/** The 32-bit Mach-O signature. */
[3567]76#define IMAGE_MACHO32_SIGNATURE KU32_C(0xfeedface)
[2954]77/** The 32-bit Mach-O signature, other endian. */
[3567]78#define IMAGE_MACHO32_SIGNATURE_OE KU32_C(0xcefaedfe)
[2954]79/** The 64-bit Mach-O signature. */
[3567]80#define IMAGE_MACHO64_SIGNATURE KU32_C(0xfeedfacf)
[2954]81/** The 64-bit Mach-O signature, other endian. */
[3567]82#define IMAGE_MACHO64_SIGNATURE_OE KU32_C(0xfefaedfe)
[2827]83/** @} */
84
[2833]85/** @defgroup grp_kLdrInternal Internals
86 * @internal
87 * @{
88 */
[2827]89
[2833]90
[2825]91/**
92 * The state of a dynamic loader module.
[2840]93 * @image html KLDRSTATE.gif "The state diagram"
[2825]94 */
95typedef enum KLDRSTATE
96{
97 /** The usual invalid 0 enum. */
98 KLDRSTATE_INVALID = 0,
[2840]99
100 /** The module has just been opened and linked into the load list.
101 *
[2836]102 * Prev state: -
[2840]103 * Next state: MAPPED, PENDING_DESTROY
[2836]104 */
[2825]105 KLDRSTATE_OPEN,
[2840]106
107 /** The module segments has been mapped into the process memory.
108 *
[2836]109 * Prev state: OPEN
[2840]110 * Next state: LOADED_PREREQUISITES, PENDING_DESTROY
[2836]111 */
112 KLDRSTATE_MAPPED,
[2837]113 /** The module has been reloaded and needs to be fixed up again.
[2840]114 * This can occure when the loader is called recursivly.
115 *
116 * The reason RELOADED modules must go back to the PENDING_GC state is
117 * because we want to guard against uninit order issues, and therefore
118 * doesn't unmap modules untill all pending termintation callbacks has
119 * been executed.
120 *
[2837]121 * Prev state: PENDING_GC
[2840]122 * Next state: RELOADED_LOADED_PREREQUISITES, PENDING_GC
[2837]123 */
124 KLDRSTATE_RELOADED,
[2840]125
[2837]126 /** The immediate prerequisites have been loaded.
[2840]127 *
128 * Prev state: MAPPED
129 * Next state: FIXED_UP, PENDING_DESTROY
[2836]130 */
[2837]131 KLDRSTATE_LOADED_PREREQUISITES,
[2840]132 /** The immediate prerequisites have been loaded for a reloaded module.
133 *
134 * Prev state: RELOADED
135 * Next state: RELOADED_FIXED_UP, PENDING_GC
136 */
137 KLDRSTATE_RELOADED_LOADED_PREREQUISITES,
138
[2836]139 /** Fixups has been applied.
[2840]140 *
[2837]141 * Prev state: LOADED_PREREQUISITES
[2840]142 * Next state: PENDING_INITIALIZATION, PENDING_DESTROY
[2836]143 */
144 KLDRSTATE_FIXED_UP,
[2840]145 /** Fixups has been applied.
146 *
147 * Prev state: RELOADED_LOADED_PREREQUISITES
[2836]148 * Next state: PENDING_INITIALIZATION, PENDING_GC
149 */
[2840]150 KLDRSTATE_RELOADED_FIXED_UP,
151
152 /** Pending initialization.
153 * While the module is in this state the loader is in reentrant mode.
154 *
155 * Prev state: FIXED_UP, RELOADED_FIXED_UP
156 * Next state: INITIALIZATION, PENDING_GC
157 */
[2836]158 KLDRSTATE_PENDING_INITIALIZATION,
[2840]159
[2836]160 /** Initializing.
[2840]161 * While the module is in this state the loader is in reentrant mode.
162 *
[2836]163 * Prev state: PENDING_INITIALIZATION
164 * Next state: GOOD, PENDING_GC
165 */
166 KLDRSTATE_INITIALIZING,
[2840]167
168 /** Initialization failed.
169 *
170 * This is somewhat similar to PENDING_GC except that, a module
171 * in this state cannot be reloaded untill we've done GC. This ensures
172 * that a init failure during recursive loading is propagated up.
173 *
174 * While the module is in this state the loader is in reentrant mode.
175 *
176 * Prev state: INITIALIZING
177 * Next state: GC
178 */
179 KLDRSTATE_INITIALIZATION_FAILED,
180
[2836]181 /** The module has been successfully loaded and initialized.
[2840]182 * While the module is in this state the loader can be in reentrant
183 * or 'unused' mode.
184 *
[2836]185 * Prev state: INITIALIZING
186 * Next state: PENDING_TERMINATION
187 */
188 KLDRSTATE_GOOD,
[2840]189
[2836]190 /** Pending termination, reference count is 0.
[2840]191 * While the module is in this state the loader is in reentrant mode.
[2842]192 * Prerequisite modules are dropped when a module enters this state.
[2840]193 *
[2836]194 * Prev state: GOOD
195 * Next state: TERMINATING, GOOD
196 */
197 KLDRSTATE_PENDING_TERMINATION,
[2840]198
[2836]199 /** Terminating, reference count is still 0.
[2840]200 * While the module is in this state the loader is in reentrant mode.
201 *
[2836]202 * Prev state: PENDING_TERMINATION
203 * Next state: PENDING_GC
204 */
205 KLDRSTATE_TERMINATING,
[2840]206
[2836]207 /** Pending garbage collection.
[2842]208 * Prerequisite modules are dropped when a module enters this state (if not done already).
[2840]209 *
210 * Prev state: TERMINATING, PENDING_INITIALIZATION, INITIALIZATION_FAILED
[2837]211 * Next state: GC, RELOADED
[2836]212 */
213 KLDRSTATE_PENDING_GC,
[2840]214
[2836]215 /** Being garbage collected.
[2840]216 *
217 * Prev state: PENDING_GC, INITIALIZATION_FAILED
[2837]218 * Next state: PENDING_DESTROY, DESTROYED
[2836]219 */
220 KLDRSTATE_GC,
[2840]221
[2837]222 /** The module has be unlinked, but there are still stack references to it.
[2840]223 *
224 * Prev state: GC, FIXED_UP, LOADED_PREREQUISITES, MAPPED, OPEN
[2837]225 * Next state: DESTROYED
[2836]226 */
[2837]227 KLDRSTATE_PENDING_DESTROY,
[2840]228
[2845]229 /** The module has been destroyed but not freed yet.
[2840]230 *
[2845]231 * This happens when a module ends up being destroyed when cRefs > 0. The
232 * module structure will be freed when cRefs reaches 0.
233 *
[2837]234 * Prev state: GC, PENDING_DESTROY
[2836]235 */
236 KLDRSTATE_DESTROYED,
[2840]237
[2825]238 /** The end of valid states (exclusive) */
[2836]239 KLDRSTATE_END = KLDRSTATE_DESTROYED,
[2825]240 /** The usual 32-bit blowup. */
241 KLDRSTATE_32BIT_HACK = 0x7fffffff
242} KLDRSTATE;
243
244
245/**
246 * Dynamic loader module.
247 */
[2833]248typedef struct KLDRDYLDMOD
[2825]249{
[2833]250 /** Magic number. */
[3567]251 KU32 u32MagicHead;
[2833]252 /** The module state. */
253 KLDRSTATE enmState;
[2825]254 /** The module. */
255 PKLDRMOD pMod;
[2836]256 /** The module handle. */
257 HKLDRMOD hMod;
[2837]258 /** The total number of references. */
[3567]259 KU32 cRefs;
[2837]260 /** The number of dependency references. */
[3567]261 KU32 cDepRefs;
[2837]262 /** The number of dynamic load references. */
[3567]263 KU32 cDynRefs;
[2836]264 /** Set if this is the executable module.
265 * When clear, the module is a shared object or relocatable object. */
[3567]266 KU32 fExecutable : 1;
[2825]267 /** Global DLL (set) or specific DLL (clear). */
[3567]268 KU32 fGlobalOrSpecific : 1;
[2836]269 /** Whether the module contains bindable symbols in the global unix namespace. */
[3567]270 KU32 fBindable : 1;
[2842]271 /** Set if linked into the global init list. */
[3567]272 KU32 fInitList : 1;
[2842]273 /** Already loaded or checked prerequisites.
274 * This flag is used when loading prerequisites, when set it means that
275 * this module is already seen and shouldn't be processed again. */
[3567]276 KU32 fAlreadySeen : 1;
[2845]277 /** Set if the module is currently mapped.
278 * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */
[3567]279 KU32 fMapped : 1;
[2846]280 /** Set if TLS allocation has been done. (part of the mapping). */
[3567]281 KU32 fAllocatedTLS : 1;
[2825]282 /** Reserved for future use. */
[3567]283 KU32 f25Reserved : 25;
[2836]284 /** The load list linkage. */
285 struct
286 {
287 /** The next module in the list. */
288 struct KLDRDYLDMOD *pNext;
289 /** The prev module in the list. */
290 struct KLDRDYLDMOD *pPrev;
291 } Load;
[2842]292 /** The initialization and termination list linkage.
293 * If non-recursive initialization is used, the module will be pushed on
294 * the initialization list.
[2840]295 * A module will be linked into the termination list upon a successful
296 * return from module initialization. */
[2836]297 struct
298 {
299 /** The next module in the list. */
300 struct KLDRDYLDMOD *pNext;
301 /** The prev module in the list. */
302 struct KLDRDYLDMOD *pPrev;
[2842]303 } InitTerm;
[2836]304 /** The bind order list linkage.
305 * The module is not in this list when fBindable is clear. */
306 struct
307 {
308 /** The next module in the list. */
309 struct KLDRDYLDMOD *pNext;
310 /** The prev module in the list. */
311 struct KLDRDYLDMOD *pPrev;
312 } Bind;
[2842]313
314 /** The number of prerequisite modules in the prereq array. */
[3567]315 KU32 cPrereqs;
[2842]316 /** Pointer to an array of prerequisite module pointers.
317 * This array is only filled when in the states starting with
318 * KLDRSTATE_LOADED_PREREQUISITES thru KLDRSTATE_GOOD.
319 */
320 struct KLDRDYLDMOD **papPrereqs;
321
[2833]322 /** Magic number. */
[3567]323 KU32 u32MagicTail;
[2833]324} KLDRDYLDMOD, *PKLDRDYLDMOD, **PPKLDRDYLDMOD;
[2825]325
[2836]326/** KLDRDYLDMOD magic value. (Fuyumi Soryo) */
[2833]327#define KLDRDYMOD_MAGIC 0x19590106
[2825]328
[2833]329/** Return / crash validation of a module handle argument. */
330#define KLDRDYLD_VALIDATE_HKLDRMOD(hMod) \
331 do { \
332 if ( (hMod) == NIL_HKLDRMOD \
333 || (hMod)->u32MagicHead != KLDRDYMOD_MAGIC \
334 || (hMod)->u32MagicTail != KLDRDYMOD_MAGIC) \
335 { \
[3579]336 return KERR_INVALID_HANDLE; \
[2833]337 } \
338 } while (0)
339
340
[2875]341int kldrInit(void);
342void kldrTerm(void);
343
344int kldrDyldInit(void);
345void kldrDyldTerm(void);
346
347void kldrDyldDoLoadExe(PKLDRDYLDMOD pExe);
348int kldrDyldFailure(int rc, const char *pszFormat, ...);
349
[3567]350int kldrDyldOSStartExe(KUPTR uMainEntrypoint, void *pvStack, KSIZE cbStack);
351void *kldrDyldOSAllocStack(KSIZE cb);
[2875]352
353int kldrDyldFindInit(void);
[2843]354int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
[2835]355 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
[2843]356int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
[2835]357 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
358
[2847]359int kldrDyldGetPrerequisite(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
360 unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod);
[2835]361
[2847]362
[3578]363int kldrDyldModCreate(PKRDR pRdr, KU32 fFlags, PPKLDRDYLDMOD ppMod);
[2845]364void kldrDyldModDestroy(PKLDRDYLDMOD pMod);
365void kldrDyldModAddRef(PKLDRDYLDMOD pMod);
[2837]366void kldrDyldModDeref(PKLDRDYLDMOD pMod);
[2845]367void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
[2837]368void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
[2835]369int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
370int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
[2845]371void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
372void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
373void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep);
374void kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
[2835]375int kldrDyldModMap(PKLDRDYLDMOD pMod);
376int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
[2843]377int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
[2837]378 KLDRDYLDSEARCH enmSearch, unsigned fFlags);
379int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod);
380void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod);
[2835]381int kldrDyldModFixup(PKLDRDYLDMOD pMod);
382int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
[2837]383void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
384int kldrDyldModReload(PKLDRDYLDMOD pMod);
[2836]385int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
[2846]386void kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
[3567]387int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, KSIZE *pcbStack);
[2835]388int kldrDyldModStartExe(PKLDRDYLDMOD pMod);
389
[3567]390int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, KSIZE cchName);
391int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, KSIZE cchFilename);
392int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, KU32 uSymbolOrdinal, const char *pszSymbolName, KUPTR *puValue, KU32 *pfKind);
[2835]393
[2869]394
[2842]395/** Pointer to the head module (the executable).
396 * (This is exported, so no prefix.) */
397extern PKLDRDYLDMOD kLdrDyldHead;
398/** Pointer to the tail module.
399 * (This is exported, so no prefix.) */
400extern PKLDRDYLDMOD kLdrDyldTail;
[2845]401/** Pointer to the head module of the initialization list.
402 * The outermost load call will pop elements from this list in LIFO order (i.e.
403 * from the tail). The list is only used during non-recursive initialization
404 * and may therefore share the pNext/pPrev members with the termination list
405 * since we don't push a module onto the termination list untill it has been
406 * successfully initialized. */
407extern PKLDRDYLDMOD g_pkLdrDyldInitHead;
408/** Pointer to the tail module of the initalization list. */
409extern PKLDRDYLDMOD g_pkLdrDyldInitTail;
[2836]410/** Pointer to the head module of the termination order list. */
411extern PKLDRDYLDMOD g_pkLdrDyldTermHead;
412/** Pointer to the tail module of the termination order list. */
413extern PKLDRDYLDMOD g_pkLdrDyldTermTail;
414/** Pointer to the head module of the bind order list.
415 * The modules in this list makes up the global namespace used when binding symbol unix fashion. */
416extern PKLDRDYLDMOD g_pkLdrDyldBindHead;
417/** Pointer to the tail module of the bind order list. */
418extern PKLDRDYLDMOD g_pkLdrDyldBindTail;
419
[2846]420/** Indicates that the other MainStack globals have been filled in. */
421extern unsigned g_fkLdrDyldDoneMainStack;
422/** Whether the stack was allocated seperatly or was part of the executable. */
423extern unsigned g_fkLdrDyldMainStackAllocated;
424/** Pointer to the main stack object. */
425extern void *g_pvkLdrDyldMainStack;
426/** The size of the main stack object. */
[3567]427extern KSIZE g_cbkLdrDyldMainStack;
[2846]428
[2835]429/** The global error buffer. */
430extern char g_szkLdrDyldError[1024];
[2825]431
[2875]432extern char kLdrDyldExePath[8192];
433extern char kLdrDyldLibraryPath[8192];
[2867]434extern char kLdrDyldDefPrefix[16];
435extern char kLdrDyldDefSuffix[16];
[2833]436
[2875]437extern int g_fBootstrapping;
[2836]438
[2875]439
[3576]440/** @name The Loader semaphore
441 * @{ */
442int kLdrDyldSemInit(void);
443void kLdrDyldSemTerm(void);
444int kLdrDyldSemRequest(void);
445void kLdrDyldSemRelease(void);
446/** @} */
447
448
[2858]449/** @name Module interpreter method tables
450 * @{ */
[2879]451extern KLDRMODOPS g_kLdrModLXOps;
[2954]452extern KLDRMODOPS g_kLdrModMachOOps;
[2877]453extern KLDRMODOPS g_kLdrModNativeOps;
[2954]454extern KLDRMODOPS g_kLdrModPEOps;
[2825]455/** @} */
[2858]456
[3573]457
[2858]458/** @} */
[2825]459#ifdef __cplusplus
460}
461#endif
462
463#endif
Note: See TracBrowser for help on using the repository browser.