Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix various 64bit issues #50

Merged
merged 4 commits into from
Sep 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ endif ()
if (NOT MSVC)
add_definitions ("-Wall")
else ()
# Show level 4 warnings.
add_definitions ("-W4")
endif ()

Expand Down
110 changes: 98 additions & 12 deletions MemoryModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
#if _MSC_VER
// Disable warning about data -> function pointer conversion
#pragma warning(disable:4055)
// C4244: conversion from 'uintptr_t' to 'DWORD', possible loss of data.
#pragma warning(error: 4244)
// C4267: conversion from 'size_t' to 'int', possible loss of data.
#pragma warning(error: 4267)

#define inline __inline
#endif

#ifndef IMAGE_SIZEOF_BASE_RELOCATION
Expand Down Expand Up @@ -68,14 +74,27 @@ typedef struct {
typedef struct {
LPVOID address;
LPVOID alignedAddress;
DWORD size;
SIZE_T size;
DWORD characteristics;
BOOL last;
} SECTIONFINALIZEDATA, *PSECTIONFINALIZEDATA;

#define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
#define ALIGN_DOWN(address, alignment) (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))
#define ALIGN_VALUE_UP(value, alignment) (((value) + (alignment) - 1) & ~((alignment) - 1))

static inline uintptr_t
AlignValueDown(uintptr_t value, uintptr_t alignment) {
return value & ~(alignment - 1);
}

static inline LPVOID
AlignAddressDown(LPVOID address, uintptr_t alignment) {
return (LPVOID) AlignValueDown((uintptr_t) address, alignment);
}

static inline size_t
AlignValueUp(size_t value, size_t alignment) {
return (value + alignment - 1) & ~(alignment - 1);
}

#ifdef DEBUG_OUTPUT
static void
Expand Down Expand Up @@ -173,7 +192,7 @@ static int ProtectionFlags[2][2][2] = {
},
};

static DWORD
static SIZE_T
GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {
DWORD size = section->SizeOfRawData;
if (size == 0) {
Expand All @@ -183,7 +202,7 @@ GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {
size = module->headers->OptionalHeader.SizeOfUninitializedData;
}
}
return size;
return (SIZE_T) size;
}

static BOOL
Expand Down Expand Up @@ -242,7 +261,7 @@ FinalizeSections(PMEMORYMODULE module)
#endif
SECTIONFINALIZEDATA sectionData;
sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize);
sectionData.alignedAddress = AlignAddressDown(sectionData.address, module->pageSize);
sectionData.size = GetRealSectionSize(module, section);
sectionData.characteristics = section->Characteristics;
sectionData.last = FALSE;
Expand All @@ -251,8 +270,8 @@ FinalizeSections(PMEMORYMODULE module)
// loop through all sections and change access flags
for (i=1; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize);
DWORD sectionSize = GetRealSectionSize(module, section);
LPVOID alignedAddress = AlignAddressDown(sectionAddress, module->pageSize);
SIZE_T sectionSize = GetRealSectionSize(module, section);
// Combine access flags of all sections that share a page
// TODO(fancycode): We currently share flags of a trailing large section
// with the page of a first small section. This should be optimized.
Expand All @@ -263,7 +282,7 @@ FinalizeSections(PMEMORYMODULE module)
} else {
sectionData.characteristics |= section->Characteristics;
}
sectionData.size = (((uintptr_t)sectionAddress) + sectionSize) - (uintptr_t) sectionData.address;
sectionData.size = (((uintptr_t)sectionAddress) + ((uintptr_t) sectionSize)) - (uintptr_t) sectionData.address;
continue;
}

Expand Down Expand Up @@ -543,8 +562,8 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
}

