VirtualBox

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

Last change on this file since 75 was 29, checked in by bird, 15 years ago

Finally got around execute the switch to the MIT license.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette