1#include <stdio.h> 2#include <stdlib.h> 3#include <libc.h> 4#include <sys/file.h> 5#include <dlfcn.h> 6#include "llvm-c/Disassembler.h" 7#include "stuff/llvm.h" 8#include "stuff/allocate.h" 9#include <mach-o/dyld.h> 10 11/* 12 * The disassembler API is currently exported from libLTO.dylib. Eventually we 13 * plan to include it (along with the current libLTO APIs) in a generic 14 * libLLVM.dylib. 15 */ 16#define LIB_LLVM "libLTO.dylib" 17 18static int tried_to_load_llvm = 0; 19static void *llvm_handle = NULL; 20static void (*initialize)(void) = NULL; 21static LLVMDisasmContextRef (*create)(const char *, void *, int, 22 LLVMOpInfoCallback, LLVMSymbolLookupCallback) = NULL; 23static LLVMDisasmContextRef (*createCPU)(const char *, const char *,void *, int, 24 LLVMOpInfoCallback, LLVMSymbolLookupCallback) = NULL; 25static void (*dispose)(LLVMDisasmContextRef) = NULL; 26static size_t (*disasm)(LLVMDisasmContextRef, uint8_t *, uint64_t, uint64_t, 27 char *, size_t) = NULL; 28static int (*options)(LLVMDisasmContextRef, uint64_t) = NULL; 29 30/* 31 * Wrapper to dynamically load LIB_LLVM and call LLVMCreateDisasm(). 32 */ 33__private_extern__ 34LLVMDisasmContextRef 35llvm_create_disasm( 36const char *TripleName, 37const char *CPU, 38void *DisInfo, 39int TagType, 40LLVMOpInfoCallback GetOpInfo, 41LLVMSymbolLookupCallback SymbolLookUp) 42{ 43 uint32_t bufsize; 44 char *p, *prefix, *llvm_path, buf[MAXPATHLEN], resolved_name[PATH_MAX]; 45 int i; 46 LLVMDisasmContextRef DC; 47 48 if(tried_to_load_llvm == 0){ 49 tried_to_load_llvm = 1; 50 /* 51 * Construct the prefix to this executable assuming it is in a bin 52 * directory relative to a lib directory of the matching lto library 53 * and first try to load that. If not then fall back to trying 54 * "/Applications/Xcode.app/Contents/Developer/Toolchains/ 55 * XcodeDefault.xctoolchain/usr/lib/" LIB_LLVM. 56 */ 57 bufsize = MAXPATHLEN; 58 p = buf; 59 i = _NSGetExecutablePath(p, &bufsize); 60 if(i == -1){ 61 p = allocate(bufsize); 62 _NSGetExecutablePath(p, &bufsize); 63 } 64 prefix = realpath(p, resolved_name); 65 p = rindex(prefix, '/'); 66 if(p != NULL) 67 p[1] = '\0'; 68 llvm_path = makestr(prefix, "../lib/" LIB_LLVM, NULL); 69 70 llvm_handle = dlopen(llvm_path, RTLD_NOW); 71 if(llvm_handle == NULL){ 72 free(llvm_path); 73 llvm_path = NULL; 74 llvm_handle = dlopen("/Applications/Xcode.app/Contents/" 75 "Developer/Toolchains/XcodeDefault." 76 "xctoolchain/usr/lib/" LIB_LLVM, 77 RTLD_NOW); 78 } 79 if(llvm_handle == NULL) 80 return(0); 81 82 create = dlsym(llvm_handle, "LLVMCreateDisasm"); 83 dispose = dlsym(llvm_handle, "LLVMDisasmDispose"); 84 disasm = dlsym(llvm_handle, "LLVMDisasmInstruction"); 85 86 /* Note we allow these to not be defined */ 87 options = dlsym(llvm_handle, "LLVMSetDisasmOptions"); 88 createCPU = dlsym(llvm_handle, "LLVMCreateDisasmCPU"); 89 90 if(create == NULL || 91 dispose == NULL || 92 disasm == NULL){ 93 94 dlclose(llvm_handle); 95 if(llvm_path != NULL) 96 free(llvm_path); 97 llvm_handle = NULL; 98 create = NULL; 99 createCPU = NULL; 100 dispose = NULL; 101 disasm = NULL; 102 options = NULL; 103 return(NULL); 104 } 105 } 106 if(llvm_handle == NULL) 107 return(NULL); 108 109 /* 110 * Note this was added after the interface was defined, so it may 111 * be undefined. But if not we must call it first. 112 */ 113 initialize = dlsym(llvm_handle, "lto_initialize_disassembler"); 114 if(initialize != NULL) 115 initialize(); 116 117 if(*CPU != '\0' && createCPU != NULL) 118 DC = createCPU(TripleName, CPU, DisInfo, TagType, GetOpInfo, 119 SymbolLookUp); 120 else 121 DC = create(TripleName, DisInfo, TagType, GetOpInfo, SymbolLookUp); 122 return(DC); 123} 124 125/* 126 * Wrapper to call LLVMDisasmDispose(). 127 */ 128__private_extern__ 129void 130llvm_disasm_dispose( 131LLVMDisasmContextRef DC) 132{ 133 if(dispose != NULL) 134 dispose(DC); 135} 136 137/* 138 * Wrapper to call LLVMDisasmInstruction(). 139 */ 140__private_extern__ 141size_t 142llvm_disasm_instruction( 143LLVMDisasmContextRef DC, 144uint8_t *Bytes, 145uint64_t BytesSize, 146uint64_t Pc, 147char *OutString, 148size_t OutStringSize) 149{ 150 151 if(disasm == NULL) 152 return(0); 153 return(disasm(DC, Bytes, BytesSize, Pc, OutString, OutStringSize)); 154} 155 156/* 157 * Wrapper to call LLVMSetDisasmOptions(). 158 */ 159__private_extern__ 160int 161llvm_disasm_set_options( 162LLVMDisasmContextRef DC, 163uint64_t Options) 164{ 165 166 if(options == NULL) 167 return(0); 168 return(options(DC, Options)); 169} 170