我有一个我编写的程序,它使用LLVM 3.5作为JIT编译器,我正在尝试更新以在LLVM 3.7中使用MCJIT。我主要使用它,但我很难重现我用LLVM 3.5实现的一个仅调试功能。
我希望能够看到JIT进程生成的主机代码(例如x86,x64或ARM,而不是LLVM IR);在调试版本中,我在程序运行时将其记录下来。使用LLVM 3.5,我可以通过调用ExecutionEngine :: runJITOnFunction()来填充llvm :: MachineCodeInfo对象,它为我提供了生成代码的起始地址和size 。然后我可以反汇编代码。
我似乎无法在MCJIT中找到任何等效物。我可以得到函数的起始地址(例如通过getPointerToFunction())但不是大小。
我见过Disassemble Memory但除了答案中没有那么多细节之外,它似乎更多的是关于如何反汇编一系列字节。我知道怎么做,我的问题是:我怎样才能掌握字节序列?
如果有助于使其更具体,请将此问题重新解释为:“我如何扩展示例Kaleidoscope JIT以显示它产生的机器代码(x86,ARM等),而不仅仅是LLVM IR?”
感谢。
答案 0 :(得分:1)
这里至少有两个选项。
提供自己的内存管理器。这必须有详细记录,并在许多使用MCJIT的项目中完成。但为了完整起见,这里是代码:
class MCJITMemoryManager : public llvm::RTDyldMemoryManager {
public:
static std::unique_ptr<MCJITMemoryManager> Create();
MCJITMemoryManager();
virtual ~MCJITMemoryManager();
// Allocate a memory block of (at least) the given size suitable for
// executable code. The section_id is a unique identifier assigned by the
// MCJIT engine, and optionally recorded by the memory manager to access a
// loaded section.
byte* allocateCodeSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name) override;
// Allocate a memory block of (at least) the given size suitable for data.
// The SectionID is a unique identifier assigned by the JIT engine, and
// optionally recorded by the memory manager to access a loaded section.
byte* allocateDataSection(uintptr_t size, unsigned alignment,
unsigned section_id, llvm::StringRef section_name,
bool is_readonly) override;
...
}
将内存管理器实例传递给EngineBuilder:
std::unique_ptr<MCJITMemoryManager> manager = MCJITMemoryManager::Create();
llvm::ExecutionEngine* raw = lvm::EngineBuilder(std::move(module))
.setMCJITMemoryManager(std::move(manager))
...
.create();
现在通过这些回调,您可以控制发出代码的内存。 (并且大小会直接传递给您的方法)。只需记住为代码段分配的缓冲区的地址,并在gdb中停止程序并反汇编内存(或将其转储到某处或甚至使用LLVM的反汇编程序)。
llc
并选择适当的选项(优化级别等)。正如我所看到的那样,MCJIT被调用是出于某种原因,原因在于它重用了现有的代码生成模块(与llc相同)。 答案 1 :(得分:0)
包含以下标头llvm/Object/SymbolSize.h
,并使用函数llvm::object::computeSymbolSizes(ObjectFile&)
。您需要以某种方式获取ObjectFile
的实例。
要获得该实例,您可以执行以下操作:
Module
转换为ObjectFile
,类似于:
class ModuleToObjectFileCompiler {
...
// Compile a Module to an ObjectFile.
llvm::object::OwningBinary<llvm::object::ObjectFile>
operator() (llvm::Module&);
};
要实施operator()
的{{1}},请查看已定义班级ModuleToObjectFileCompiler
的{{1}}。
为llvm/ExecutionEngine/Orc/CompileUtils.h
的实例提供SimpleCompiler
的实例,例如:
ModuleToObjectFileCompiler
llvm::orc::IRCompileLayer
的{{1}}会收到您
new llvm::orc::IRCompileLayer
<llvm::orc::ObjectLinkingLayer
<llvm::orc::DoNothingOnNotifyLoaded> >
(_object_layer, _module_to_object_file);
的{{1}}实例。operator()
然后检查返回的ModuleToObjectFileCompiler
以找出ObjectFile
中定义的所有符号的大小(以字节为单位)。保存您感兴趣的符号的信息。这就是全部。