Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/tools/superpmi/superpmi/jitinstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class JitInstance
ULONGLONG times[2];
ICorJitCompiler* pJitInstance;

// The loaded JIT module handle. Used to detect when the baseline and diff
// JITs resolve to the same loaded module (which shares global state).
HMODULE getModule() const { return hLib; }

// Allocate and initialize the jit provided
static JitInstance* InitJit(char* nameOfJit,
bool breakOnAssert,
Expand Down
22 changes: 22 additions & 0 deletions src/coreclr/tools/superpmi/superpmi/neardiffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,28 @@ bool NearDiffer::compareOffsets(
return compareOffsetsWasm(payload, blockOffset, instrLen, offset1, offset2);
}

// On arm32 a direct BL is fixed up with an ARM32_THUMB_BRANCH24 reloc. When the
// two code blocks are allocated more than +-16MB apart, applyRelocs substitutes a
// placeholder target for the out-of-range side, so the immediates differ even
// though both BLs target the same recorded address. Treat the sites as equal when
// both recorded the same reloc kind and target.
if (GetSpmiTargetArchitecture() == SPMI_TARGET_ARCHITECTURE_ARM)
{
const DiffData* data = (const DiffData*)payload;

const Agnostic_RecordRelocation* reloc1 =
data->cr1->findRelocationInRange(data->originalBlock1, blockOffset, instrLen);
const Agnostic_RecordRelocation* reloc2 =
data->cr2->findRelocationInRange(data->originalBlock2, blockOffset, instrLen);

if ((reloc1 != nullptr) && (reloc2 != nullptr) && (reloc1->fRelocType == reloc2->fRelocType) &&
((uint64_t)reloc1->target + (int32_t)reloc1->addlDelta ==
(uint64_t)reloc2->target + (int32_t)reloc2->addlDelta))
{
return true;
}
Comment on lines +579 to +584
Comment on lines +579 to +584

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For x64 and arm64 we truncate in CompileResult::applyRelocs:

case CorInfoReloc::ARM64_BRANCH26: // 26 bit offset << 2 & sign ext, for B and BL
{
if ((section_begin <= address) && (address < section_end)) // A reloc for our section?
{
// Similar to x64's IMAGE_REL_BASED_REL32 handling we
// will handle this by also hardcoding the bottom bits
// of the target into the instruction.
PutArm64Rel28((UINT32*)address, (INT32)target);
}
wasRelocHandled = true;

if (retVal == CorInfoReloc::RELATIVE32)
{
LogDebug(" RELATIVE32 target used as argument to getRelocTypeHint: setting delta=%d (0x%X)",
(int)key, (int)key);
delta = (INT64)(int)key;
deltaIsFinal = true;
}

Can we do the same for arm32?

}

const DiffData* data = (const DiffData*)payload;
size_t ip1 = data->originalBlock1 + blockOffset;
size_t ip2 = data->originalBlock2 + blockOffset;
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/tools/superpmi/superpmi/superpmi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,18 @@ int __cdecl main(int argc, char* argv[])
// InitJit already printed a failure message
return (int)SpmiResult::JitFailedToInit;
}

if (jit2->getModule() == jit->getModule())
{
// The baseline and diff JITs resolved to the same loaded module. Because the JIT keeps
// global state (e.g. g_jitHost, JitConfig), sharing a single module between the two
// JitInstances corrupts that state and produces spurious diffs and intermittent crashes.
// Require the two JITs to be distinct files (copy one to a different path if needed).
LogError("The baseline JIT ('%s') and diff JIT ('%s') resolve to the same loaded module. "
"They must be distinct files; copy one JIT to a different path.",
o.nameOfJit, o.nameOfJit2);
return (int)SpmiResult::JitFailedToInit;
}
}
}

Expand Down
Loading