[PATCH] D96627: [llvm-jitlink] Implement JITLoaderGDB ObjectLinkingLayer plugin for ELF x86-64

Lang Hames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 14 16:00:22 PST 2021


lhames added a comment.

In D96627#2562274 <https://reviews.llvm.org/D96627#2562274>, @sgraenitz wrote:

> Hi Lang, thanks for your feedback!
>
> In D96627#2561402 <https://reviews.llvm.org/D96627#2561402>, @lhames wrote:
>
>> (2) If we constructed the debug object file from scratch (rather than mutating the existing one)
>
> Let me see if I understand that right. At the moment LinkGraphBuilder skips DWARF sections in createNormalizedSections() so they will not appear in the linker's resulting target memory allocation. Instead we decide about requesting the debug object i the plugin after we built the LinkGraph and make a separate allocation for it. You propose that we could change that and let the LinkGraph prepare the debug sections in a format that could be passed to the debugger? The plugin could query the target memory addresses from the LinkGraph and pass them to the debugger.

That's not quite what I had in mind (though it's also something we could discuss).

What I meant was that right now RuntimeDyld copies the entire incoming object (text, data and all) then mutates the load addresses in the header and passes the resulting object to the debugger. What I'm suggesting is that we consider constructing a new object file (ELF, MachO, COFF) from scratch to hold the debug info that we want to pass to the debugger. This synthesized object file should (ideally) not need to carry anything but the headers and debug info. How we transport that to the target process would be a separate question.

> I think we'd still need to patch section addresses to inform the debugger about final locations, but otherwise it sounds reasonable.

In the scheme I'm suggesting we'd just be synthesizing new load commands for the sections in the LinkGraph. This would be a post-allocation pass, so we could inspect the graph to see where each section referred to by the debug info starts and ends.

> We will need a way to tell the LinkGraphBuilder whether or not to include them (i.e. the ObjectLinkingLayer plugin is present/enabled or not) in order to avoid overhead in non-debug sessions right? ObjectLinkingLayer::emit() could accomplish it by passing a flag to createLinkGraphFromObject(), but I don't see a way to hook into it from a plugin context currently. How could we solve that?

I think the aim would be that we just don't install the debugging support plugin if debugging is not enabled.

>> (1) We shouldn't special-case the JITLinkContext callbacks except as a last resort.
>
> We'd avoid the extra callback parameter in notifyLoaded(), but we'd need some other API function instead. Or would you propose not to use an ObjectLinkingLayer plugin altogether?

No, this should definitely be an object linking layer plugin, but I think we should be synthesizing / modifying the debug object in a jitlink pass installed by the plugin. That's the way EH-frame registration now works in the runtime prototype: https://github.com/lhames/llvm-project/blob/315f9f15e7233a5c956022201ac898f94196802a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp#L825 .

>> - support debug info for raw LinkGraphs (very attractive for long term performance -- avoids serializing / deserializing to objects),
>
> Oh interesting. Thinking about synthetic debug info for compiler/linker injected code..

Exactly. One day

>> - reduce memory usage by not redundantly representing non-debug sections in the debug object
>
> I think we could already strip them in the current approach. LLDB at least doesn't seem to touch it.

Yeah. I think we're converging on the same solution from different ends: You can think of this as stripping the incoming object back to contain only what's needed for the debugger, or you can think of it as building up a new object (using some source of debug info) for the debugger. The latter generalizes to support debug info in LinkGraphs.

If we take the synthesizing-a-new-object approach it means that we'll need to represent the debug info in the graphs, at least initially. I guess a sketch of the approach would look like this:

(1) LinkGraphBuilders stop skipping debug info (this adds some overhead in the case where objects have debug info, but debug info is not used by the JIT. I think that's tolerable for now, we can revisit later if we want to make this optional).
(2) JITLinkGDBLoaderPlugin installs two plugins that cooperate to synthesize and register a debug object:

  (2.1) A pre-allocation pass synthesizes a debug object by copying the data out of the debug sections in the graph. In the synthesized object section and symbol target addresses are initially zero. The pass then deletes the debug sections from the graph.
  (2.2) A post-allocation pass mutates the synthesized debug object based on the final target addresses in the graph. It then calls the runtime to register the debug info with the gdb registration API.

Does that sound reasonable?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96627/new/

https://reviews.llvm.org/D96627



More information about the llvm-commits mailing list