Skip to content

Commit

Permalink
Get function addresses from llvm-compiled code
Browse files Browse the repository at this point in the history
  • Loading branch information
lachlansneff committed Feb 28, 2019
1 parent 5d77769 commit d4ae5cd
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 143 deletions.
46 changes: 20 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions lib/llvm-backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" }
hashbrown = "0.1.8"
smallvec = "0.6.8"
goblin = "0.0.20"
dlopen = "0.1.6"
tempfile = "3.0.7"
libc = "0.2.49"
capstone = "0.5.0"

[build-dependencies]
cc = "1.0"
Expand Down
76 changes: 43 additions & 33 deletions lib/llvm-backend/cpp/object_loader.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "object_loader.hh"
#include <llvm/ExecutionEngine/RuntimeDyld.h>
#include <iostream>
#include <memory>

Expand Down Expand Up @@ -40,20 +39,26 @@ struct MemoryManager : llvm::RuntimeDyld::MemoryManager {
uintptr_t read_write_data_size,
uint32_t read_write_data_align
) override {
uint8_t *ptr_out = nullptr;
size_t size_out = 0;

auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &ptr_out, &size_out);
code_section = Section { ptr_out, size_out };
code_bump_ptr = (uintptr_t)ptr_out;

auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out);
read_section = Section { ptr_out, size_out };
read_bump_ptr = (uintptr_t)ptr_out;

auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out);
readwrite_section = Section { ptr_out, size_out };
readwrite_bump_ptr = (uintptr_t)ptr_out;
uint8_t *code_ptr_out = nullptr;
size_t code_size_out = 0;
auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out);
assert(code_result == RESULT_OK);
code_section = Section { code_ptr_out, code_size_out };
code_bump_ptr = (uintptr_t)code_ptr_out;

uint8_t *read_ptr_out = nullptr;
size_t read_size_out = 0;
auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out);
assert(read_result == RESULT_OK);
read_section = Section { read_ptr_out, read_size_out };
read_bump_ptr = (uintptr_t)read_ptr_out;

uint8_t *readwrite_ptr_out = nullptr;
size_t readwrite_size_out = 0;
auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out);
assert(readwrite_result == RESULT_OK);
readwrite_section = Section { readwrite_ptr_out, readwrite_size_out };
readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out;
}

/* Turn on the `reserveAllocationSpace` callback. */
Expand Down Expand Up @@ -145,32 +150,37 @@ struct SymbolLookup : llvm::JITSymbolResolver {
}
};

class WasmModule {
public:
WasmModule(
WasmModule::WasmModule(
const uint8_t *object_start,
size_t object_size,
callbacks_t *callbacks
) : memory_manager(std::unique_ptr<MemoryManager>(new MemoryManager(callbacks)))
{
object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef(
llvm::StringRef((const char *)object_start, object_size), "object"
)));

) : memory_manager(std::unique_ptr<MemoryManager>(new MemoryManager(callbacks))) {
object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef(
llvm::StringRef((const char *)object_start, object_size), "object"
)));
SymbolLookup symbol_resolver;
llvm::RuntimeDyld loader(*memory_manager, symbol_resolver);

SymbolLookup symbol_resolver;
llvm::RuntimeDyld loader(*memory_manager, symbol_resolver);
loader.setProcessAllSections(true);

loader.setProcessAllSections(true);
auto loaded_object_info = loader.loadObject(*object_file);
loader.finalizeWithMemoryManagerLocking();

auto loaded_object_info = loader.loadObject(*object_file);
loader.finalizeWithMemoryManagerLocking();
assert(!loader.hasError());

assert(!loader.hasError());
symbol_table = loader.getSymbolTable();


for (auto const& pair : symbol_table) {
std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl;
}
}

void* WasmModule::get_func(llvm::StringRef name) const {
try {
return (void*)symbol_table.at(name).getAddress();
} catch (const std::out_of_range& e) {
return nullptr;
}
private:
std::unique_ptr<MemoryManager> memory_manager;
std::unique_ptr<llvm::object::ObjectFile> object_file;
};
}
27 changes: 24 additions & 3 deletions lib/llvm-backend/cpp/object_loader.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <cstddef>
#include <cstdint>
#include <llvm/ExecutionEngine/RuntimeDyld.h>

typedef enum {
PROTECT_NONE,
Expand All @@ -19,7 +20,7 @@ typedef enum {
typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out);
typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect);
typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size);
typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size);
typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr);

typedef struct {
/* Memory management. */
Expand All @@ -30,11 +31,31 @@ typedef struct {
lookup_vm_symbol_t lookup_vm_symbol;
} callbacks_t;



class WasmModule {
public:
WasmModule(
const uint8_t *object_start,
size_t object_size,
callbacks_t *callbacks
);

void *get_func(llvm::StringRef name) const;
private:
std::unique_ptr<llvm::RuntimeDyld::MemoryManager> memory_manager;
std::unique_ptr<llvm::object::ObjectFile> object_file;
std::map<llvm::StringRef, llvm::JITEvaluatedSymbol> symbol_table;
};

extern "C" {
result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) {
result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) {
*module_out = new WasmModule(mem_ptr, mem_size, callbacks);

return RESULT_OK;
}

void test_cpp() {
void* get_func_symbol(WasmModule* module, const char* name) {
return module->get_func(llvm::StringRef(name));
}
}
Loading

0 comments on commit d4ae5cd

Please sign in to comment.