HomePhabricator

[Orc] Add JITLink debug support plugin for ELF x86-64

Authored by sgraenitz on Mar 2 2021, 3:37 AM.

Description

[Orc] Add JITLink debug support plugin for ELF x86-64

Add a new ObjectLinkingLayer plugin DebugObjectManagerPlugin and infrastructure to handle creation of DebugObjects as well as their registration in OrcTargetProcess. The current implementation only covers ELF on x86-64, but the infrastructure is not limited to that.

The journey starts with a new LinkGraph / JITLinkContext pair being created for a MaterializationResponsibility in ORC's ObjectLinkingLayer. It sends a notifyMaterializing() notification, which is forwarded to all registered plugins. The DebugObjectManagerPlugin aims to create a DebugObject form the provided target triple and object buffer. (Future implementations might create DebugObjects from a LinkGraph in other ways.) On success it will track it as the pending DebugObject for the MaterializationResponsibility.

This patch only implements the ELFDebugObject for x86-64 targets. It follows the RuntimeDyld approach for debug object setup: it captures a copy of the input object, parses all section headers and prepares to patch their load-address fields with their final addresses in target memory. It instructs the plugin to report the section load-addresses once they are available. The plugin overrides modifyPassConfig() and installs a JITLink post-allocation pass to capture them.

Once JITLink emitted the finalized executable, the plugin emits and registers the DebugObject. For emission it requests a new JITLinkMemoryManager::Allocation with a single read-only segment, copies the object with patched section load-addresses over to working memory and triggers finalization to target memory. For registration, it notifies the DebugObjectRegistrar provided in the constructor and stores the previously pending`DebugObject` as registered for the corresponding MaterializationResponsibility.

The DebugObjectRegistrar registers the DebugObject with the target process. llvm-jitlink uses the TPCDebugObjectRegistrar, which calls llvm_orc_registerJITLoaderGDBWrapper() in the target process via TargetProcessControl to emit a jit_code_entry compatible with the GDB JIT interface [1]. So far the implementation only supports registration and no removal. It appears to me that it wouldn't raise any new design questions, so I left this as an addition for the near future.

[1] https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D97335