I am trying to disassemble some bytes using LLVM's C interface .
However LLVMCreateDisasm()
returns NULL.
#include <stdio.h> // printf()
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS
#define __STDC_CONSTANT_MACROS // llvm complains otherwise
#define __STDC_LIMIT_MACROS
#include <llvm-c/Disassembler.h>
int main()
{
LLVMDisasmContextRef dc = LLVMCreateDisasm (
"testname",
NULL,
0,
NULL,
NULL
);
if (dc == NULL) {
printf("Could not create disassembler");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I am on x64 Linux. Looking at the documentation seems like I am doing everything right.
LLVMDisasmContextRef LLVMCreateDisasm (
const char * TripleName,
void * DisInfo,
int TagType,
LLVMOpInfoCallback GetOpInfo,
LLVMSymbolLookupCallback SymbolLookUp
)
Create a disassembler for the TripleName. Symbolic disassembly is supported by passing a block of information in the DisInfo parameter and specifying the TagType and callback functions as described above. These can all be passed as NULL. If successful, this returns a disassembler context. If not, it returns NULL.
Update
- My llvm version is 3.4
- I tried every possible triple/target I could think of, still the same.
Inserted
printf
's in lib/MC/MCDisassembler/Disassembler.cpp: LLVMCreateDisasmCPU() and it fails upon firstif
check. TheError
string at that point is"Unable to find target for this triple (no targets are registered)"
LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp){ std::cout << ">>> Triplename: " << Triple << std::endl; // Get the target. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); if (!TheTarget) { std::cout << "Failed 1: " << Error << std::endl; return 0; } ...
So it fails at
lookupTarget
call.Looking at lib/Support/TargetRegistry.cpp: lookupTarget() it fails upon first
if
check. The comment there gives some clues:const Target *TargetRegistry::lookupTarget(const std::string &TT, std::string &Error) { // Provide special warning when no targets are initialized. if (begin() == end()) { Error = "Unable to find target for this triple (no targets are registered)"; return 0; } ...
So it turns out I have to initialize a target first.
In my code I first call
LLVMInitializeAllTargetInfos();
from thellvm-c/Target.h
header. Now it fails on secondif
check in Disassembler.cpp: LLVMCreateDisasmCPU()const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple); if (!MRI) { std::cout << "Failed 2: " << Error << std::endl; return 0; }
with this
Error
string:Could not create disassembler
Finally Solved!
I just had to call LLVMInitializeAllTargetInfos();
, LLVMInitializeAllTargetMCs();
, LLVMInitializeAllDisassemblers();
before creating disasm context:
#include <stdio.h> // printf()
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS
#define __STDC_CONSTANT_MACROS // llvm complains otherwise
#define __STDC_LIMIT_MACROS
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
int main()
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
LLVMDisasmContextRef dc = LLVMCreateDisasm (
"x86_64-unknown-linux-gnu",
NULL,
0,
NULL,
NULL
);
if (dc == NULL) {
printf("Could not create disassembler");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}