From 18ace528472bacb103f91dd9edac70defce0875b Mon Sep 17 00:00:00 2001 From: DaLynX Date: Sun, 17 Feb 2019 22:47:19 +0100 Subject: [PATCH 1/4] Added x64 exception handling --- MemoryModule.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MemoryModule.c b/MemoryModule.c index 9f95a70..2fb311b 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -435,6 +435,15 @@ PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) return TRUE; } +static BOOL +RegisterExceptionHandling(PMEMORYMODULE module) +{ + PIMAGE_DATA_DIRECTORY pDir = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION); + PIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(module->codeBase + pDir->VirtualAddress); + UINT count = (pDir->Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)) - 1; + return RtlAddFunctionTable(pEntry, count, (DWORD64)module->codeBase); +} + static BOOL BuildImportTable(PMEMORYMODULE module) { @@ -725,6 +734,10 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, goto error; } + if (!RegisterExceptionHandling(result)) { + goto error; + } + // mark memory pages depending on section headers and release // sections that are marked as "discardable" if (!FinalizeSections(result)) { From f89837636a37340770dfa768f577060d79ace37f Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Sun, 24 Feb 2019 14:41:35 +0100 Subject: [PATCH 2/4] Fix exception handling registration. - Only compile on 64bit, 32bit exception handling works differently. - Unregister table when module is unloaded. - Handle empty tables. - Fix wrong number of entries being passed to "RtlAddFunctionTable". --- MemoryModule.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/MemoryModule.c b/MemoryModule.c index 2fb311b..bc5124a 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -438,10 +438,39 @@ PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) static BOOL RegisterExceptionHandling(PMEMORYMODULE module) { - PIMAGE_DATA_DIRECTORY pDir = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION); - PIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(module->codeBase + pDir->VirtualAddress); - UINT count = (pDir->Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)) - 1; - return RtlAddFunctionTable(pEntry, count, (DWORD64)module->codeBase); +#ifdef _WIN64 + PRUNTIME_FUNCTION pEntry; + DWORD count; + PIMAGE_DATA_DIRECTORY pDir = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION); + if (pDir->Size == 0) { + return TRUE; + } + + pEntry = (PRUNTIME_FUNCTION)(module->codeBase + pDir->VirtualAddress); + count = (pDir->Size / sizeof(RUNTIME_FUNCTION)); + return RtlAddFunctionTable(pEntry, count, (DWORD64) module->codeBase); +#else + // TODO(fancycode): Support 32bit exception handling. + return TRUE; +#endif +} + +static BOOL +UnregisterExceptionHandling(PMEMORYMODULE module) +{ +#ifdef _WIN64 + PRUNTIME_FUNCTION pEntry; + PIMAGE_DATA_DIRECTORY pDir = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION); + if (pDir->Size == 0) { + return TRUE; + } + + pEntry = (PRUNTIME_FUNCTION)(module->codeBase + pDir->VirtualAddress); + return RtlDeleteFunctionTable(pEntry); +#else + // TODO(fancycode): Support 32bit exception handling. + return TRUE; +#endif } static BOOL @@ -734,6 +763,7 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, goto error; } + // register exception handling table so "try { } catch ( ) { }"" works if (!RegisterExceptionHandling(result)) { goto error; } @@ -880,6 +910,8 @@ void MemoryFreeLibrary(HMEMORYMODULE mod) (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); } + UnregisterExceptionHandling(module); + free(module->nameExportsTable); if (module->modules != NULL) { // free previously opened libraries From bf23ebf03ccd0affa1cdc772d4d98ea5c71ccdb9 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Sun, 24 Feb 2019 14:42:48 +0100 Subject: [PATCH 3/4] Add testcase for exception handling code. --- tests/CMakeLists.txt | 2 ++ tests/LoadDll.cpp | 72 +++++++++++++++++++++++++++++++++++++++ tests/Makefile | 2 +- tests/generate-exports.sh | 6 ++++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8b1007f..e968369 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,6 +5,8 @@ set (sources_testsuite if (NOT MSVC) set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-static") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-static") +else () + set (CMAKE_CXX_FLAGS "/EHsc") endif () add_executable (TestSuite ${sources_testsuite}) diff --git a/tests/LoadDll.cpp b/tests/LoadDll.cpp index 8cb215b..15e9f93 100644 --- a/tests/LoadDll.cpp +++ b/tests/LoadDll.cpp @@ -13,6 +13,9 @@ typedef int (*addProc)(int); typedef int (*addNumberProc)(int, int); +#ifdef _WIN64 +typedef void (*throwExceptionProc)(void); +#endif // Thanks to Tim Cooper (from http://stackoverflow.com/a/8584708) const char *sstrstr(const char *haystack, const char *needle, size_t length) { @@ -283,6 +286,70 @@ BOOL LoadExportsFromMemory(char *filename) return result; } +#ifdef _WIN64 +BOOL LoadExceptionsFromMemory(char *filename) +{ + FILE *fp; + unsigned char *data=NULL; + long size; + size_t read; + HMEMORYMODULE handle = NULL; + throwExceptionProc throwException; + BOOL result = TRUE; + + fp = fopen(filename, "rb"); + if (fp == NULL) + { + printf("Can't open DLL file \"%s\".", filename); + result = FALSE; + goto exit; + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + assert(size > 0); + data = (unsigned char *)malloc(size); + assert(data != NULL); + fseek(fp, 0, SEEK_SET); + read = fread(data, 1, size, fp); + assert(read == static_cast(size)); + fclose(fp); + + handle = MemoryLoadLibrary(data, size); + if (handle == NULL) + { + _tprintf(_T("Can't load library from memory.\n")); + result = FALSE; + goto exit; + } + + throwException = (throwExceptionProc)MemoryGetProcAddress(handle, "throwException"); + if (!throwException) { + _tprintf(_T("MemoryGetProcAddress(\"throwException\") returned NULL\n")); + result = FALSE; + goto exit; + } + + try { + throwException(); + _tprintf(_T("Should have caught exception.\n")); + result = FALSE; + goto exit; + } catch (int e) { + if (e != 42) { + _tprintf(_T("Should have caught exception 42, got %d instead\n"), e); + result = FALSE; + goto exit; + } + } + +exit: + MemoryFreeLibrary(handle); + free(data); + return result; +} +#endif + int main(int argc, char* argv[]) { if (argc < 2) { @@ -298,6 +365,11 @@ int main(int argc, char* argv[]) if (!LoadExportsFromMemory(argv[1])) { return 2; } +#ifdef _WIN64 + if (!LoadExceptionsFromMemory(argv[1])) { + return 2; + } +#endif } return 0; diff --git a/tests/Makefile b/tests/Makefile index 028bcad..532a1b7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -74,7 +74,7 @@ test-relocate.dll: $(DLL_OBJ) $(CXX) $(LDFLAGS_DLL) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o $@ $(DLL_OBJ) test-exports.dll: SampleExports.o - $(CXX) $(LDFLAGS_DLL) $(LDFLAGS) -o $@ SampleExports.o + $(CXX) $(LDFLAGS_DLL) $(LDFLAGS) -static -lstdc++ -dynamic -o $@ SampleExports.o SampleExports.cpp: generate-exports.sh ./generate-exports.sh diff --git a/tests/generate-exports.sh b/tests/generate-exports.sh index 974b2a6..ece6d45 100755 --- a/tests/generate-exports.sh +++ b/tests/generate-exports.sh @@ -48,5 +48,11 @@ EOF done cat >> SampleExports.cpp << EOF +#ifdef _WIN64 +SAMPLEDLL_API void throwException(void) +{ + throw 42; +} +#endif } EOF From 1adaf0ef668f60e9757768b458d727a738932fea Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Sun, 24 Feb 2019 14:54:07 +0100 Subject: [PATCH 4/4] Add exception handling code to example. --- example/DllLoader/DllLoader.cpp | 45 ++++++++++++++++++++++++++++++++ example/SampleDLL/CMakeLists.txt | 3 +++ example/SampleDLL/Makefile | 2 +- example/SampleDLL/SampleDLL.cpp | 7 +++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/example/DllLoader/DllLoader.cpp b/example/DllLoader/DllLoader.cpp index 4355ea8..abaaaac 100644 --- a/example/DllLoader/DllLoader.cpp +++ b/example/DllLoader/DllLoader.cpp @@ -12,12 +12,18 @@ #include "../../MemoryModule.h" typedef int (*addNumberProc)(int, int); +#ifdef _WIN64 +typedef void (*throwExceptionProc)(void); +#endif #define DLL_FILE TEXT("..\\SampleDLL\\SampleDLL.dll") void LoadFromFile(void) { addNumberProc addNumber; +#ifdef _WIN64 + throwExceptionProc throwException; +#endif HRSRC resourceInfo; DWORD resourceSize; LPVOID resourceData; @@ -43,6 +49,24 @@ void LoadFromFile(void) LoadString(handle, 20, buffer, sizeof(buffer)); _tprintf(_T("String2: %s\n"), buffer); +#ifdef _WIN64 + throwException = (throwExceptionProc)GetProcAddress(handle, "throwException"); + if (!throwException) { + _tprintf(_T("GetProcAddress(\"throwException\") returned NULL\n")); + } else { + try { + throwException(); + _tprintf(_T("Should have caught exception.\n")); + } catch (int e) { + if (e != 42) { + _tprintf(_T("Should have caught exception 42, got %d instead\n"), e); + } else { + _tprintf(_T("Caught exception %d\n"), e); + } + } + } +#endif + FreeLibrary(handle); } @@ -90,6 +114,9 @@ void LoadFromMemory(void) size_t size; HMEMORYMODULE handle; addNumberProc addNumber; +#ifdef _WIN64 + throwExceptionProc throwException; +#endif HMEMORYRSRC resourceInfo; DWORD resourceSize; LPVOID resourceData; @@ -124,6 +151,24 @@ void LoadFromMemory(void) MemoryLoadString(handle, 20, buffer, sizeof(buffer)); _tprintf(_T("String2: %s\n"), buffer); +#ifdef _WIN64 + throwException = (throwExceptionProc)MemoryGetProcAddress(handle, "throwException"); + if (!throwException) { + _tprintf(_T("MemoryGetProcAddress(\"throwException\") returned NULL\n")); + } else { + try { + throwException(); + _tprintf(_T("Should have caught exception.\n")); + } catch (int e) { + if (e != 42) { + _tprintf(_T("Should have caught exception 42, got %d instead\n"), e); + } else { + _tprintf(_T("Caught exception %d\n"), e); + } + } + } +#endif + MemoryFreeLibrary(handle); exit: diff --git a/example/SampleDLL/CMakeLists.txt b/example/SampleDLL/CMakeLists.txt index e3a3af3..381e719 100644 --- a/example/SampleDLL/CMakeLists.txt +++ b/example/SampleDLL/CMakeLists.txt @@ -7,6 +7,9 @@ set (sources add_definitions (-DSAMPLEDLL_EXPORTS) add_library (SampleDLL MODULE ${sources}) if (NOT MSVC) + set_target_properties ("SampleDLL" PROPERTIES LINK_FLAGS "-static -lstdc++ -dynamic") set_target_properties ("SampleDLL" PROPERTIES PREFIX "") set_target_properties ("SampleDLL" PROPERTIES SUFFIX ".dll") +else () + set (CMAKE_CXX_FLAGS "/EHs") endif () diff --git a/example/SampleDLL/Makefile b/example/SampleDLL/Makefile index ce3f65b..ce6aaee 100644 --- a/example/SampleDLL/Makefile +++ b/example/SampleDLL/Makefile @@ -27,7 +27,7 @@ endif OBJ = SampleDLL.o SampleDLL.res SampleDLL.dll: $(OBJ) - $(LINK) $(LDFLAGS) -o SampleDLL.dll $(OBJ) + $(LINK) $(LDFLAGS) -static -lstdc++ -dynamic -o SampleDLL.dll $(OBJ) %.o: %.cpp $(CXX) $(CFLAGS) -c $< diff --git a/example/SampleDLL/SampleDLL.cpp b/example/SampleDLL/SampleDLL.cpp index 7bf03ef..ec73b0e 100644 --- a/example/SampleDLL/SampleDLL.cpp +++ b/example/SampleDLL/SampleDLL.cpp @@ -7,4 +7,11 @@ SAMPLEDLL_API int addNumbers(int a, int b) return a + b; } +#ifdef _WIN64 +SAMPLEDLL_API void throwException(void) +{ + throw 42; +} +#endif + } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy