64-bit support for CSGO on Linux and macOS (#705)

This commit is contained in:
Scott Ehlert
2017-12-20 01:56:23 -06:00
committed by GitHub
parent 057a5790e2
commit ce1a4dcac0
90 changed files with 15682 additions and 947 deletions
+60 -2
View File
@@ -1,11 +1,13 @@
#include "asm.h"
#include "libudis86/udis86.h"
#ifndef WIN32
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "libudis86/udis86.h"
#define REG_EAX 0
#define REG_ECX 1
@@ -25,7 +27,9 @@
*/
void check_thunks(unsigned char *dest, unsigned char *pc)
{
#ifndef WIN32
#if defined(_WIN32) || defined(__x86_64__)
return;
#else
/* Step write address back 4 to the start of the function address */
unsigned char *writeaddr = dest - 4;
unsigned char *calloffset = *(unsigned char **)writeaddr;
@@ -85,6 +89,59 @@ void check_thunks(unsigned char *dest, unsigned char *pc)
#endif
}
int copy_bytes(unsigned char *func, unsigned char *dest, int required_len)
{
ud_t ud_obj;
ud_init(&ud_obj);
#if defined(_WIN64) || defined(__x86_64__)
ud_set_mode(&ud_obj, 64);
#else
ud_set_mode(&ud_obj, 32);
#endif
ud_set_input_buffer(&ud_obj, func, 20);
unsigned int bytecount = 0;
while (bytecount < required_len && ud_disassemble(&ud_obj))
{
unsigned int insn_len = ud_insn_len(&ud_obj);
bytecount += insn_len;
if (dest)
{
const uint8_t *opcode = ud_insn_ptr(&ud_obj);
if ((opcode[0] & 0xFE) == 0xE8) // Fix CALL/JMP offset
{
dest[0] = func[0];
dest++; func++;
if (ud_insn_opr(&ud_obj, 0)->size == 32)
{
*(int32_t *)dest = func + *(int32_t *)func - dest;
check_thunks(dest+4, func+4);
dest += sizeof(int32_t);
}
else
{
*(int16_t *)dest = func + *(int16_t *)func - dest;
dest += sizeof(int16_t);
}
func--;
}
else
{
memcpy(dest, func, insn_len);
dest += insn_len;
}
}
func += insn_len;
}
return bytecount;
}
#if 0
//if dest is NULL, returns minimum number of bytes needed to be copied
//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs
//http://www.devmaster.net/forums/showthread.php?t=2311
@@ -336,6 +393,7 @@ int copy_bytes(unsigned char *func, unsigned char* dest, int required_len) {
return bytecount;
}
#endif
//insert a specific JMP instruction at the given location
void inject_jmp(void* src, void* dest) {
+1
View File
@@ -3,6 +3,7 @@
#define OP_JMP 0xE9
#define OP_JMP_SIZE 5
#define X64_ABS_SIZE 14
#define OP_NOP 0x90
#define OP_NOP_SIZE 1