This is an archive of the discontinued LLVM Phabricator instance.

[JITLink][RISCV] Move relax to PostAllocationPasses
ClosedPublic

Authored by jobnoorman on Jul 5 2023, 5:27 AM.

Details

Summary

JITLinkContext is notified (using notifyResolved) of the final
symbol addresses after allocating memory and running the post-allocation
passes. However, linker relaxation, which can cause symbol addresses to
change, was run during the pre-fixup passes. This causes users of
JITLink (e.g., ORC) to pick-up wrong symbol addresses when linker
relaxation was enabled.

This patch fixes this by running relaxation during the post-allocation
passes.

Fixes #63671

@lhames: afaict, llvm-jitlink gathers symbol values during a custom
post-fixup pass [1]. Therefore, it isn't affected by this bug and I'm
not quite sure how to add a test for it. Any suggestions?

[1] https://github.com/llvm/llvm-project/blob/3003da71540bb8483615e18f8ab379da39fa4512/llvm/tools/llvm-jitlink/llvm-jitlink.cpp#L1080-L1082

Diff Detail

Event Timeline

jobnoorman created this revision.Jul 5 2023, 5:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 5 2023, 5:27 AM
Herald added subscribers: asb, luke, pmatos and 28 others. · View Herald Transcript
jobnoorman requested review of this revision.Jul 5 2023, 5:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 5 2023, 5:27 AM

Perfect, solves my issue - thanks for the quick fix!

lhames accepted this revision.Jul 5 2023, 10:52 AM

LGTM.

afaict, llvm-jitlink gathers symbol values during a custom
post-fixup pass [1]. Therefore, it isn't affected by this bug and I'm
not quite sure how to add a test for it. Any suggestions?

One approach would be to move the anonymous pass that calls register<Format>GraphInfo in llvm-jitlink.cpp to the post-allocation phase. If I do that I can immediately see the relaxation testcases failing. That doesn't work in general though because later phases (pre- and post-fixup) might introduce new symbols that llvm-jitlink needs to know about -- I see other testcases breaking because of this.

Maybe we could add a post-allocation pass in llvm-jitlink that records the initial addresses, then have register<Format>GraphInfo throw an error if any of the previously resolved symbols has changed address.

It'd be even better if we could catch this in an assert in LinkGraph itself. If we modified the Section class to have a pointer back to the LinkGraph and modified the LinkGraph to track the phase, then we could write checks like:

void Addressable::setAddress(ExecutorAddr Adds) {
  assert(
    (!isDefined() || static_cast<Block&>(*this).getSection().getGraph().getPhase() < PreFixupPass) &&
    "Cannot change defined symbol address after symbol resolution");
}

I think you can land this without waiting for that though. :)

This revision is now accepted and ready to land.Jul 5 2023, 10:52 AM
This revision was automatically updated to reflect the committed changes.

It'd be even better if we could catch this in an assert in LinkGraph itself. If we modified the Section class to have a pointer back to the LinkGraph and modified the LinkGraph to track the phase, then we could write checks like:

void Addressable::setAddress(ExecutorAddr Adds) {
  assert(
    (!isDefined() || static_cast<Block&>(*this).getSection().getGraph().getPhase() < PreFixupPass) &&
    "Cannot change defined symbol address after symbol resolution");
}

This looks like an interesting approach but just a heads-up that if you were to implement this now, it might break BOLT. We currently reassign section addresses within notifyResolved. I know this is not the correct approach and I have a local fix for it. This is part of a bigger patch though and it hasn't been submitted yet.