summaryrefslogtreecommitdiff
path: root/src/pal/src/loader/module.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/loader/module.cpp')
-rw-r--r--src/pal/src/loader/module.cpp188
1 files changed, 184 insertions, 4 deletions
diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp
index 74156fd..78069b8 100644
--- a/src/pal/src/loader/module.cpp
+++ b/src/pal/src/loader/module.cpp
@@ -85,8 +85,98 @@ using namespace CorUnix;
#define LIBC_NAME_WITHOUT_EXTENSION "libc"
+struct PreloadedImageListNode
+{
+ PreloadedImageListNode *next;
+ LPSTR szPath;
+ LPWSTR wszPath;
+ LPVOID lpMappedImage;
+ SIZE_T virtualSize;
+ bool isLoaded;
+};
+
+class PreloadedImageList
+{
+ PreloadedImageListNode *m_start;
+
+public:
+
+ PreloadedImageList()
+ : m_start(NULL) {}
+
+ void addNew(LPCSTR szPath, LPVOID lpImage, SIZE_T size)
+ {
+ PreloadedImageListNode *node = (PreloadedImageListNode *) InternalMalloc(sizeof(PreloadedImageListNode));
+ node->szPath = (LPSTR) InternalMalloc(strlen(szPath) + 1);
+ strcpy(node->szPath, szPath);
+ node->wszPath = NULL;
+ node->lpMappedImage = lpImage;
+ node->virtualSize = size;
+ node->isLoaded = false;
+ node->next = m_start;
+ m_start = node;
+ }
+
+ bool freeAll()
+ {
+ PreloadedImageListNode *node = m_start;
+ while (node != NULL)
+ {
+ PreloadedImageListNode *nextNode = node->next;
+ if (!node->isLoaded)
+ {
+ MAPUnmapPreloadedPEFile(node->lpMappedImage, node->virtualSize);
+ }
+
+ if (node->wszPath != NULL)
+ {
+ free(node->wszPath);
+ }
+ free(node->szPath);
+ free(node);
+ node = nextNode;
+ }
+
+ return true;
+ }
+
+ PreloadedImageListNode *find(LPCWSTR wszPath)
+ {
+ PreloadedImageListNode *node = m_start;
+ while (node != NULL)
+ {
+ if (node->wszPath == NULL)
+ {
+ // MultiByteToWideChar requires PAL initialization
+ if (!PALIsInitialized())
+ break;
+
+ int length = MultiByteToWideChar(CP_UTF8, 0, node->szPath, -1, NULL, 0);
+ _ASSERTE(length != 0);
+
+ node->wszPath = (LPWSTR) InternalMalloc(length * sizeof(WCHAR));
+ _ASSERTE(node->wszPath != NULL);
+
+ length = MultiByteToWideChar(CP_UTF8, 0, node->szPath, -1, node->wszPath, length);
+ _ASSERTE(length != 0);
+ }
+
+ if (PAL_wcscmp(node->wszPath, wszPath) == 0)
+ {
+ return node;
+ }
+
+ node = node->next;
+ }
+
+ return NULL;
+ }
+};
+
/* static variables ***********************************************************/
+PreloadedImageList preloadedAssemblies;
+
/* critical section that regulates access to the module list */
CRITICAL_SECTION module_critsec;
@@ -779,6 +869,8 @@ PAL_UnregisterModule(
Parameters:
IN hFile - file to map
+ IN wszPath - File path
+ OUT isPreloaded - Flag whether pefile was preloaded
Return value:
non-NULL - the base address of the mapped image
@@ -786,11 +878,14 @@ Return value:
--*/
PVOID
PALAPI
-PAL_LOADLoadPEFile(HANDLE hFile)
+PAL_LOADLoadPEFile(HANDLE hFile, LPCWSTR wszPath, BOOL *isPreloaded)
{
ENTRY("PAL_LOADLoadPEFile (hFile=%p)\n", hFile);
- void * loadedBase = MAPMapPEFile(hFile);
+ void * preloadedBase = LOADFindPreloadedPEFile(wszPath);
+ *isPreloaded = preloadedBase != NULL;
+
+ void * loadedBase = MAPMapPEFile(hFile, NULL, 0, preloadedBase);
#ifdef _DEBUG
if (loadedBase != nullptr)
@@ -801,8 +896,11 @@ PAL_LOADLoadPEFile(HANDLE hFile)
if (strlen(envVar) > 0)
{
TRACE("Forcing failure of PE file map, and retry\n");
- PAL_LOADUnloadPEFile(loadedBase); // unload it
- loadedBase = MAPMapPEFile(hFile); // load it again
+ if (preloadedBase == NULL)
+ {
+ PAL_LOADUnloadPEFile(loadedBase); // unload it
+ }
+ loadedBase = MAPMapPEFile(hFile, NULL, 0, preloadedBase); // load it again
}
free(envVar);
@@ -815,6 +913,60 @@ PAL_LOADLoadPEFile(HANDLE hFile)
}
/*++
+Function:
+ PAL_LOADPreloadPEFile
+
+Abstract
+ Preloads a PE file into memory. Properly maps all of the sections in the PE file. Returns a pointer to the
+ loaded base.
+
+Parameters:
+ IN szPath - path of file to load
+
+Return value:
+ A valid base address if successful.
+ 0 if failure
+--*/
+void *
+PALAPI
+PAL_LOADPreloadPEFile(LPCSTR szPath)
+{
+ size_t size;
+ void *addr = MAPMapPEFile(NULL, szPath, &size, NULL);
+
+ if (addr == NULL)
+ {
+ return NULL;
+ }
+
+ if (!MAPApplyBaseRelocationsPreloadedPEFile(addr, size))
+ {
+ MAPUnmapPreloadedPEFile(addr, size);
+ return NULL;
+ }
+
+ preloadedAssemblies.addNew(szPath, addr, size);
+
+ return addr;
+}
+
+/*++
+ PAL_LOADUnloadPreloadedPEFiles
+
+ Unload all PE files that were loaded by PAL_LOADPreloadPEFile().
+
+Return value:
+ TRUE - success
+ FALSE - failure
+--*/
+BOOL
+PALAPI
+PAL_LOADUnloadPreloadedPEFiles()
+{
+ return preloadedAssemblies.freeAll();
+}
+
+/*++
PAL_LOADUnloadPEFile
Unload a PE file that was loaded by PAL_LOADLoadPEFile().
@@ -921,6 +1073,34 @@ PAL_GetLoadLibraryError()
/* Internal PAL functions *****************************************************/
/*++
+ LOADFindPreloadedPEFile -
+
+ Find image in list of preloaded
+
+Parameters:
+ IN wszPath - path to mapped file
+
+Return value:
+ non-NULL - the base address of the mapped image
+ NULL - image is not in the list of preloaded.
+--*/
+
+void * LOADFindPreloadedPEFile(LPCWSTR wszPath)
+{
+ void * preloadedBase = NULL;
+
+ PreloadedImageListNode *node = preloadedAssemblies.find(wszPath);
+ if (node != NULL)
+ {
+ preloadedBase = node->lpMappedImage;
+ _ASSERTE(!node->isLoaded);
+ node->isLoaded = true;
+ }
+
+ return preloadedBase;
+}
+
+/*++
Function :
LOADInitializeModules