-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
starting a simple compiler interface which wraps asmjit
- Loading branch information
Showing
12 changed files
with
295 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
[submodule "deps/udis86"] | ||
path = deps/udis86 | ||
url = https://github.com/vmt/udis86.git | ||
[submodule "deps/asmjit"] | ||
path = deps/asmjit | ||
url = https://github.com/kobalicek/asmjit.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
#define TRACE_STACK_OFFSET 728 /* hardcode offset from this base stack */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "simple_compiler.h" | ||
|
||
using namespace redmagic; | ||
using namespace asmjit; | ||
|
||
SimpleCompiler::~SimpleCompiler() { | ||
if(buffer) { | ||
finalize(); | ||
} | ||
} | ||
|
||
CodeBuffer SimpleCompiler::finalize() { | ||
assert(buffer); | ||
// check that no one else used this buffer while this was running | ||
assert(buffer->getRawBuffer() + buffer->getOffset() == buffer_cursor); | ||
restore_registers(); | ||
getOffset(); | ||
getCodeSize(); | ||
void *start = make(); | ||
assert(start == (void*)buffer_cursor); | ||
size_t len = runtime.getBaseAddress() - buffer_cursor; | ||
buffer->setOffset(runtime.getBaseAddress() - buffer->getRawBuffer()); | ||
|
||
buffer = NULL; | ||
CodeBuffer ret(buffer_cursor, len); | ||
ret.can_write_buffer = true; | ||
return ret; | ||
} | ||
|
||
void SimpleCompiler::restore_registers() { | ||
uint64_t restore = clobbered_registers; | ||
int indx = 0; | ||
while(restore) { | ||
if(restore & 0x1) { | ||
mov(get_register_from_id(indx), x86::ptr(x86::rsp, -TRACE_STACK_OFFSET + indx * 8 + move_stack_by)); | ||
} | ||
restore >>= 1; | ||
indx++; | ||
} | ||
clobbered_registers = 0; | ||
} | ||
|
||
void SimpleCompiler::protect_register(int id) { | ||
if(clobbered_registers & (1 << id) == 0) { | ||
mov(x86::ptr(x86::rsp, -TRACE_STACK_OFFSET + id * 8 + move_stack_by), get_register_from_id(id)); | ||
clobbered_registers |= 1 << id; | ||
} | ||
} | ||
|
||
const asmjit::X86GpReg& SimpleCompiler::get_scratch_register() { | ||
int indx = 0; | ||
if(~regs_using & clobbered_registers) { | ||
// if there is a clobbered register that we can use as scratch then favor that | ||
while(indx <= RDI) { | ||
if((~regs_using & clobbered_registers & (1 << indx)) == 0) { | ||
regs_using |= 1 << indx; | ||
return get_register(indx); | ||
} | ||
} | ||
} | ||
while(indx <= RDI) { | ||
if((regs_using & (1 << indx)) == 0) { | ||
protect_register(indx); | ||
regs_using |= 1 << indx; | ||
clobbered_registers |= 1 << indx; | ||
return get_register_from_id(indx); | ||
} | ||
} | ||
// did not find a register | ||
assert(0); | ||
} | ||
|
||
const asmjit::X86GpReg& SimpleCompiler::get_register(int id) { | ||
assert((clobbered_registers & 1 << id) == 0); | ||
regs_using |= 1 << id; | ||
return get_register_from_id(id); | ||
} | ||
|
||
|
||
void SimpleCompiler::MemToRegister(mem_loc_t mem, int reg) { | ||
auto r = get_register(reg); | ||
mov(r, imm_u(mem)); | ||
mov(r, x86::ptr(r)); | ||
} | ||
|
||
void SimpleCompiler::RegisterToMem(int reg, mem_loc_t mem) { | ||
auto r = get_register(reg); | ||
auto scr = get_scratch_register(); | ||
mov(scr, imm_u(mem)); | ||
mov(x86::ptr(scr), r); | ||
} | ||
|
||
void SimpleCompiler::SetRegister(int reg, register_t val) { | ||
mov(get_register(reg), imm_u(val)); | ||
} | ||
|
||
void SimpleCompiler::TestRegister(int reg, register_t val) { | ||
auto r = get_register(reg); | ||
Label success = newLabel(); | ||
pushf(); | ||
test(r, imm_u(val)); | ||
je(success); | ||
// TODO: make this use some label for a generated address | ||
popf(); | ||
jmp(imm_u(0xfafafafafafafafa)); | ||
bind(success); | ||
popf(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#ifndef REDMAGIC_ASMJIT_WRAP_H_ | ||
#define REDMAGIC_ASMJIT_WRAP_H_ | ||
|
||
#include "jit_internal.h" | ||
#include "constants.h" | ||
#include <asmjit/asmjit.h> | ||
|
||
namespace redmagic { | ||
class SimpleCompiler final : public asmjit::X86Assembler { | ||
public: | ||
SimpleCompiler(CodeBuffer *buffer): | ||
buffer(buffer), | ||
runtime((void*)(buffer->getRawBuffer() + buffer->getOffset()), buffer->getSize() - buffer->getOffset()), | ||
//assembler(&runtime), | ||
buffer_cursor(buffer->getRawBuffer() + buffer->getOffset()), | ||
asmjit::X86Assembler(&runtime) | ||
{ | ||
} | ||
|
||
// trigger generating the code to the buffer; | ||
~SimpleCompiler(); | ||
CodeBuffer finalize(); | ||
|
||
// asmjit::X86Assembler assembler; | ||
|
||
auto& get_register_from_id(int id) { | ||
// take the sys struct register id and convert it to asmjit | ||
using namespace asmjit::x86; | ||
switch(id) { | ||
case R15: return r15; | ||
case R14: return r14; | ||
case R13: return r13; | ||
case R12: return r12; | ||
case RBP: return rbp; | ||
case RBX: return rbx; | ||
case R11: return r11; | ||
case R10: return r10; | ||
case R9: return r9; | ||
case R8: return r8; | ||
case RAX: return rax; | ||
case RCX: return rcx; | ||
case RDX: return rdx; | ||
case RSI: return rsi; | ||
case RDI: return rdi; | ||
//case RIP: return rip; | ||
//case CS: return cs; | ||
// case RSP: return rsp; | ||
// case DS: return ds; | ||
// case ES: return es; | ||
// case FS: return fs; | ||
// case GS: return gs; | ||
} | ||
assert(0); | ||
} | ||
|
||
// stash the register | ||
void protect_register(int id); | ||
void restore_registers(); | ||
void move_stack(int amount); | ||
|
||
// argument of which registers it should avoid when allocating a new scratch register | ||
const asmjit::X86GpReg& get_scratch_register(); | ||
// get the current value of the register | ||
// should be called first since it will add to protection | ||
const asmjit::X86GpReg& get_register(int id); | ||
|
||
void MemToRegister(mem_loc_t where, int reg); | ||
void RegisterToMem(int reg, mem_loc_t where); | ||
void SetRegister(int reg, register_t val); | ||
|
||
void TestRegister(int reg, register_t val); | ||
|
||
private: | ||
CodeBuffer *buffer; | ||
mem_loc_t buffer_cursor; | ||
|
||
// registers that we have clobbered and thus have to restore at the end | ||
uint64_t clobbered_registers = 0; | ||
// registers that our program is using for something | ||
// so dont reallocate these | ||
uint64_t regs_using = 0;; | ||
|
||
int32_t move_stack_by = 0; | ||
|
||
asmjit::StaticRuntime runtime; | ||
|
||
}; | ||
|
||
} | ||
|
||
#endif // REDMAGIC_ASMJIT_WRAP_H_ |
Oops, something went wrong.