Skip to content

Verify correctness of the TR_RelativeMethodAddress relo record #12653

@dsouzai

Description

@dsouzai

When generating a TR_RelativeMethodAddress relo reocrd, the eipRelative flag is set.

rmaRecord->setEipRelative(reloTarget);

When relocating, the TR_RelocationRecordMethodAddress API class is used:

case TR_RelativeMethodAddress:
case TR_AbsoluteMethodAddress:
case TR_AbsoluteMethodAddressOrderedPair:
reloRecord = new (storage) TR_RelocationRecordMethodAddress(reloRuntime, record);

Because the eipRelative flag is set, loadCallTarget is called:

TR_RelocationRecordMethodAddress::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation)
{
bool eipRel = eipRelative(reloTarget);
uint8_t *oldAddress;
if (eipRel)
oldAddress = reloTarget->loadCallTarget(reloLocation);

uint8_t *
TR_RelocationTarget::loadCallTarget(uint8_t *reloLocation)
{
return loadPointer(reloLocation);
}

which in turn calls loadPointer:

virtual uint8_t *loadPointer(uint8_t *address) { return *(uint8_t**) address; }

So, in 64 bit, it loads a 64bit value out of the instruction in the code. It relocates it via the call to currentMethodAddress:

TR_RelocationRecordMethodAddress::currentMethodAddress(TR_RelocationRuntime *reloRuntime, uint8_t *oldMethodAddress)
{
TR_AOTMethodHeader *methodHdr = reloRuntime->aotMethodHeaderEntry();
return oldMethodAddress - methodHdr->compileMethodCodeStartPC + (uintptr_t) reloRuntime->newMethodCodeStart();
}

and then updates the code via:

if (eipRel)
reloTarget->storeCallTarget((uintptr_t)newAddress, reloLocation);

which calls storeCallTarget:
TR_X86RelocationTarget::storeCallTarget(uintptr_t callTarget, uint8_t *reloLocation)
{
// reloLocation points at the start of the call offset, so just store the uint8_t * at reloLocation
storeUnsigned32b((uint32_t)callTarget, reloLocation);
}

However, storeCallTarget stores a 32-bit unsigned value.

The fact that a 32-bit value is stored is not necessarily the problem, but it's the fact that a 64 bit value was loaded, had arithmetic performed on it, and then a 32-bit value is stored back. As such, I don't think this relocation is correct.

The only place this relocation is generated is in https://github.com/eclipse/omr/blob/83e28dc0dcdcf8d9a751cc2b8567fcc8acc30e84/compiler/x/codegen/X86BinaryEncoding.cpp#L1111

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions