Convert to unix line endings.
[wincetools.git] / loader / README
1 HiMemCE
2 =======
3
4 HiMemCE is a high memory loader for Windows CE.  It softens the 32 MB
5 process limit by allowing the EXE to load in the large file area
6 reserved for file mappings.  This way, the EXE can be as large as free
7 unfragmented virtual memory in that region, or free physical memory
8 (whatever is smaller).  By linking libraries statically to the
9 program, problems with too large or too many DLLs can be avoided.
10
11 The usage of the loader is very simple.
12
13 1. First, the program to be loaded has to be linked with the option
14 /FIXED:NO (in MSVS, this setting can be found under Properties,
15 Configuration Properties, Linker, Advanced, Fixed Base Address, choose
16 "Generate a relocation section").  Here is a CMake example:
17
18 SET_TARGET_PROPERTIES(foo PROPERTIES LINK_FLAGS " /FIXED:NO")
19
20 2. Install the program "foo" under foo-real.exe, and copy the loader's
21 himemce.exe side-by-side to it as foo.exe.  Then the loader (as
22 foo.exe) transparently proxies all start ups of the foo program.  It
23 will automatically look for foo-real.exe and load that into high
24 memory, continueing execution there.
25
26 Contained in this package is a himemce-real.exe, that serves as an
27 example/test program.  In the special case of "himemce.exe", verbose
28 output is on by default.
29
30 How it works
31 ------------
32
33 HiMemCE allocates a virtual memory region with VirtulAlloc
34 (MEM_RESERVE, PAGE_NOACCESS) large enough to cover the whole image
35 (SizeOfImage).  If that is larger than 2 MB, Windows CE automatically
36 uses the large memory area for the allocation.  Then HiMemCE loads the
37 sections into the designated place.  This immediately commits all
38 pages[1].
39
40 The image is then relocated (this is why /FIXED:NO is required).
41 Although an attempt is made to honor the preferred base address, once
42 all pages are copied, there is no big advantage to avoiding
43 relocating, so setting a preferred base address (without a way to also
44 use MapViewOfFile) is currently not recommended.
45
46 The next step is to resolve imports.  For this, the import section is
47 processed, and for each DLL listed there, we use LoadLibrary to pass
48 off the load request to the system loader.  We don't do any DLL
49 loading ourselves[1].  For every DLL loaded this way, we resolve
50 references by GetProcAddress, which supports lookup by name as well as
51 by ordinal.
52
53 Finally, pass execution to the loaded program.  Because the entry
54 point is a normal C function, we can reuse the current thread and all
55 its state.  The first argument is the module handle of the started
56 image.  As we constructed this ourselve, there is no valid module
57 handle for it, so we reuse the module handle of the loader as well.[3]
58 Because this affects argv[0], we give the loader the same name as the
59 executable we want to load (and rename the loaded executable to
60 foo-real.exe).
61
62
63 Footnotes
64
65 [1] This is a pessimization, but because only MapViewOfFile and
66 not MapVieOfFileEx is available, mapping in the read only sections of
67 the file directly is difficult, and when relocating the image, many
68 pages end up being dirty anyway.  See Optimization options.
69
70 [2] This avoids the complexity of sharing DLLs across applications as
71 well as walking the dependency chain.  A more complex loader, that can
72 also load DLLs and thus effectively extend the slot 61 and 60 by
73 further slots is feasible, but quite a bit of work.  The only benefit
74 over static linking this has is code sharing, but if we are only
75 talking about a couple of MB, then code duplication across a small
76 number of programs is not a big problem.  And the number of processes
77 in Windows CE is necessarily small!
78
79 [3] Note that this could confuse some programs that do deep
80 introspection and want to manually load custom sections or do other
81 magic.
82
83
84 TODO
85 ----
86
87 * Switch off verbose output for non-himemce.exe named copies of
88 the loader (but allow a switch --himemce-log to switch it back on).
89
90 * Show load errors in a diagnostic window for the user.
91
92 * Handle DISCARDABLE flag?
93
94
95 Optimization options
96 --------------------
97
98 * Physical memory pressure can be relieved by trying to use
99   MapViewOfFile opportunistically (create relocated image, save to
100   temporary file, map it).
101
102 * Handle DISCARDABLE sections (if any).
103
104
105 How it works (DLL version)
106 --------------------------
107
108 The preloader (himemce-pre) should be run when the device starts up,
109 and must be run before any program is loaded high with himemce.  It
110 preloads the DLLs that should be loaded high.
111
112 Note that these DLLs are unknown to the system and can only be used by
113 himemce.  This means that any program resp. DLL that depends on a high
114 loaded DLL must be loaded by himemce resp. himemce-pre as well.
115 Further note that himemce can not generate stub code for ARM, so ARM
116 DLLs such as gpgme, gpg-error etc can not be preloaded and should be
117 exempted.
118
119 The himemce-pre program looks for all .dll files in its directory and
120 preloads them, unless they are in the blacklist (FIXME: implement and
121 document blacklist mechanism).
122
123 The preloader performs the following steps:
124
125 1. For all preloaded DLLs, map them to high memory without resolving
126 their references.
127
128 2. For all preloaded DLLs, identify sections that are writable and
129 thus need to be allocated per process.  For these DLLs, reserve some
130 memory in a continuous range at the bottom of the process address
131 space (_HIMEMCE_MAP_LOW_BASE == 2 MB).  Also rewrite all base
132 relocations that point into these sections to point to the low memory
133 instead.
134
135 3. For all preloaded DLLs, import their dependencies.  For DLLs
136 managed by himemce-pre, this will resolve to the entry points in the
137 high loaded DLLs (adjusting entry points into writable section to
138 their low memory variant).  For system managed DLLs, use the normal
139 LoadLibrary/GetProcAddressA mechanism.
140
141 4. Map the data structures describing all this to a shared memory
142 region named HIMEMCE_MAP_NAME == L"himemcemap".  This can be accessed
143 by himemce.
144
145 5. Sleep forever.  It is important that this process does not exit,
146 because if this was the last user of HIMEMCE_MAP_NAME, the preloaded
147 libraries will be deallocated.
148
149 These steps must be executed for programs that run with preloaded
150 DLLs (done by himemce):
151
152 1. At startup, reserve the low memory sections.
153
154 2. For each preloaded DLL, copy its writable sections to the process
155 memory reserved in step 1.
156
157 3. For each system DLL that is used by preloaded DLLs, call
158 LoadLibrary to copy their writable sections into the process memory.
159
160 4. For each preloaded DLL, call DllMain (their entry point).
161
162 [5. TODO: Load a himemce.dll library that calls these DllMain's for
163 each Thread in its DllMain.]
164
165
166  Copyright 2010 g10 Code GmbH
167
168  This file is free software; as a special exception the author gives
169  unlimited permission to copy and/or distribute it, with or without
170  modifications, as long as this notice is preserved.
171
172  This file is distributed in the hope that it will be useful, but
173  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
174  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.