#include <stdio.h>
#include <stdlib.h>
#include <libc.h>
#include <sys/file.h>
#include <dlfcn.h>
#include "llvm-c/Disassembler.h"
#include "stuff/llvm.h"
#include "stuff/allocate.h"
#include <mach-o/dyld.h>
#define LIB_LLVM "libLTO.dylib"
static int tried_to_load_llvm = 0;
static void *llvm_handle = NULL;
static LLVMDisasmContextRef (*create)(const char *, void *, int,
LLVMOpInfoCallback, LLVMSymbolLookupCallback) = NULL;
static void (*dispose)(LLVMDisasmContextRef) = NULL;
static size_t (*disasm)(LLVMDisasmContextRef, uint8_t *, uint64_t, uint64_t,
char *, size_t) = NULL;
__private_extern__
LLVMDisasmContextRef
llvm_create_disasm(
const char *TripleName,
void *DisInfo,
int TagType,
LLVMOpInfoCallback GetOpInfo,
LLVMSymbolLookupCallback SymbolLookUp)
{
size_t bufsize;
char *p, *prefix, *llvm_path, buf[MAXPATHLEN], resolved_name[PATH_MAX];
int i;
LLVMDisasmContextRef DC;
if(tried_to_load_llvm == 0){
tried_to_load_llvm = 1;
bufsize = MAXPATHLEN;
p = buf;
i = _NSGetExecutablePath(p, &bufsize);
if(i == -1){
p = allocate(bufsize);
_NSGetExecutablePath(p, &bufsize);
}
prefix = realpath(p, resolved_name);
p = rindex(prefix, '/');
if(p != NULL)
p[1] = '\0';
llvm_path = makestr(prefix, "../lib/" LIB_LLVM, NULL);
llvm_handle = dlopen(llvm_path, RTLD_NOW);
if(llvm_handle == NULL){
free(llvm_path);
llvm_path = NULL;
llvm_handle = dlopen("/Developer/usr/lib/" LIB_LLVM,
RTLD_NOW);
}
if(llvm_handle == NULL)
return(0);
create = dlsym(llvm_handle, "LLVMCreateDisasm");
dispose = dlsym(llvm_handle, "LLVMDisasmDispose");
disasm = dlsym(llvm_handle, "LLVMDisasmInstruction");
if(create == NULL ||
dispose == NULL ||
disasm == NULL){
dlclose(llvm_handle);
if(llvm_path != NULL)
free(llvm_path);
llvm_handle = NULL;
create = NULL;
dispose = NULL;
disasm = NULL;
return(NULL);
}
}
if(llvm_handle == NULL)
return(NULL);
DC = create(TripleName, DisInfo, TagType, GetOpInfo, SymbolLookUp);
return(DC);
}
__private_extern__
void
llvm_disasm_dispose(
LLVMDisasmContextRef DC)
{
if(dispose != NULL)
dispose(DC);
}
__private_extern__
size_t
llvm_disasm_instruction(
LLVMDisasmContextRef DC,
uint8_t *Bytes,
uint64_t BytesSize,
uint64_t Pc,
char *OutString,
size_t OutStringSize)
{
if(disasm == NULL)
return(0);
return(disasm(DC, Bytes, BytesSize, Pc, OutString, OutStringSize));
}