10 Commits
12 changed files with 232 additions and 83 deletions

No files matched your search

+5 -5
View File
@@ -16,8 +16,8 @@ jobs:
- name: Configure CMake
shell: cmd
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -A x64 -B build64
cmake -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -A Win32 -B build32
cmake -DCMAKE_SYSTEM_PROCESSOR=amd64 -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -A x64 -B build64
cmake -DCMAKE_SYSTEM_PROCESSOR=x86 -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -A Win32 -B build32
- name: Build x86
run: |
@@ -54,8 +54,8 @@ jobs:
- name: Configure CMake
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build64
cmake -DCMAKE_CXX_FLAGS="-m32" -DCMAKE_C_FLAGS="-m32" -DCMAKE_SHARED_LINKER_FLAGS="-m32" -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build86
cmake -DCMAKE_SYSTEM_PROCESSOR=amd64 -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build64
cmake -DCMAKE_SYSTEM_PROCESSOR=x86 -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_CXX_FLAGS="-m32" -DCMAKE_C_FLAGS="-m32" -DCMAKE_SHARED_LINKER_FLAGS="-m32" -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build86
- name: Build x64
run: |
@@ -86,7 +86,7 @@ jobs:
- name: Configure CMake
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build64
cmake -DCMAKE_SYSTEM_PROCESSOR=amd64 -DCMAKE_SYSTEM_NAME=Darwin -DCMAKE_BUILD_TYPE=Release -DDynamicBinaryInstrument=OFF -DPlugin.SymbolResolver=OFF -B build64
- name: Build x64
run: |
+60 -13
View File
@@ -1,4 +1,6 @@
cmake_minimum_required(VERSION 3.5)
include(cmake/EarlyGlobals.cmake)
project(Dobby)
enable_language(ASM)
@@ -101,19 +103,65 @@ elseif(SYSTEM.Android)
elseif(SYSTEM.Linux)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
elseif(SYSTEM.Windows)
# Statically link UCRT
if(NOT DOBBY_DEBUG)
if(COMPILER.Gcc OR COMPILER.Clang)
add_compile_options(-MT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MT")
else()
add_compile_options(/MT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT")
endif()
else()
if(COMPILER.Gcc OR COMPILER.Clang)
add_compile_options(-MTd)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MTd")
else()
add_compile_options(/MTd)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MTd")
endif()
endif()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_DEPRECATE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbyPrepare /export:DobbyHook /export:DobbyCommit /export:DobbyBuildVersion /export:DobbyDestroy")
if (DynamicBinaryInstrument)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbyInstrument")
endif()
if (Plugin.SymbolResolver)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbySymbolResolver")
endif()
if (DOBBY_DEBUG)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:log_switch_to_file /export:log_set_level")
endif()
if (NearBranch)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:dobby_enable_near_branch_trampoline /export:dobby_disable_near_branch_trampoline")
if(COMPILER.MSVC)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbyPrepare /export:DobbyHook /export:DobbyCommit /export:DobbyBuildVersion /export:DobbyDestroy")
if (DynamicBinaryInstrument)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbyInstrument")
endif()
if (Plugin.SymbolResolver)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:DobbySymbolResolver")
endif()
if (DOBBY_DEBUG)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:log_switch_to_file /export:log_set_level")
endif()
if (NearBranch)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /export:dobby_enable_near_branch_trampoline /export:dobby_disable_near_branch_trampoline")
endif()
elseif(COMPILER.Gcc OR Compiler.Clang)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
# Enable unicode, Statically link libgcc/libstdc++
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -municode")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static")
if (NOT DOBBY_DEBUG)
# Garbage-collect/strip unused code
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-gc-sections -s")
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,${CMAKE_BINARY_DIR}/libdobby.def")
file(WRITE "${CMAKE_BINARY_DIR}/libdobby.def" "LIBRARY \"libdobby.dll\"\n\nEXPORTS")
file(APPEND "${CMAKE_BINARY_DIR}/libdobby.def" "\nDobbyPrepare\nDobbyHook\nDobbyCommit\nDobbyBuildVersion\nDobbyDestroy")
if (DynamicBinaryInstrument)
file(APPEND "${CMAKE_BINARY_DIR}/libdobby.def" "\nDobbyInstrument")
endif()
if (Plugin.SymbolResolver)
file(APPEND "${CMAKE_BINARY_DIR}/libdobby.def" "\nDobbySymbolResolver")
endif()
if (DOBBY_DEBUG)
file(APPEND "${CMAKE_BINARY_DIR}/libdobby.def" "\nlog_switch_to_file\nlog_set_level")
endif()
if (NearBranch)
file(APPEND "${CMAKE_BINARY_DIR}/libdobby.def" "\ndobby_enable_near_branch_trampoline\ndobby_disable_near_branch_trampoline")
endif()
endif()
endif()
@@ -456,4 +504,3 @@ if(SYSTEM.Darwin)
endif()
add_subdirectory(example)
@@ -17,7 +17,7 @@ PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name
void *result = NULL;
HMODULE hMod = LoadLibraryExA(image_name, NULL, DONT_RESOLVE_DLL_REFERENCES);
result = GetProcAddress(hMod, symbol_name_pattern);
result = (void *)GetProcAddress(hMod, symbol_name_pattern);
if (result)
return result;
+59
View File
@@ -0,0 +1,59 @@
# Early global definitions.
# Put anything here needed for the toolchain
# and include this file before calling project()
# The Processor
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|x64.*")
set(PROCESSOR.X86_64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*")
set(PROCESSOR.X86 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64.*")
set(PROCESSOR.AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
set(PROCESSOR.AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
set(PROCESSOR.ARM 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
set(PROCESSOR.PPC64LE 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
set(PROCESSOR.PPC64 1)
else()
message (FATAL_ERROR "Processor ${CMAKE_SYSTEM_PROCESSOR} not configured")
endif()
# The System
if(CMAKE_SYSTEM_NAME MATCHES "^Android")
set(SYSTEM.Android 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
set(SYSTEM.Windows 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Linux")
set(SYSTEM.Linux 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^iOS")
set(SYSTEM.iOS 1)
set(SYSTEM.Darwin 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^macOS")
set(SYSTEM.macOS 1)
set(SYSTEM.Darwin 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Darwin")
if(PROCESSOR.AARCH64 OR PROCESSOR.ARM)
set(CMAKE_SYSTEM_NAME "iOS")
set(SYSTEM.iOS 1)
elseif(PROCESSOR.X86 OR PROCESSOR.X86_64)
set(SYSTEM.macOS 1)
endif()
set(SYSTEM.Darwin 1)
else()
message (FATAL_ERROR "System ${CMAKE_SYSTEM_NAME} not configured")
endif()
if (SYSTEM.Windows)
if (CMAKE_HOST_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_HOST_SYSTEM_NAME MATCHES "MSYS")
if (PROCESSOR.X86_64)
set(CMAKE_TOOLCHAIN_FILE "cmake/mingw64-x86_64.toolchain.cmake")
else()
message (FATAL_ERROR "Windows cross-compilation toolchain for processor ${CMAKE_SYSTEM_PROCESS} not configured")
endif()
endif()
endif()
+6 -47
View File
@@ -35,54 +35,13 @@ endif()
string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR)
# The Processor
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|x64.*")
set(PROCESSOR.X86_64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*")
set(PROCESSOR.X86 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64.*")
set(PROCESSOR.AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
set(PROCESSOR.AARCH64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
set(PROCESSOR.ARM 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
set(PROCESSOR.PPC64LE 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
set(PROCESSOR.PPC64 1)
else()
message (FATAL_ERROR "Processor ${CMAKE_SYSTEM_PROCESSOR} not configured")
endif()
message(STATUS "\tProcessor:\t ${CMAKE_SYSTEM_PROCESSOR}")
# The System
if(CMAKE_SYSTEM_NAME MATCHES "^Android")
set(SYSTEM.Android 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
set(SYSTEM.Windows 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Linux")
set(SYSTEM.Linux 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^iOS")
set(SYSTEM.iOS 1)
set(SYSTEM.Darwin 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^macOS")
set(SYSTEM.macOS 1)
set(SYSTEM.Darwin 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Darwin")
if(PROCESSOR.AARCH64 OR PROCESSOR.ARM)
set(CMAKE_SYSTEM_NAME "iOS")
set(SYSTEM.iOS 1)
elseif(PROCESSOR.X86 OR PROCESSOR.X86_64)
set(CMAKE_SYSTEM_NAME "macOS")
set(SYSTEM.macOS 1)
endif()
set(SYSTEM.Darwin 1)
else()
message (FATAL_ERROR "System ${CMAKE_SYSTEM_NAME} not configured")
endif()
message(STATUS "\tSystem: \t ${CMAKE_SYSTEM_NAME}")
if (NOT CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR)
message(STATUS "\tHost processor:\t ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
if (NOT CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
message(STATUS "\tHost system :\t ${CMAKE_HOST_SYSTEM_NAME}")
endif()
message(STATUS "***************************************")
message(STATUS "")
+24
View File
@@ -0,0 +1,24 @@
# Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64`
# *) cd build
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake ..
# This is free and unencumbered software released into the public domain.
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
# cross compilers to use for C, C++ and Fortran
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+13
View File
@@ -34,6 +34,19 @@ cmake ..
make -j4
```
## Build for Windows using MINGW
```
cd Dobby && mkdir build_for_windows_x64 && cd build_for_windows_x64
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_SYSTEM_PROCESSOR=x64
make -j4
```
## Build for iOS / macOS
#### Manual build for macOS X64 host
+3
View File
@@ -15,6 +15,8 @@
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#ifndef _STDINT_H
/* should be in some equivalent to <sys/types.h> */
typedef __int8 int8_t;
typedef __int16 int16_t;
@@ -24,6 +26,7 @@ typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#endif // _STDINT_H
#else
@@ -447,11 +447,30 @@ static void x86_insn_decode_opcode(x86_insn_reader_t *rd, x86_insn_decode_t *ins
} else {
insn_spec = x86_opcode_map_one_byte[opcode];
}
DLOG(0, "[x86 decode] spec: %p", &x86_opcode_map_one_byte[opcode]);
DLOG(0, "[x86 decode] spec; opcode: %x; name: %s; flags: %d", opcode, insn_spec.name, insn_spec.flags);
// check sse group
if (X86_INSN_FLAG_GET_GROUP(insn_spec.flags) > X86_INSN_SSE_GROUP_START) {
UNIMPLEMENTED();
int group_ndx = X86_INSN_FLAG_GET_SSE_GROUP(insn_spec.flags);
x86_insn_modrm_t modrm;
modrm.byte = peek_byte(rd);
int insn_ndx = modrm.reg;
x86_insn_spec_t *group_insn = NULL;
group_insn = &x86_insn_sse_groups_repz[group_ndx].insns[insn_ndx];
insn_spec.name = group_insn->name;
insn_spec.flags = group_insn->flags;
for (int i = 0; i < sizeof(insn_spec.operands) / sizeof(x86_insn_operand_spec_t); i++) {
x86_insn_operand_spec_t group_op = group_insn->operands[i];
if (group_op.data[0] != '_' && group_op.data[1] != '_') {
insn_spec.operands[i] = group_insn->operands[i];
}
}
DLOG(0, "[x86 sse decode] modrm_group_spec; group: %d, ins: %d, byte: %x; name: %s; flags: %d", group_ndx, insn_ndx,
modrm.byte, insn_spec.name, insn_spec.flags);
}
if (X86_INSN_FLAG_GET_GROUP(insn_spec.flags) > X86_INSN_GROUP_START &&
@@ -471,6 +490,15 @@ static void x86_insn_decode_opcode(x86_insn_reader_t *rd, x86_insn_decode_t *ins
// update the insn spec
insn_spec.name = group_insn->name;
insn_spec.flags = group_insn->flags;
for (int i = 0; i < sizeof(insn_spec.operands) / sizeof(x86_insn_operand_spec_t); i++) {
x86_insn_operand_spec_t group_op = group_insn->operands[i];
if (group_op.data[0] != '_' && group_op.data[1] != '_') {
insn_spec.operands[i] = group_insn->operands[i];
}
}
DLOG(0, "[x86 decode] modrm_group_spec; group: %d, ins: %d, byte: %x; name: %s; flags: %d", group_ndx, insn_ndx, modrm.byte,
insn_spec.name,
insn_spec.flags);
}
insn->primary_opcode = opcode;
@@ -561,10 +589,10 @@ void x86_insn_decode(x86_insn_decode_t *insn, uint8_t *buffer, x86_options_t *co
x86_insn_decode_immediate(&rd, insn, conf);
}
#if 1
DLOG(0, "[x86 insn] %s, %p", insn->insn_spec.name, &insn->insn_spec);
#endif
// set insn length
insn->length = rd.buffer_cursor - rd.buffer;
#if 1
DLOG(0, "[x86 insn] opcode: %s, spec: %p, size: %d", insn->insn_spec.name, &insn->insn_spec, insn->length);
#endif
}
@@ -4,15 +4,15 @@
#include "MemoryAllocator/CodeBuffer/code-buffer-x64.h"
void CodeBuffer::Emit32(int32_t data) {
ensureCapacity(getSize() + sizeof(int32_t));
*reinterpret_cast<int32_t *>(getCursor()) = data;
this->ensureCapacity(this->getSize() + sizeof(int32_t));
*reinterpret_cast<int32_t *>(buffer_cursor) = data;
buffer_cursor += sizeof(int32_t);
return;
}
void CodeBuffer::Emit64(int64_t data) {
ensureCapacity(getSize() + sizeof(int64_t));
*reinterpret_cast<int64_t *>(getCursor()) = data;
this->ensureCapacity(this->getSize() + sizeof(int64_t));
*reinterpret_cast<int64_t *>(buffer_cursor) = data;
buffer_cursor += sizeof(int64_t);
return;
}
@@ -15,12 +15,25 @@ PUBLIC MemoryOperationError CodePatch(void *address, uint8_t *buffer, uint32_t b
void *addressPageAlign = (void *)ALIGN(address, pageSize);
if (!VirtualProtect(addressPageAlign, pageSize, PAGE_EXECUTE_READWRITE, &oldProtect))
return kMemoryOperationError;
HANDLE hProc = NULL;
if (!VirtualProtect(addressPageAlign, pageSize, PAGE_EXECUTE_READWRITE, &oldProtect)) {
// Some games fiddles with VirtualProtect
DWORD pid = GetCurrentProcessId();
hProc = OpenProcess(PROCESS_VM_OPERATION, FALSE, pid);
if (!VirtualProtectEx(hProc, addressPageAlign, pageSize, PAGE_EXECUTE_READWRITE, &oldProtect)) {
CloseHandle(hProc);
return kMemoryOperationError;
}
}
memcpy(address, buffer, buffer_size);
if (!VirtualProtect(addressPageAlign, pageSize, oldProtect, &oldProtect))
if (hProc) {
BOOL ok = VirtualProtectEx(hProc, addressPageAlign, pageSize, oldProtect, &oldProtect);
CloseHandle(hProc);
if (!ok)
return kMemoryOperationError;
} else if (!VirtualProtect(addressPageAlign, pageSize, oldProtect, &oldProtect))
return kMemoryOperationError;
return kMemoryOperationSuccess;
@@ -8,10 +8,13 @@
#include "UnifiedInterface/platform.h"
int GetProtectionFromMemoryPermission(MemoryPermission access) {
if (kReadWriteExecute == access)
return PAGE_EXECUTE_READWRITE;
else if (kReadExecute == access)
return PAGE_EXECUTE_READ;
switch (access) {
case kNoAccess: return PAGE_NOACCESS;
case kRead: return PAGE_READONLY;
case kReadWrite: return PAGE_READWRITE;
case kReadWriteExecute: return PAGE_EXECUTE_READWRITE;
case kReadExecute: return PAGE_EXECUTE_READ;
}
}
int OSMemory::AllocPageSize() {