- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用 LLVM 的 C 接口(interface)反汇编一些字节。 但是 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;
}
我在 x64 Linux 上。看着 documentation似乎我做的一切都是对的。
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.
在 lib/MC/MCDisassembler/Disassembler.cpp: LLVMCreateDisasmCPU() 中插入了 printf
它在第一次 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;
}
...
因此它在 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;
}
...
原来我必须先初始化一个目标。
在我的代码中,我首先从 llvm-c/Target.h
header 调用 LLVMInitializeAllTargetInfos();
。现在它在第二次 if
checkin Disassembler.cpp: LLVMCreateDisasmCPU() 时失败
const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
if (!MRI) {
std::cout << "Failed 2: " << Error << std::endl;
return 0;
}
使用此错误
字符串:无法创建反汇编程序
在创建 disasm 上下文之前,我只需要调用 LLVMInitializeAllTargetInfos();
、LLVMInitializeAllTargetMCs();
、LLVMInitializeAllDisassemblers();
:
#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;
}
最佳答案
LLVMCreateDisasm
的第一个参数,
"testname"
无效 TripleName . TripleName 将指示 LLVM 你的目标是什么,这是必需的,因为 LLVM 在单个安装中包含对多个目标的支持。
您可以通过运行命令列出支持的目标架构
llc -version
并且有针对 x86 和 x86_64 的目标
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
要构建正确的 TripleName,您应该为您的目标找到一些好的子架构(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
这里有 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
在同一个文件中有有效的供应商(enum VendorType
)、操作系统类型(enum OSType
)和环境(enum EnvironmentType
)。在大多数情况下,您可以对供应商和操作系统使用“未知”,但通常使用“-unknown-linux-gnu”。
一些有效的 TripleName
示例:
x86_64--linux-gnu
x86_64-unknown-linux-gnu
i486--linux-gnu
这里有更多关于 clang 有效三元组的描述:http://clang.llvm.org/docs/CrossCompilation.html和 https://stackoverflow.com/a/18576360/196561 中列出的一些有效名称
LLVMCreateDisasm
的另一个限制是并非所有 Target 都实现了 MCDisassembler
。例如,在 LLVM-2.9 there are仅适用于 X86、X86_64、ARM 和 MBlaze 的 MCDissassemblers;最近(来自 2014-02-01 的 svn)also for Sparc、PPC、MIPS、SystemZ、XCore 和 AArch64。
如果即使使用正确的三元组也无法创建 MCDisassembler,可以通过多种选项从 MC/MCDisassembler/Disassembler.cpp 文件中调试 LLVMCreateDisasmCPU
函数。您可以使用 gdb 进入,然后执行“next”-stepping 直到出现错误(使用 LLVM 的调试版本会更漂亮、更容易);或者您可以将一些调试 printf 添加到 LLVMCreateDisasmCPU
中,或者从纯 NULL 信息临时更改返回值,每个错误都有一些不同。
更新:您的 LLVM 似乎在调用时未初始化。 llvm-c/Target.h 中有很多 LLVM Initializers当前 LLVM(~3.4 或更新版本)中的 header :
LLVMInitializeAllTargetInfos()
- The main program should call this function if it wants access to all available targets that LLVM is configured to support.
LLVMInitializeAllTargets()
- The main program should call this function if it wants to link in all available targets that LLVM is configured to support.
LLVMInitializeAllTargetMCs()
- The main program should call this function if it wants access to all available target MC that LLVM is configured to support.
LLVMInitializeAllDisassemblers()
- The main program should call this function if it wants all disassemblers that LLVM is configured to support, to make them available via the TargetRegistry.
LLVMInitializeAllAsmPrinters()
- The main program should call this function if it wants all asm printers that LLVM is configured to support, to make them available via the TargetRegistry.
甚至还有 LLVMInitializeNativeTarget
函数初始化原生目标:
LLVMInitializeNativeTarget()
- The main program should call this function to initialize the native target corresponding to the host. This is useful for JIT applications to ensure that the target gets linked in correctly.
关于c - LLVMCreateDisasm 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21462853/
我正在尝试使用 LLVM 的 C 接口(interface)反汇编一些字节。 但是 LLVMCreateDisasm() 返回 NULL。 #include // printf() #include
我是一名优秀的程序员,十分优秀!