source: trunk/kLdr/kLdrInternal.h@ 3232

Last change on this file since 3232 was 2954, checked in by bird, 19 years ago

implemented kldrModMachOPreParseLoadCommands

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