GetNativeSystemInfo(&sysInfo);
alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
if (alignedImageSize != ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) {
alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
Expand Down Expand Up @@ -849,7 +868,11 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(
cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length);
if (cmp == 0) {
// Handle partial match
cmp = searchKeyLen - resourceString->Length;
if (searchKeyLen > resourceString->Length) {
cmp = 1;
} else if (searchKeyLen < resourceString->Length) {
cmp = -1;
}
}
if (cmp < 0) {
end = (middle != end ? middle : middle-1);
Expand Down Expand Up @@ -994,3 +1017,66 @@ MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WO
#endif
return size;
}

#ifdef TESTSUITE
#include <stdio.h>
#include <inttypes.h>

#ifndef PRIxPTR
#ifdef _WIN64
#define PRIxPTR "I64x"
#else
#define PRIxPTR "x"
#endif
#endif

static const uintptr_t AlignValueDownTests[][3] = {
{16, 16, 16},
{17, 16, 16},
{32, 16, 32},
{33, 16, 32},
#ifdef _WIN64
{0x12345678abcd1000, 0x1000, 0x12345678abcd1000},
{0x12345678abcd101f, 0x1000, 0x12345678abcd1000},
#endif
{0, 0, 0},
};

static const uintptr_t AlignValueUpTests[][3] = {
{16, 16, 16},
{17, 16, 32},
{32, 16, 32},
{33, 16, 48},
#ifdef _WIN64
{0x12345678abcd1000, 0x1000, 0x12345678abcd1000},
{0x12345678abcd101f, 0x1000, 0x12345678abcd2000},
#endif
{0, 0, 0},
};

BOOL MemoryModuleTestsuite() {
BOOL success = TRUE;
for (size_t idx = 0; AlignValueDownTests[idx][0]; ++idx) {
const uintptr_t* tests = AlignValueDownTests[idx];
uintptr_t value = AlignValueDown(tests[0], tests[1]);
if (value != tests[2]) {
printf("AlignValueDown failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n",
tests[0], tests[1], tests[2], value);
success = FALSE;
}
}
for (size_t idx = 0; AlignValueDownTests[idx][0]; ++idx) {
const uintptr_t* tests = AlignValueUpTests[idx];
uintptr_t value = AlignValueUp(tests[0], tests[1]);
if (value != tests[2]) {
printf("AlignValueUp failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n",
tests[0], tests[1], tests[2], value);
success = FALSE;
}
}
if (success) {
printf("OK\n");
}
return success;
}
#endif
12 changes: 10 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ RC = rc
endif

RM = rm
CFLAGS = -Wall -g
CFLAGS = -Wall -g -DTESTSUITE
LDFLAGS =
RCFLAGS = -O coff

Expand Down Expand Up @@ -49,13 +49,20 @@ TEST_DLLS = \
test-relocate.dll \

LOADDLL_OBJ = LoadDll.o ../MemoryModule.o
TESTSUITE_OBJ = TestSuite.o ../MemoryModule.o
DLL_OBJ = SampleDLL.o SampleDLL.res

all: LoadDll.exe $(TEST_DLLS)
all: prepare_testsuite LoadDll.exe TestSuite.exe $(TEST_DLLS)

prepare_testsuite:
rm -f $(TESTSUITE_OBJ)

LoadDll.exe: $(LOADDLL_OBJ)
$(CC) $(LDFLAGS_EXE) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o LoadDll.exe $(LOADDLL_OBJ)

TestSuite.exe: $(TESTSUITE_OBJ)
$(CC) $(LDFLAGS_EXE) $(LDFLAGS) -o TestSuite.exe $(TESTSUITE_OBJ)

LoadDll.o: LoadDll.cpp
$(CXX) $(CFLAGS) $(CFLAGS_EXE) -c $<

Expand All @@ -78,4 +85,5 @@ clean:
$(RM) -rf LoadDll.exe $(TEST_DLLS) $(LOADDLL_OBJ) $(DLL_OBJ)

test: all
./runwine.sh $(PLATFORM) TestSuite.exe
./runtests.sh $(PLATFORM) "$(TEST_DLLS)"
17 changes: 17 additions & 0 deletions tests/TestSuite.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <windows.h>

extern BOOL MemoryModuleTestsuite();

int main(int argc, char* argv[])
{
if (!MemoryModuleTestsuite()) {
return 1;
}

return 0;
}
10 changes: 1 addition & 9 deletions tests/runtests.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
#!/bin/bash
PLATFORM=$1
if [ "${PLATFORM}" = "x86_64" ]; then
export WINEPREFIX=${HOME}/.wine64/
WINE=wine64
else
export WINEPREFIX=${HOME}/.wine/
WINE=wine
fi
export WINEPATH=/usr/lib/gcc/${PLATFORM}-w64-mingw32/4.6/

read -a TEST_DLLS <<< $2

for filename in "${TEST_DLLS[@]}"
do
:
echo "Testing $filename"
${WINE} ./LoadDll.exe $filename
./runwine.sh "${PLATFORM}" ./LoadDll.exe $filename
if [ "$?" != "0" ]; then
exit 1
fi
Expand Down
15 changes: 15 additions & 0 deletions tests/runwine.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
set -eu
PLATFORM=$1
shift

if [ "${PLATFORM}" = "x86_64" ]; then
export WINEPREFIX=${HOME}/.wine64/
WINE=wine64
else
export WINEPREFIX=${HOME}/.wine/
WINE=wine
fi
export WINEPATH=/usr/lib/gcc/${PLATFORM}-w64-mingw32/4.6/

exec ${WINE} $@