gpt4 book ai didi

c - LLVMCreateDisasm 返回 NULL

转载 作者:太空狗 更新时间:2023-10-29 16:56:02 28 4
gpt4 key购买 nike

我正在尝试使用 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.

更新

  1. 我的 llvm 版本是 3.4
  2. 我尝试了所有我能想到的可能的三重/目标,但还是一样。
  3. 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 调用时失败。

  4. 查看 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;
    }
    ...

    原来我必须先初始化一个目标。

  5. 在我的代码中,我首先从 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.htmlhttps://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.

等等(https://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Target.h?logsort=rev&diff_format=h&r1=192697&r2=192696&pathrev=192697)。

甚至还有 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com