source: trunk/kStuff/kLdr/kLdrInternal.h@ 3578

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

kLdrRdr cleanup.

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