Bab*_*yan 9 c llvm disassembly
我试图使用LLVM的C接口反汇编一些字节.但是LLVMCreateDisasm()返回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;
}
Run Code Online (Sandbox Code Playgroud)
我在x64 Linux上.查看文档似乎我正在做的一切正确.
LLVMDisasmContextRef LLVMCreateDisasm (
const char * TripleName,
void * DisInfo,
int TagType,
LLVMOpInfoCallback GetOpInfo,
LLVMSymbolLookupCallback SymbolLookUp
)
Run Code Online (Sandbox Code Playgroud)
为TripleName创建反汇编程序.通过在DisInfo参数中传递信息块并指定TagType和回调函数来支持符号反汇编,如上所述.这些都可以作为NULL传递.如果成功,则返回反汇编程序上下文.如果不是,则返回NULL.
printf在lib/MC/MCDisassembler/Disassembler.cpp:LLVMCreateDisasmCPU()中插入,并在首次if检查时失败.Error那一点的字符串是"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;
}
...
Run Code Online (Sandbox Code Playgroud)
所以它在lookupTarget通话中失败了.
查看lib/Support/TargetRegistry.cpp:lookupTarget()在第一次if检查时失败.那里的评论提供了一些线索:
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;
}
...
Run Code Online (Sandbox Code Playgroud)
所以事实证明我必须首先初始化目标.
在我的代码中,我首先LLVMInitializeAllTargetInfos();从llvm-c/Target.h标题中调用.现在它if在Disassembler.cpp中的第二次检查失败:LLVMCreateDisasmCPU()
const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
if (!MRI) {
std::cout << "Failed 2: " << Error << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用这个Error字符串:Could not create disassembler
我刚打电话LLVMInitializeAllTargetInfos();,LLVMInitializeAllTargetMCs();,LLVMInitializeAllDisassemblers();创造DISASM上下文之前:
#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;
}
Run Code Online (Sandbox Code Playgroud)
第一个论点LLVMCreateDisasm,
"testname"
Run Code Online (Sandbox Code Playgroud)
是无效的TripleName.TripleName将指示LLVM您的目标是什么,这是必需的,因为LLVM在单个安装中包含对多个目标的支持.
您可以通过运行命令列出支持的目标体系结构
llc -version
Run Code Online (Sandbox Code Playgroud)
并且有x86和x86_64的目标
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
Run Code Online (Sandbox Code Playgroud)
要构建正确的TripleName,您应该为您的目标找到一些好的子shell(i486或x86_64),然后添加供应商和操作系统:
http://llvm.org/docs/doxygen/html/Triple_8h_source.html
00022 /// Triple - Helper class for working with autoconf configuration names. For
00023 /// historical reasons, we also call these 'triples' (they used to contain
00024 /// exactly three fields).
00025 ///
00026 /// Configuration names are strings in the canonical form:
00027 /// ARCHITECTURE-VENDOR-OPERATING_SYSTEM
00028 /// or
00029 /// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT
Run Code Online (Sandbox Code Playgroud)
这里有ArchType枚举,注释中已识别的Arch列表(实际的解析器是lib/Support/Triple.cpp - parseArch),就像
arm, // ARM: arm, armv.*, xscale
aarch64, // AArch64: aarch64
....
x86, // X86: i[3-9]86
x86_64, // X86-64: amd64, x86_64
Run Code Online (Sandbox Code Playgroud)
在同一个文件中有有效的vendor(enum VendorType),OS types(enum OSType)和Envronments(enum EnvironmentType).在大多数情况下,您可以为vendor和os使用"unknown",但通常使用"-unknown-linux-gnu".
一些有效TripleName的例子:
x86_64--linux-gnu
x86_64-unknown-linux-gnu
i486--linux-gnu
Run Code Online (Sandbox Code Playgroud)
这里有更多关于clang的有效三元组的描述:http://clang.llvm.org/docs/CrossCompilation.html以及/sf/answers/1300345231/中列出的一些有效名称
另一个限制 LLVMCreateDisasm是并非所有目标都已MCDisassembler实施.例如,在LLVM-2.9中,只有X86,X86_64,ARM和MBlaze有MCDissasemblers; 最近(2014年2月1日), Sparc,PPC,MIPS,SystemZ,XCore和AArch64.
如果即使使用正确的三元组也无法创建MCDisassembler,有几个选项可以LLVMCreateDisasmCPU从MC/MCDisassembler/Disassembler.cpp文件调试该函数.您可以使用gdb进入,然后执行"下一步" - 执行直到出现错误(使用LLVM的调试版本,这将更加美观和简单); 或者你可以LLVMCreateDisasmCPU从普通的NULL信息中添加一些调试printf到临时更改返回值,每个错误都有一些不同.
更新:似乎您的LLVM在通话时未初始化.当前LLVM(~3.4或更新版本)中的llvm-c/Target.h头中有许多LLVM初始值设定项:
LLVMInitializeAllTargetInfos()- 如果主程序想要访问LLVM配置为支持的所有可用目标,则应调用此函数.
LLVMInitializeAllTargets()- 如果主程序要链接LLVM配置为支持的所有可用目标,则应调用此函数.
LLVMInitializeAllTargetMCs()- 如果主程序要访问LLVM配置为支持的所有可用目标MC,则应调用此函数.
LLVMInitializeAllDisassemblers()- 主程序应该调用此函数,如果它想要LLVM配置为支持的所有反汇编程序,则通过TargetRegistry使它们可用.
LLVMInitializeAllAsmPrinters()- 主程序应该调用此函数,如果它想要LLVM配置为支持的所有asm打印机,则通过TargetRegistry使它们可用.
甚至还有LLVMInitializeNativeTarget初始化本机目标的函数:
LLVMInitializeNativeTarget()- 主程序应调用此函数来初始化与主机对应的本机目标.这对于JIT应用程序非常有用,可以确保正确链接目标.
| 归档时间: |
|
| 查看次数: |
529 次 |
| 最近记录: |