How can I parse the LLVM MCJIT compilation result?

I have a program that I wrote that uses LLVM 3.5 as a JIT compiler, which I am trying to upgrade to use MCJIT in LLVM 3.7. This basically works for me, but I'm struggling to reproduce one debugging function implemented with LLVM 3.5.

I would like to see the host machine code (for example, x86, x64 or ARM, not the LLVM IR) generated by the JIT process; in debug builds I log this when my program is running. With LLVM 3.5, I was able to do this by calling ExecutionEngine :: runJITOnFunction () to populate the llvm :: MachineCodeInfo object, which gave me the starting address and size of the generated code. Then I could parse this code.

I can not find the equivalent in MCJIT. I can get the start address of the function (e.g. via getPointerToFunction ()), but not the size.

I have seen disassemble the memory , but besides the fact that the answers do not have so many details, it looks like it's more about how to parse a sequence of bytes. I know how to do this, my question is: how can I get a sequence of bytes in the first place?

If this helps to make it more specific, please reformulate this question as follows: "How can I extend the Kaleidoscope JIT example to show the machine code (x86, ARM, etc.) that it produces, and not just LLVM IR? "

Thanks.

+4
source share
2 answers

.

  • . 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 LLVM IR ( ..). , MCJIT - , , ( , llc).
+1

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() of ModuleToObjectFileCompiler, llvm/ExecutionEngine/Orc/CompileUtils.h, SimpleCompiler.

  • ModuleToObjectFileCompiler llvm::orc::IRCompileLayer, : new llvm::orc::IRCompileLayer <llvm::orc::ObjectLinkingLayer <llvm::orc::DoNothingOnNotifyLoaded> > (_object_layer, _module_to_object_file);

  • operator() of ModuleToObjectFileCompiler ObjectFile, computeSymbolSizes(). std::vector, , Module. . .

0

Source: https://habr.com/ru/post/1620837/


All Articles