source: trunk/kLdr/kLdrInternal.h@ 2945

Last change on this file since 2945 was 2944, checked in by bird, 19 years ago

split up kLdrHlp.c and kLdr.c to make it more flexible (like using the module interpreters without the dynamic loader bit and similar).

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