6 #include "llvm-c/Disassembler.h"
7 #include "stuff/llvm.h"
8 #include "stuff/allocate.h"
9 #include <mach-o/dyld.h>
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
16 #define LIB_LLVM "libLTO.dylib"
18 static int tried_to_load_llvm
= 0;
19 static void *llvm_handle
= NULL
;
20 static void (*initialize
)(void) = NULL
;
21 static LLVMDisasmContextRef (*create
)(const char *, void *, int,
22 LLVMOpInfoCallback
, LLVMSymbolLookupCallback
) = NULL
;
23 static LLVMDisasmContextRef (*createCPU
)(const char *, const char *,void *, int,
24 LLVMOpInfoCallback
, LLVMSymbolLookupCallback
) = NULL
;
25 static void (*dispose
)(LLVMDisasmContextRef
) = NULL
;
26 static size_t (*disasm
)(LLVMDisasmContextRef
, uint8_t *, uint64_t, uint64_t,
27 char *, size_t) = NULL
;
28 static int (*options
)(LLVMDisasmContextRef
, uint64_t) = NULL
;
29 static const char * (*version
)(void) = NULL
;
32 * load_llvm() will dynamically load libLTO.dylib if tried_to_load_llvm is 0,
33 * and set llvm_handle to the value returned by dlopen() and set the function
36 static void load_llvm(void)
39 char *p
, *prefix
, *llvm_path
, buf
[MAXPATHLEN
], resolved_name
[PATH_MAX
];
42 if(tried_to_load_llvm
== 0){
43 tried_to_load_llvm
= 1;
45 * Construct the prefix to this executable assuming it is in a bin
46 * directory relative to a lib directory of the matching lto library
47 * and first try to load that. If not then fall back to trying
48 * "/Applications/Xcode.app/Contents/Developer/Toolchains/
49 * XcodeDefault.xctoolchain/usr/lib/" LIB_LLVM.
53 i
= _NSGetExecutablePath(p
, &bufsize
);
55 p
= allocate(bufsize
);
56 _NSGetExecutablePath(p
, &bufsize
);
58 prefix
= realpath(p
, resolved_name
);
59 p
= rindex(prefix
, '/');
62 llvm_path
= makestr(prefix
, "../lib/" LIB_LLVM
, NULL
);
64 llvm_handle
= dlopen(llvm_path
, RTLD_NOW
);
65 if(llvm_handle
== NULL
){
68 llvm_handle
= dlopen("/Applications/Xcode.app/Contents/"
69 "Developer/Toolchains/XcodeDefault."
70 "xctoolchain/usr/lib/" LIB_LLVM
,
73 if(llvm_handle
== NULL
)
76 create
= dlsym(llvm_handle
, "LLVMCreateDisasm");
77 dispose
= dlsym(llvm_handle
, "LLVMDisasmDispose");
78 disasm
= dlsym(llvm_handle
, "LLVMDisasmInstruction");
80 /* Note we allow these to not be defined */
81 options
= dlsym(llvm_handle
, "LLVMSetDisasmOptions");
82 createCPU
= dlsym(llvm_handle
, "LLVMCreateDisasmCPU");
83 version
= dlsym(llvm_handle
, "lto_get_version");
102 if(llvm_handle
== NULL
)
107 * Wrapper to dynamically load LIB_LLVM and call LLVMCreateDisasm().
112 const char *TripleName
,
116 LLVMOpInfoCallback GetOpInfo
,
117 LLVMSymbolLookupCallback SymbolLookUp
)
119 LLVMDisasmContextRef DC
;
121 if(tried_to_load_llvm
== 0){
124 if(llvm_handle
== NULL
)
128 * Note this was added after the interface was defined, so it may
129 * be undefined. But if not we must call it first.
131 initialize
= dlsym(llvm_handle
, "lto_initialize_disassembler");
132 if(initialize
!= NULL
)
135 if(*CPU
!= '\0' && createCPU
!= NULL
)
136 DC
= createCPU(TripleName
, CPU
, DisInfo
, TagType
, GetOpInfo
,
139 DC
= create(TripleName
, DisInfo
, TagType
, GetOpInfo
, SymbolLookUp
);
144 * Wrapper to call LLVMDisasmDispose().
149 LLVMDisasmContextRef DC
)
156 * Wrapper to call LLVMDisasmInstruction().
160 llvm_disasm_instruction(
161 LLVMDisasmContextRef DC
,
166 size_t OutStringSize
)
171 return(disasm(DC
, Bytes
, BytesSize
, Pc
, OutString
, OutStringSize
));
175 * Wrapper to call LLVMSetDisasmOptions().
179 llvm_disasm_set_options(
180 LLVMDisasmContextRef DC
,
186 return(options(DC
, Options
));
190 * Wrapper to call lto_get_version().
194 llvm_disasm_version_string(void)
196 if(tried_to_load_llvm
== 0){
199 if(llvm_handle
== NULL
)