First version of DLL preloader.
[wincetools.git] / loader / README
index bc07ce1..847af0c 100644 (file)
-HiMemCE
-=======
-
-HiMemCE is a high memory loader for Windows CE.  It softens the 32 MB
-process limit by allowing the EXE to load in the large file area
-reserved for file mappings.  This way, the EXE can be as large as free
-unfragmented virtual memory in that region, or free physical memory
-(whatever is smaller).  By linking libraries statically to the
-program, problems with too large or too many DLLs can be avoided.
-
-The usage of the loader is very simple.
-
-1. First, the program to be loaded has to be linked with the option
-/FIXED:NO (in MSVS, this setting can be found under Properties,
-Configuration Properties, Linker, Advanced, Fixed Base Address, choose
-"Generate a relocation section").  Here is a CMake example:
-
-SET_TARGET_PROPERTIES(foo PROPERTIES LINK_FLAGS " /FIXED:NO")
-
-2. Install the program "foo" under foo-real.exe, and copy the loader's
-himemce.exe side-by-side to it as foo.exe.  Then the loader (as
-foo.exe) transparently proxies all start ups of the foo program.  It
-will automatically look for foo-real.exe and load that into high
-memory, continueing execution there.
-
-Contained in this package is a himemce-real.exe, that serves as an
-example/test program.  In the special case of "himemce.exe", verbose
-output is on by default.
-
-How it works
-------------
-
-HiMemCE allocates a virtual memory region with VirtulAlloc
-(MEM_RESERVE, PAGE_NOACCESS) large enough to cover the whole image
-(SizeOfImage).  If that is larger than 2 MB, Windows CE automatically
-uses the large memory area for the allocation.  Then HiMemCE loads the
-sections into the designated place.  This immediately commits all
-pages[1].
-
-The image is then relocated (this is why /FIXED:NO is required).
-Although an attempt is made to honor the preferred base address, once
-all pages are copied, there is no big advantage to avoiding
-relocating, so setting a preferred base address (without a way to also
-use MapViewOfFile) is currently not recommended.
-
-The next step is to resolve imports.  For this, the import section is
-processed, and for each DLL listed there, we use LoadLibrary to pass
-off the load request to the system loader.  We don't do any DLL
-loading ourselves[1].  For every DLL loaded this way, we resolve
-references by GetProcAddress, which supports lookup by name as well as
-by ordinal.
-
-Finally, pass execution to the loaded program.  Because the entry
-point is a normal C function, we can reuse the current thread and all
-its state.  The first argument is the module handle of the started
-image.  As we constructed this ourselve, there is no valid module
-handle for it, so we reuse the module handle of the loader as well.[3]
-Because this affects argv[0], we give the loader the same name as the
-executable we want to load (and rename the loaded executable to
-foo-real.exe).
-
-
-Footnotes
-
-[1] This is a pessimization, but because only MapViewOfFile and
-not MapVieOfFileEx is available, mapping in the read only sections of
-the file directly is difficult, and when relocating the image, many
-pages end up being dirty anyway.  See Optimization options.
-
-[2] This avoids the complexity of sharing DLLs across applications as
-well as walking the dependency chain.  A more complex loader, that can
-also load DLLs and thus effectively extend the slot 61 and 60 by
-further slots is feasible, but quite a bit of work.  The only benefit
-over static linking this has is code sharing, but if we are only
-talking about a couple of MB, then code duplication across a small
-number of programs is not a big problem.  And the number of processes
-in Windows CE is necessarily small!
-
-[3] Note that this could confuse some programs that do deep
-introspection and want to manually load custom sections or do other
-magic.
-
-
-TODO
-----
-
-* Switch off verbose output for non-himemce.exe named copies of
-the loader (but allow a switch --himemce-log to switch it back on).
-
-* Show load errors in a diagnostic window for the user.
-
-
-Optimization options
---------------------
-
-* Physical memory pressure can be relieved by trying to use
-  MapViewOfFile opportunistically (create relocated image, save to
-  temporary file, map it).
-
-
- Copyright 2010 g10 Code GmbH
-
- This file is free software; as a special exception the author gives
- unlimited permission to copy and/or distribute it, with or without
- modifications, as long as this notice is preserved.
-
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+HiMemCE\r
+=======\r
+\r
+HiMemCE is a high memory loader for Windows CE.  It softens the 32 MB\r
+process limit by allowing the EXE to load in the large file area\r
+reserved for file mappings.  This way, the EXE can be as large as free\r
+unfragmented virtual memory in that region, or free physical memory\r
+(whatever is smaller).  By linking libraries statically to the\r
+program, problems with too large or too many DLLs can be avoided.\r
+\r
+The usage of the loader is very simple.\r
+\r
+1. First, the program to be loaded has to be linked with the option\r
+/FIXED:NO (in MSVS, this setting can be found under Properties,\r
+Configuration Properties, Linker, Advanced, Fixed Base Address, choose\r
+"Generate a relocation section").  Here is a CMake example:\r
+\r
+SET_TARGET_PROPERTIES(foo PROPERTIES LINK_FLAGS " /FIXED:NO")\r
+\r
+2. Install the program "foo" under foo-real.exe, and copy the loader's\r
+himemce.exe side-by-side to it as foo.exe.  Then the loader (as\r
+foo.exe) transparently proxies all start ups of the foo program.  It\r
+will automatically look for foo-real.exe and load that into high\r
+memory, continueing execution there.\r
+\r
+Contained in this package is a himemce-real.exe, that serves as an\r
+example/test program.  In the special case of "himemce.exe", verbose\r
+output is on by default.\r
+\r
+How it works\r
+------------\r
+\r
+HiMemCE allocates a virtual memory region with VirtulAlloc\r
+(MEM_RESERVE, PAGE_NOACCESS) large enough to cover the whole image\r
+(SizeOfImage).  If that is larger than 2 MB, Windows CE automatically\r
+uses the large memory area for the allocation.  Then HiMemCE loads the\r
+sections into the designated place.  This immediately commits all\r
+pages[1].\r
+\r
+The image is then relocated (this is why /FIXED:NO is required).\r
+Although an attempt is made to honor the preferred base address, once\r
+all pages are copied, there is no big advantage to avoiding\r
+relocating, so setting a preferred base address (without a way to also\r
+use MapViewOfFile) is currently not recommended.\r
+\r
+The next step is to resolve imports.  For this, the import section is\r
+processed, and for each DLL listed there, we use LoadLibrary to pass\r
+off the load request to the system loader.  We don't do any DLL\r
+loading ourselves[1].  For every DLL loaded this way, we resolve\r
+references by GetProcAddress, which supports lookup by name as well as\r
+by ordinal.\r
+\r
+Finally, pass execution to the loaded program.  Because the entry\r
+point is a normal C function, we can reuse the current thread and all\r
+its state.  The first argument is the module handle of the started\r
+image.  As we constructed this ourselve, there is no valid module\r
+handle for it, so we reuse the module handle of the loader as well.[3]\r
+Because this affects argv[0], we give the loader the same name as the\r
+executable we want to load (and rename the loaded executable to\r
+foo-real.exe).\r
+\r
+\r
+Footnotes\r
+\r
+[1] This is a pessimization, but because only MapViewOfFile and\r
+not MapVieOfFileEx is available, mapping in the read only sections of\r
+the file directly is difficult, and when relocating the image, many\r
+pages end up being dirty anyway.  See Optimization options.\r
+\r
+[2] This avoids the complexity of sharing DLLs across applications as\r
+well as walking the dependency chain.  A more complex loader, that can\r
+also load DLLs and thus effectively extend the slot 61 and 60 by\r
+further slots is feasible, but quite a bit of work.  The only benefit\r
+over static linking this has is code sharing, but if we are only\r
+talking about a couple of MB, then code duplication across a small\r
+number of programs is not a big problem.  And the number of processes\r
+in Windows CE is necessarily small!\r
+\r
+[3] Note that this could confuse some programs that do deep\r
+introspection and want to manually load custom sections or do other\r
+magic.\r
+\r
+\r
+TODO\r
+----\r
+\r
+* Switch off verbose output for non-himemce.exe named copies of\r
+the loader (but allow a switch --himemce-log to switch it back on).\r
+\r
+* Show load errors in a diagnostic window for the user.\r
+\r
+* Handle DISCARDABLE flag?\r
+\r
+\r
+Optimization options\r
+--------------------\r
+\r
+* Physical memory pressure can be relieved by trying to use\r
+  MapViewOfFile opportunistically (create relocated image, save to\r
+  temporary file, map it).\r
+\r
+* Handle DISCARDABLE sections (if any).\r
+\r
+\r
+How it works (DLL version)\r
+--------------------------\r
+\r
+The preloader (himemce-pre) should be run when the device starts up,\r
+and must be run before any program is loaded high with himemce.  It\r
+preloads the DLLs that should be loaded high.\r
+\r
+Note that these DLLs are unknown to the system and can only be used by\r
+himemce.  This means that any program resp. DLL that depends on a high\r
+loaded DLL must be loaded by himemce resp. himemce-pre as well.\r
+Further note that himemce can not generate stub code for ARM, so ARM\r
+DLLs such as gpgme, gpg-error etc can not be preloaded and should be\r
+exempted.\r
+\r
+The himemce-pre program looks for all .dll files in its directory and\r
+preloads them, unless they are in the blacklist (FIXME: implement and\r
+document blacklist mechanism).\r
+\r
+The preloader performs the following steps:\r
+\r
+1. For all preloaded DLLs, map them to high memory without resolving\r
+their references.\r
+\r
+2. For all preloaded DLLs, identify sections that are writable and\r
+thus need to be allocated per process.  For these DLLs, reserve some\r
+memory in a continuous range at the bottom of the process address\r
+space (_HIMEMCE_MAP_LOW_BASE == 2 MB).  Also rewrite all base\r
+relocations that point into these sections to point to the low memory\r
+instead.\r
+\r
+3. For all preloaded DLLs, import their dependencies.  For DLLs\r
+managed by himemce-pre, this will resolve to the entry points in the\r
+high loaded DLLs (adjusting entry points into writable section to\r
+their low memory variant).  For system managed DLLs, use the normal\r
+LoadLibrary/GetProcAddressA mechanism.\r
+\r
+4. Map the data structures describing all this to a shared memory\r
+region named HIMEMCE_MAP_NAME == L"himemcemap".  This can be accessed\r
+by himemce.\r
+\r
+5. Sleep forever.  It is important that this process does not exit,\r
+because if this was the last user of HIMEMCE_MAP_NAME, the preloaded\r
+libraries will be deallocated.\r
+\r
+These steps must be executed for programs that run with preloaded\r
+DLLs (done by himemce):\r
+\r
+1. At startup, reserve the low memory sections.\r
+\r
+2. For each preloaded DLL, copy its writable sections to the process\r
+memory reserved in step 1.\r
+\r
+3. For each system DLL that is used by preloaded DLLs, call\r
+LoadLibrary to copy their writable sections into the process memory.\r
+\r
+4. For each preloaded DLL, call DllMain (their entry point).\r
+\r
+[5. TODO: Load a himemce.dll library that calls these DllMain's for\r
+each Thread in its DllMain.]\r
+\r
+\r
+ Copyright 2010 g10 Code GmbH\r
+\r
+ This file is free software; as a special exception the author gives\r
+ unlimited permission to copy and/or distribute it, with or without\r
+ modifications, as long as this notice is preserved.\r
+\r
+ This file is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the\r
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r