source: trunk/kLdr/kLdrInternal.h@ 3003

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

implemented kldrModMachOPreParseLoadCommands

  • Property svn:keywords set to Id
File size: 16.0 KB
Line 
1/* $Id: kLdrInternal.h 2954 2007-02-07 04:42:32Z 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/** 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)
75/** @} */
76
77/** @defgroup grp_kLdrInternal Internals
78 * @internal
79 * @{
80 */
81
82
83/** Native file provider operations. */
84extern const KLDRRDROPS g_kLdrRdrFileOps;
85
86
87/**
88 * The state of a dynamic loader module.
89 * @image html KLDRSTATE.gif "The state diagram"
90 */
91typedef enum KLDRSTATE
92{
93 /** The usual invalid 0 enum. */
94 KLDRSTATE_INVALID = 0,
95
96 /** The module has just been opened and linked into the load list.
97 *
98 * Prev state: -
99 * Next state: MAPPED, PENDING_DESTROY
100 */
101 KLDRSTATE_OPEN,
102
103 /** The module segments has been mapped into the process memory.
104 *
105 * Prev state: OPEN
106 * Next state: LOADED_PREREQUISITES, PENDING_DESTROY
107 */
108 KLDRSTATE_MAPPED,
109 /** The module has been reloaded and needs to be fixed up again.
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 *
117 * Prev state: PENDING_GC
118 * Next state: RELOADED_LOADED_PREREQUISITES, PENDING_GC
119 */
120 KLDRSTATE_RELOADED,
121
122 /** The immediate prerequisites have been loaded.
123 *
124 * Prev state: MAPPED
125 * Next state: FIXED_UP, PENDING_DESTROY
126 */
127 KLDRSTATE_LOADED_PREREQUISITES,
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
135 /** Fixups has been applied.
136 *
137 * Prev state: LOADED_PREREQUISITES
138 * Next state: PENDING_INITIALIZATION, PENDING_DESTROY
139 */
140 KLDRSTATE_FIXED_UP,
141 /** Fixups has been applied.
142 *
143 * Prev state: RELOADED_LOADED_PREREQUISITES
144 * Next state: PENDING_INITIALIZATION, PENDING_GC
145 */
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 */
154 KLDRSTATE_PENDING_INITIALIZATION,
155
156 /** Initializing.
157 * While the module is in this state the loader is in reentrant mode.
158 *
159 * Prev state: PENDING_INITIALIZATION
160 * Next state: GOOD, PENDING_GC
161 */
162 KLDRSTATE_INITIALIZING,
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
177 /** The module has been successfully loaded and initialized.
178 * While the module is in this state the loader can be in reentrant
179 * or 'unused' mode.
180 *
181 * Prev state: INITIALIZING
182 * Next state: PENDING_TERMINATION
183 */
184 KLDRSTATE_GOOD,
185
186 /** Pending termination, reference count is 0.
187 * While the module is in this state the loader is in reentrant mode.
188 * Prerequisite modules are dropped when a module enters this state.
189 *
190 * Prev state: GOOD
191 * Next state: TERMINATING, GOOD
192 */
193 KLDRSTATE_PENDING_TERMINATION,
194
195 /** Terminating, reference count is still 0.
196 * While the module is in this state the loader is in reentrant mode.
197 *
198 * Prev state: PENDING_TERMINATION
199 * Next state: PENDING_GC
200 */
201 KLDRSTATE_TERMINATING,
202
203 /** Pending garbage collection.
204 * Prerequisite modules are dropped when a module enters this state (if not done already).
205 *
206 * Prev state: TERMINATING, PENDING_INITIALIZATION, INITIALIZATION_FAILED
207 * Next state: GC, RELOADED
208 */
209 KLDRSTATE_PENDING_GC,
210
211 /** Being garbage collected.
212 *
213 * Prev state: PENDING_GC, INITIALIZATION_FAILED
214 * Next state: PENDING_DESTROY, DESTROYED
215 */
216 KLDRSTATE_GC,
217
218 /** The module has be unlinked, but there are still stack references to it.
219 *
220 * Prev state: GC, FIXED_UP, LOADED_PREREQUISITES, MAPPED, OPEN
221 * Next state: DESTROYED
222 */
223 KLDRSTATE_PENDING_DESTROY,
224
225 /** The module has been destroyed but not freed yet.
226 *
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 *
230 * Prev state: GC, PENDING_DESTROY
231 */
232 KLDRSTATE_DESTROYED,
233
234 /** The end of valid states (exclusive) */
235 KLDRSTATE_END = KLDRSTATE_DESTROYED,
236 /** The usual 32-bit blowup. */
237 KLDRSTATE_32BIT_HACK = 0x7fffffff
238} KLDRSTATE;
239
240
241/**
242 * Dynamic loader module.
243 */
244typedef struct KLDRDYLDMOD
245{
246 /** Magic number. */
247 uint32_t u32MagicHead;
248 /** The module state. */
249 KLDRSTATE enmState;
250 /** The module. */
251 PKLDRMOD pMod;
252 /** The module handle. */
253 HKLDRMOD hMod;
254 /** The total number of references. */
255 uint32_t cRefs;
256 /** The number of dependency references. */
257 uint32_t cDepRefs;
258 /** The number of dynamic load references. */
259 uint32_t cDynRefs;
260 /** Set if this is the executable module.
261 * When clear, the module is a shared object or relocatable object. */
262 uint32_t fExecutable : 1;
263 /** Global DLL (set) or specific DLL (clear). */
264 uint32_t fGlobalOrSpecific : 1;
265 /** Whether the module contains bindable symbols in the global unix namespace. */
266 uint32_t fBindable : 1;
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;
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;
276 /** Set if TLS allocation has been done. (part of the mapping). */
277 uint32_t fAllocatedTLS : 1;
278 /** Reserved for future use. */
279 uint32_t f25Reserved : 25;
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;
288 /** The initialization and termination list linkage.
289 * If non-recursive initialization is used, the module will be pushed on
290 * the initialization list.
291 * A module will be linked into the termination list upon a successful
292 * return from module initialization. */
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;
299 } InitTerm;
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;
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
318 /** Magic number. */
319 uint32_t u32MagicTail;
320} KLDRDYLDMOD, *PKLDRDYLDMOD, **PPKLDRDYLDMOD;
321
322/** KLDRDYLDMOD magic value. (Fuyumi Soryo) */
323#define KLDRDYMOD_MAGIC 0x19590106
324
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
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);
350int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
351 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
352int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
353 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod);
354
355int kldrDyldGetPrerequisite(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch,
356 unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod);
357
358
359int kldrDyldModCreate(PKLDRRDR pRdr, uint32_t fFlags, PPKLDRDYLDMOD ppMod);
360void kldrDyldModDestroy(PKLDRDYLDMOD pMod);
361void kldrDyldModAddRef(PKLDRDYLDMOD pMod);
362void kldrDyldModDeref(PKLDRDYLDMOD pMod);
363void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
364void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
365int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
366int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
367void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
368void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
369void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep);
370void kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
371int kldrDyldModMap(PKLDRDYLDMOD pMod);
372int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
373int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
374 KLDRDYLDSEARCH enmSearch, unsigned fFlags);
375int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod);
376void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod);
377int kldrDyldModFixup(PKLDRDYLDMOD pMod);
378int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
379void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
380int kldrDyldModReload(PKLDRDYLDMOD pMod);
381int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
382void kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
383int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack);
384int kldrDyldModStartExe(PKLDRDYLDMOD pMod);
385
386int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName);
387int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename);
388int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *puValue, uint32_t *pfKind);
389
390
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;
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;
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
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
425/** The global error buffer. */
426extern char g_szkLdrDyldError[1024];
427
428extern char kLdrDyldExePath[8192];
429extern char kLdrDyldLibraryPath[8192];
430extern char kLdrDyldDefPrefix[16];
431extern char kLdrDyldDefSuffix[16];
432
433extern int g_fBootstrapping;
434
435
436/** @name Module interpreter method tables
437 * @{ */
438extern KLDRMODOPS g_kLdrModLXOps;
439extern KLDRMODOPS g_kLdrModMachOOps;
440extern KLDRMODOPS g_kLdrModNativeOps;
441extern KLDRMODOPS g_kLdrModPEOps;
442/** @} */
443
444/** @} */
445#ifdef __cplusplus
446}
447#endif
448
449#endif
Note: See TracBrowser for help on using the repository browser.