diff --git a/compiler/runtime/OMRExternalRelocationsKindToHeaderSizeMap.hpp b/compiler/runtime/OMRExternalRelocationsKindToHeaderSizeMap.hpp new file mode 100644 index 00000000000..6cf88b3f427 --- /dev/null +++ b/compiler/runtime/OMRExternalRelocationsKindToHeaderSizeMap.hpp @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at http://eclipse.org/legal/epl-2.0 + * or the Apache License, Version 2.0 which accompanies this distribution + * and is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License, v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception [1] and GNU General Public + * License, version 2 with the OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +// The project specific relocation header sizes should be included to at end of this file +#if defined (TR_HOST_64BIT) + 24, // TR_ConstantPool = 0 + 8, // TR_HelperAddress = 1 + 24, // TR_RelativeMethodAddress = 2 + 8, // TR_AbsoluteMethodAddress = 3 + 0, // TR_DataAddress = 4 + 24, // TR_ClassObject = 5 + 24, // TR_MethodObject = 6 + 24, // TR_InterfaceObject = 7 + 8, // TR_AbsoluteHelperAddress = 8 + 16, // TR_FixedSeqAddress = 9 + 16, // TR_FixedSeq2Address = 10 + 32, // TR_JNIVirtualTargetAddress = 11 + 32, // TR_JNIStaticTargetAddress = 12 + 4, // Dummy for TR_ArrayCopyHelper = 13 + 4, // Dummy for TR_ArrayCopyToc = 14 + 8, // TR_BodyInfoAddress = 15 + 24, // TR_Thunks = 16 + 32, // TR_StaticRamMethodConst = 17 + 24, // TR_Trampolines = 18 + 8, // TR_PicTrampolines = 19 + 16, // TR_CheckMethodEnter = 20 + 8, // TR_RamMethod = 21 + 16, // TR_RamMethodSequence = 22 + 16, // TR_RamMethodSequenceReg = 23 + 48, // TR_VerifyClassObjectForAlloc = 24 + 24, // TR_ConstantPoolOrderedPair = 25 + 8, // TR_AbsoluteMethodAddressOrderedPair = 26 + 40, // TR_VerifyRefArrayForAlloc = 27 + 24, // TR_J2IThunks = 28 + 16, // TR_GlobalValue = 29 + 4, // dummy for TR_BodyInfoAddress = 30 + 40, // TR_ValidateInstanceField = 31 + 48, // TR_InlinedStaticMethodWithNopGuard = 32 + 48, // TR_InlinedSpecialMethodWithNopGuard = 33 + 48, // TR_InlinedVirtualMethodWithNopGuard = 34 + 48, // TR_InlinedInterfaceMethodWithNopGuard = 35 + 32, // TR_SpecialRamMethodConst = 36 + 48, // TR_InlinedHCRMethod = 37 + 40, // TR_ValidateStaticField = 38 + 40, // TR_ValidateClass = 39 + 32, // TR_ClassAddress = 40 + 16, // TR_HCR = 41 + 64, // TR_ProfiledMethodGuardRelocation = 42 + 64, // TR_ProfiledClassGuardRelocation = 43 + 0, // TR_HierarchyGuardRelocation = 44 + 0, // TR_AbstractGuardRelocation = 45 + 64, // TR_ProfiledInlinedMethodRelocation = 46 + 40, // TR_MethodPointer = 47 + 32, // TR_ClassPointer = 48 + 16, // TR_CheckMethodExit = 49 + 24, // TR_ValidateArbitraryClass = 50 + 0, // TR_EmitClass(not used) = 51 + 32, // TR_JNISpecialTargetAddress = 52 + 32, // TR_VirtualRamMethodConst = 53 + 40, // TR_InlinedInterfaceMethod = 54 + 40, // TR_InlinedVirtualMethod = 55 + 0, // TR_NativeMethodAbsolute = 56, + 0, // TR_NativeMethodRelative = 57, + 32, // TR_ArbitraryClassAddress = 58, + 56, // TR_DebugCounter = 59 + 8, // TR_ClassUnloadAssumption = 60 + 32, // TR_J2IVirtualThunkPointer = 61, + 48, // TR_InlinedAbstractMethodWithNopGuard = 62, + 0, // TR_ValidateRootClass = 63, +0, // sizeof(TR_RelocationRecordValidateClassByNameBinaryTemplate), // TR_ValidateClassByName = 64, +0, // sizeof(TR_RelocationRecordValidateProfiledClassBinaryTemplate), // TR_ValidateProfiledClass = 65, +0, // sizeof(TR_RelocationRecordValidateClassFromCPBinaryTemplate), // TR_ValidateClassFromCP = 66, +0, // sizeof(TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate),//TR_ValidateDefiningClassFromCP = 67, +0, // sizeof(TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate), // TR_ValidateStaticClassFromCP = 68, + 0, // TR_ValidateClassFromMethod = 69, + 0, // TR_ValidateComponentClassFromArrayClass= 70, +0, // sizeof(TR_RelocationRecordValidateArrayFromCompBinaryTemplate), // TR_ValidateArrayClassFromComponentClass= 71, +0, // sizeof(TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate),//TR_ValidateSuperClassFromClass = 72, +0, // sizeof(TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate),//TR_ValidateClassInstanceOfClass = 73, +0, // sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate), //TR_ValidateSystemClassByName = 74, +0, // sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate),//TR_ValidateClassFromITableIndexCP = 75, +0, // sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate),//TR_ValidateDeclaringClassFromFieldOrStatic=76, + 0, // TR_ValidateClassClass = 77, +0, // sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate),//TR_ValidateConcreteSubClassFromClass = 78, +0, // sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate), // TR_ValidateClassChain = 79, + 0, // TR_ValidateRomClass = 80, + 0, // TR_ValidatePrimitiveClass = 81, + 0, // TR_ValidateMethodFromInlinedSite = 82, + 0, // TR_ValidatedMethodByName = 83, +0, // sizeof(TR_RelocationRecordValidateMethodFromClassBinaryTemplate), // TR_ValidatedMethodFromClass = 84, +0, // sizeof(TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate),// TR_ValidateStaticMethodFromCP = 85, +0, // sizeof(TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate),//TR_ValidateSpecialMethodFromCP = 86, +0, // sizeof(TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate),//TR_ValidateVirtualMethodFromCP = 87, +0, // sizeof(TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate),//TR_ValidateVirtualMethodFromOffset = 88, +0, // sizeof(TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate),//TR_ValidateInterfaceMethodFromCP = 89, +0, // sizeof(TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate),//TR_ValidateMethodFromClassAndSig = 90, +0, // sizeof(TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate),//TR_ValidateStackWalkerMaySkipFramesRecord= 91, + 0, // TR_ValidateArrayClassFromJavaVM = 92, +0, // sizeof(TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate),//TR_ValidateClassInfoIsInitialized = 93, +0, // sizeof(TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate),//TR_ValidateMethodFromSingleImplementer= 94, +0, // sizeof(TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate),//TR_ValidateMethodFromSingleInterfaceImplementer= 95, +0, // sizeof(TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate),//TR_ValidateMethodFromSingleAbstractImplementer= 96, +0, // sizeof(TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate),//TR_ValidateImproperInterfaceMethodFromCP= 97, +0, // sizeof(TR_RelocationRecordSymbolFromManagerBinaryTemplate), // TR_SymbolFromManager = 98, +0, //100 +0, // 101 +#else + + 12, // TR_ConstantPool = 0 + 8, // TR_HelperAddress = 1 + 12, // TR_RelativeMethodAddress = 2 + 4, // TR_AbsoluteMethodAddress = 3 + 20, // TR_DataAddress = 4 + 12, // TR_ClassObject = 5 + 12, // TR_MethodObject = 6 + 12, // TR_InterfaceObject = 7 + 8, // TR_AbsoluteHelperAddress = 8 + 8, // TR_FixedSeqAddress = 9 + 8, // TR_FixedSeq2Address = 10 + 16, // TR_JNIVirtualTargetAddress = 11 + 16, // TR_JNIStaticTargetAddress = 12 + 4, // Dummy for TR_ArrayCopyHelper = 13 + 4, // Dummy for TR_ArrayCopyToc = 14 + 4, // TR_BodyInfoAddress = 15 + 12, // TR_Thunks = 16 + 16, // TR_StaticRamMethodConst = 17 + 12, // TR_Trampolines = 18 + 8, // TR_PicTrampolines = 19 + 8, // TR_CheckMethodEnter = 20 + 4, // TR_RamMethod = 21 + 8, // TR_RamMethodSequence = 22 + 8, // TR_RamMethodSequenceReg = 23 + 24, // TR_VerifyClassObjectForAlloc = 24 + 12, // TR_ConstantPoolOrderedPair = 25 + 8, // TR_AbsoluteMethodAddressOrderedPair = 26 + 20, // TR_VerifyRefArrayForAlloc = 27 + 12, // TR_J2IThunks = 28 + 8, // TR_GlobalValue = 29 + 4, // TR_BodyInfoAddressLoad = 30 + 20, // TR_ValidateInstanceField = 31 + 24, // TR_InlinedStaticMethodWithNopGuard = 32 + 24, // TR_InlinedSpecialMethodWithNopGuard = 33 + 24, // TR_InlinedVirtualMethodWithNopGuard = 34 + 24, // TR_InlinedInterfaceMethodWithNopGuard = 35 + 16, // TR_SpecialRamMethodConst = 36 + 24, // TR_InlinedHCRMethod = 37 + 20, // TR_ValidateStaticField = 38 + 20, // TR_ValidateClass = 39 + 16, // TR_ClassAddress = 40 + 8, // TR_HCR = 41 + 32, // TR_ProfiledMethodGuardRelocation = 42 + 32, // TR_ProfiledClassGuardRelocation = 43 + 0, // TR_HierarchyGuardRelocation = 44 + 0, // TR_AbstractGuardRelocation = 45 + 32, // TR_ProfiledInlinedMethodRelocation = 46 + 20, // TR_MethodPointer = 47 + 16, // TR_ClassPointer = 48 + 8, // TR_CheckMethodExit = 49 + 12, // TR_ValidateArbitraryClass = 50 + 0, // TR_EmitClass(not used) = 51 + 16, // TR_JNISpecialTargetAddress = 52 + 16, // TR_VirtualRamMethodConst = 53 + 20, // TR_InlinedInterfaceMethod = 54 + 20, // TR_InlinedVirtualMethod = 55 + 0, // TR_NativeMethodAbsolute = 56, + 0, // TR_NativeMethodRelative = 57, + 16, // TR_ArbitraryClassAddress = 58, + 28, // TR_DebugCounter = 59 + 4, // TR_ClassUnloadAssumption = 60 + 16, // TR_J2IVirtualThunkPointer = 61, + 24, // TR_InlinedAbstractMethodWithNopGuard = 62, +#endiflinedAbstractMethodWithNopGuard = 62, +#endif \ No newline at end of file diff --git a/compiler/runtime/OMRRelocationRecord.cpp b/compiler/runtime/OMRRelocationRecord.cpp new file mode 100644 index 00000000000..aa00e673341 --- /dev/null +++ b/compiler/runtime/OMRRelocationRecord.cpp @@ -0,0 +1,402 @@ + /******************************************************************************* + * Copyright (c) 2000, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +#include +#include +#include +#include "omrcfg.h" +#include "codegen/CodeGenerator.hpp" +#include "codegen/FrontEnd.hpp" +#include "codegen/Relocation.hpp" +#include "compile/ResolvedMethod.hpp" +#include "control/Options.hpp" +#include "control/Options_inlines.hpp" +#include "infra/Assert.hpp" +#include "env/jittypes.h" +#include "env/VMAccessCriticalSection.hpp" +#include "il/symbol/StaticSymbol.hpp" +#include "infra/SimpleRegex.hpp" +#include "runtime/CodeCache.hpp" +#include "runtime/CodeCacheManager.hpp" +#include "runtime/RelocationRecord.hpp" +#include "runtime/RelocationRuntime.hpp" +#include "runtime/RelocationTarget.hpp" +#include "runtime/OMRRelocationRecord.hpp" + +// TODO: move this someplace common for RuntimeAssumptions.cpp and here +#if defined(__IBMCPP__) && !defined(AIXPPC) && !defined(LINUXPPC) +#define ASM_CALL __cdecl +#else +#define ASM_CALL +#endif +#if defined(TR_HOST_S390) || defined(TR_HOST_X86) // gotten from RuntimeAssumptions.cpp, should common these up +extern "C" void _patchVirtualGuard(uint8_t *locationAddr, uint8_t *destinationAddr, int32_t smpFlag); +#else +extern "C" void ASM_CALL _patchVirtualGuard(uint8_t*, uint8_t*, uint32_t); +#endif + +uint8_t +OMR::RelocationRecordBinaryTemplate::type(TR::RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned8b(&_type); + } + +void +OMR::RelocationRecordBinaryTemplate::setSize(TR::RelocationTarget *reloTarget,uint16_t size) + { + return reloTarget->storeUnsigned16b(size, reinterpret_cast(&_size)); + } +void +OMR::RelocationRecordBinaryTemplate::setType(TR::RelocationTarget *reloTarget, uint8_t type) + { + return reloTarget->storeUnsigned8b(type,&_type); + } + +void +OMR::RelocationRecordBinaryTemplate::setFlags(TR::RelocationTarget *reloTarget,uint8_t flags) + { + return reloTarget->storeUnsigned8b(flags,&_flags); + } + + +#if defined(TR_HOST_64BIT) +void +OMR::RelocationRecordBinaryTemplate::setExtra(TR::RelocationTarget *reloTarget,uint32_t extra) + { + return reloTarget->storeUnsigned32b(extra, reinterpret_cast(&_extra)); + } +#endif + +TR::RelocationRecord * +OMR::RelocationRecord::self() + { + return static_cast(this); + } + +void +OMR::RelocationRecordGroup::setSize(TR::RelocationTarget *reloTarget,uintptr_t size) + { + reloTarget->storePointer((uint8_t *)size, (uint8_t *) _dataBuffer); + } + +uintptr_t +OMR::RelocationRecordGroup::size(TR::RelocationTarget *reloTarget) + { + return (uintptr_t)reloTarget->loadPointer((uint8_t *) _dataBuffer); + } + +TR::RelocationRecordBinaryTemplate * +OMR::RelocationRecordGroup::firstRecord(TR::RelocationTarget *reloTarget) + { + // first word of the group is a pointer size field for the entire group + return (TR::RelocationRecordBinaryTemplate *) (((uintptr_t *)_dataBuffer)+1); + } + +TR::RelocationRecordBinaryTemplate * +OMR::RelocationRecordGroup::pastLastRecord(TR::RelocationTarget *reloTarget) + { + return (TR::RelocationRecordBinaryTemplate *) ((uint8_t *)_dataBuffer + size(reloTarget)); + } + +int32_t +OMR::RelocationRecordGroup::applyRelocations(TR::RelocationRuntime *reloRuntime, + TR::RelocationTarget *reloTarget, + uint8_t *reloOrigin) + { + TR::RelocationRecordBinaryTemplate *recordPointer = firstRecord(reloTarget); + TR::RelocationRecordBinaryTemplate *endOfRecords = pastLastRecord(reloTarget); + + while (recordPointer < endOfRecords) + { + TR::RelocationRecord storage; + // Create a specific type of relocation record based on the information + // in the binary record pointed to by `recordPointer` + TR::RelocationRecord *reloRecord = TR::RelocationRecord::create(&storage, reloRuntime, reloTarget, recordPointer); + int32_t rc = handleRelocation(reloRuntime, reloTarget, reloRecord, reloOrigin); + if (rc != 0) + return rc; + + recordPointer = reinterpret_cast(reloRecord->nextBinaryRecord(reloTarget)); + } + + return 0; + } +void OMR::RelocationRecord::initialize(TR::RelocationTarget *reloTarget,uint8_t* targetAddress, uint8_t* targetAddress2 ){ + +} + +int32_t +OMR::RelocationRecordGroup::handleRelocation(TR::RelocationRuntime *reloRuntime, + TR::RelocationTarget *reloTarget, + TR::RelocationRecord *reloRecord, + uint8_t *reloOrigin) + { + + if (reloRecord->ignore(reloRuntime)) + { + return 0; + } + + reloRecord->preparePrivateData(reloRuntime, reloTarget); + return reloRecord->applyRelocationAtAllOffsets(reloRuntime, reloTarget, reloOrigin); + } + +#define FLAGS_RELOCATION_WIDE_OFFSETS 0x80 +#define FLAGS_RELOCATION_EIP_OFFSET 0x40 +#define FLAGS_RELOCATION_TYPE_MASK (TR::ExternalRelocationTargetKindMask) +#define FLAGS_RELOCATION_FLAG_MASK ((uint8_t) (FLAGS_RELOCATION_WIDE_OFFSETS | FLAGS_RELOCATION_EIP_OFFSET)) + + +TR::RelocationRecord * +TR::RelocationRecord::create(TR::RelocationRecord *storage, TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, TR::RelocationRecordBinaryTemplate *record) + { + OMR::RelocationRecord *reloRecord = NULL; + // based on the type of the relocation record, create an object of a particular variety of OMR::RelocationRecord object + uint8_t reloType = record->type(reloTarget); + switch (reloType) + { + default: + // TODO: error condition + printf("Unexpected relo record: %d\n", reloType);fflush(stdout); + exit(0); + } + + return static_cast(reloRecord); + } + +void +OMR::RelocationRecord::print(TR::RelocationRuntime *reloRuntime) + { + TR::RelocationTarget *reloTarget = reloRuntime->reloTarget(); + } + +void +OMR::RelocationRecord::clean(TR::RelocationTarget *reloTarget) + { + setSize(reloTarget, 0); + reloTarget->storeUnsigned8b(0, (uint8_t *) &_record->_type); + reloTarget->storeUnsigned8b(0, (uint8_t *) &_record->_flags); + } + +int32_t +OMR::RelocationRecord::bytesInHeaderAndPayload() + { + return sizeof(OMR::RelocationRecordBinaryTemplate); + } + +OMR::RelocationRecordBinaryTemplate * +OMR::RelocationRecord::nextBinaryRecord(TR::RelocationTarget *reloTarget) + { + return (OMR::RelocationRecordBinaryTemplate*) (((uint8_t*)this->_record) + size(reloTarget)); + } + +void +OMR::RelocationRecord::setSize(TR::RelocationTarget *reloTarget, uint16_t size) + { + reloTarget->storeUnsigned16b(size,(uint8_t *) &_record->_size); + } + +uint16_t +OMR::RelocationRecord::size(TR::RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &_record->_size); + } + + +void +OMR::RelocationRecord::setType(TR::RelocationTarget *reloTarget, OMR::RelocationRecordType type) + { + reloTarget->storeUnsigned8b(type, (uint8_t *) &_record->_type); + } + +OMR::RelocationRecordType +OMR::RelocationRecord::type(TR::RelocationTarget *reloTarget) + { + return (OMR::RelocationRecordType)_record->type(reloTarget); + } + + +void +OMR::RelocationRecord::setWideOffsets(TR::RelocationTarget *reloTarget) + { + setFlag(reloTarget, FLAGS_RELOCATION_WIDE_OFFSETS); + } + +bool +OMR::RelocationRecord::wideOffsets(TR::RelocationTarget *reloTarget) + { + return (flags(reloTarget) & FLAGS_RELOCATION_WIDE_OFFSETS) != 0; + } + +void +OMR::RelocationRecord::setEipRelative(TR::RelocationTarget *reloTarget) + { + setFlag(reloTarget, FLAGS_RELOCATION_EIP_OFFSET); + } + +bool +OMR::RelocationRecord::eipRelative(TR::RelocationTarget *reloTarget) + { + return (flags(reloTarget) & FLAGS_RELOCATION_EIP_OFFSET) != 0; + } + +void +OMR::RelocationRecord::setFlag(TR::RelocationTarget *reloTarget, uint8_t flag) + { + uint8_t flags = reloTarget->loadUnsigned8b((uint8_t *) &_record->_flags) | (flag & FLAGS_RELOCATION_FLAG_MASK); + reloTarget->storeUnsigned8b(flags, (uint8_t *) &_record->_flags); + } + +uint8_t +OMR::RelocationRecord::flags(TR::RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned8b((uint8_t *) &_record->_flags) & FLAGS_RELOCATION_FLAG_MASK; + } + +void +OMR::RelocationRecord::setReloFlags(TR::RelocationTarget *reloTarget, uint8_t reloFlags) + { + TR_ASSERT((reloFlags & ~FLAGS_RELOCATION_FLAG_MASK) == 0, "reloFlags bits overlap cross-platform flags bits\n"); + uint8_t crossPlatFlags = flags(reloTarget); + uint8_t flags = crossPlatFlags | (reloFlags & ~FLAGS_RELOCATION_FLAG_MASK); + reloTarget->storeUnsigned8b(flags, (uint8_t *) &_record->_flags); + } + +uint8_t +OMR::RelocationRecord::reloFlags(TR::RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned8b((uint8_t *) &_record->_flags) & ~FLAGS_RELOCATION_FLAG_MASK; + } + +void +OMR::RelocationRecord::preparePrivateData(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget) + { + + } +// Generic helper address computation for multiple relocation types +uint8_t * +OMR::RelocationRecord::computeHelperAddress(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *baseLocation) + { + uint8_t* helperAddress = (uint8_t*) malloc(sizeof(uint8_t)); + *(helperAddress) = 0; + return helperAddress; + } + +#undef FLAGS_RELOCATION_WIDE_OFFSETS +#undef FLAGS_RELOCATION_EIP_OFFSET +#undef FLAGS_RELOCATION_ORDERED_PAIR +#undef FLAGS_RELOCATION_TYPE_MASK +#undef FLAGS_RELOCATION_FLAG_MASK + + +bool +OMR::RelocationRecord::ignore(TR::RelocationRuntime *reloRuntime) + { + return false; + } + +int32_t +OMR::RelocationRecord::applyRelocationAtAllOffsets(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *reloOrigin) + { + if (ignore(reloRuntime)) + { + return 0; + } + + if (reloTarget->isOrderedPairRelocation(self(), reloTarget)) + { + if (wideOffsets(reloTarget)) + { + int32_t *offsetsBase = (int32_t *) (((uint8_t*)_record) + bytesInHeaderAndPayload()); + int32_t *endOfOffsets = (int32_t *) nextBinaryRecord(reloTarget); + for (int32_t *offsetPtr = offsetsBase;offsetPtr < endOfOffsets; offsetPtr+=2) + { + int32_t offsetHigh = *offsetPtr; + int32_t offsetLow = *(offsetPtr+1); + uint8_t *reloLocationHigh = reloOrigin + offsetHigh + 2; // Add 2 to skip the first 16 bits of instruction + uint8_t *reloLocationLow = reloOrigin + offsetLow + 2; // Add 2 to skip the first 16 bits of instruction + int32_t rc = applyRelocation(reloRuntime, reloTarget, reloLocationHigh, reloLocationLow); + if (rc != 0) + { + return rc; + } + } + } + else + { + int16_t *offsetsBase = (int16_t *) (((uint8_t*)_record) + bytesInHeaderAndPayload()); + int16_t *endOfOffsets = (int16_t *) nextBinaryRecord(reloTarget); + for (int16_t *offsetPtr = offsetsBase;offsetPtr < endOfOffsets; offsetPtr+=2) + { + int16_t offsetHigh = *offsetPtr; + int16_t offsetLow = *(offsetPtr+1); + uint8_t *reloLocationHigh = reloOrigin + offsetHigh + 2; // Add 2 to skip the first 16 bits of instruction + uint8_t *reloLocationLow = reloOrigin + offsetLow + 2; // Add 2 to skip the first 16 bits of instruction + int32_t rc = applyRelocation(reloRuntime, reloTarget, reloLocationHigh, reloLocationLow); + if (rc != 0) + { + return rc; + } + } + } + } + else + { + if (wideOffsets(reloTarget)) + { + int32_t *offsetsBase = (int32_t *) (((uint8_t*)_record) + bytesInHeaderAndPayload()); + int32_t *endOfOffsets = (int32_t *) nextBinaryRecord(reloTarget); + for (int32_t *offsetPtr = offsetsBase;offsetPtr < endOfOffsets; offsetPtr++) + { + int32_t offset = *offsetPtr; + uint8_t *reloLocation = reloOrigin + offset; + int32_t rc = applyRelocation(reloRuntime, reloTarget, reloLocation); + if (rc != 0) + { + return rc; + } + } + } + else + { + int16_t *offsetsBase = (int16_t *) (((uint8_t*)_record) + bytesInHeaderAndPayload()); + int16_t *endOfOffsets = (int16_t *) nextBinaryRecord(reloTarget); + for (int16_t *offsetPtr = offsetsBase;offsetPtr < endOfOffsets; offsetPtr++) + { + int16_t offset = *offsetPtr; + uint8_t *reloLocation = reloOrigin + offset; + int32_t rc = applyRelocation(reloRuntime, reloTarget, reloLocation); + if (rc != 0) + { + return rc; + } + } + } + } + return 0; + } + + +uint32_t OMR::RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRelocationKinds] = + { + #include "OMRExternalRelocationsKindToHeaderSizeMap.hpp" + }; diff --git a/compiler/runtime/OMRRelocationRecord.hpp b/compiler/runtime/OMRRelocationRecord.hpp new file mode 100644 index 00000000000..f8ff958e109 --- /dev/null +++ b/compiler/runtime/OMRRelocationRecord.hpp @@ -0,0 +1,235 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +// +// PLEASE DO NOT USE ANY J9-SPECIFIC DATA TYPES IN THIS FILE +// + +#ifndef OMR_RELOCATION_RECORD_INCL +#define OMR_RELOCATION_RECORD_INCL +/* + * The following #define(s) and typedef(s) must appear before any #includes in this file + */ +#ifndef OMR_RELOCATION_RECORD_CONNECTOR +#define OMR_RELOCATION_RECORD_CONNECTOR +namespace OMR { class RelocationRecord; } +namespace OMR { typedef OMR::RelocationRecord RelocationRecordConnector; } +#else + #error OMR::RelocationRecord expected to be a primary connector, but another connector is already defined +#endif + + +#ifndef OMR_RELOCATION_RECORD_BINARY_TEMPLATE_CONNECTOR +#define OMR_RELOCATION_RECORD_BINARY_TEMPLATE_CONNECTOR +namespace OMR { class RelocationRecordBinaryTemplate; } +namespace OMR { typedef OMR::RelocationRecordBinaryTemplate RelocationRecordBinaryTemplateConnector; } +#else + #error OMR::RelocationRecord expected to be a primary connector, but another connector is already defined +#endif + + +#ifndef OMR_RELOCATION_RECORD_GROUP_CONNECTOR +#define OMR_RELOCATION_RECORD_GROUP_CONNECTOR +namespace OMR { class RelocationRecordGroup; } +namespace OMR { typedef OMR::RelocationRecordGroup RelocationRecordGroupConnector; } +#else + #error OMR::RelocationRecord expected to be a primary connector, but another connector is already defined +#endif + + +#include +#include "compile/Compilation.hpp" +#include "env/jittypes.h" +#include "infra/Link.hpp" +#include "infra/Flags.hpp" +#include "runtime/RelocationRuntime.hpp" +#include "runtime/Runtime.hpp" + +namespace TR { +class RelocationRuntime; +class RelocationTarget; +class RelocationRuntimeLogger; +struct RelocationRecordMethodCallPrivateData + { + uintptrj_t callTargetOffset; + }; + + union RelocationRecordPrivateData + { + int storage; + }; + +} + +namespace OMR { typedef TR_ExternalRelocationTargetKind RelocationRecordType;} +namespace TR { typedef TR_ExternalRelocationTargetKind RelocationRecordType;} +namespace TR { class RelocationRecordBinaryTemplate;} +extern char* AOTcgDiagOn; + +// TR::RelocationRecord is the base class for all relocation records. It is used for all queries on relocation +// records as well as holding all the "wrapper" parts. These classes are an interface to the *BinaryTemplate +// classes which are simply structs that can be used to directly access the binary representation of the relocation +// records stored in the cache (*BinaryTemplate structs are defined near the end of this file after the +// RelocationRecord* classes. The RelocationRecord* classes permit virtual function calls access to the +// *BinaryTemplate classes and must access the binary structs via the _record field in the TR::RelocationRecord +// class. Most consumers should directly manipulate the TR::RelocationRecord* classes since they offer +// the most flexibility. +namespace OMR +{ + class OMR_EXTENSIBLE RelocationRecordBinaryTemplate + { + public: + RelocationRecordBinaryTemplate(){}; + void setType(TR::RelocationTarget*, uint8_t kind); + void setSize(TR::RelocationTarget*, uint16_t size); + void setFlags(TR::RelocationTarget*, uint8_t flags); + void setExtra(TR::RelocationTarget*, uint32_t extra); + uint8_t type(TR::RelocationTarget *reloTarget); + uint16_t _size; + uint8_t _type; + uint8_t _flags; + #if defined(TR_HOST_64BIT) + uint32_t _extra; //holds prePrologue offset + #endif + }; + + struct RelocationRecordMethodCallAddressBinaryTemplate : public RelocationRecordBinaryTemplate + { + UDATA _methodAddress; + }; + struct RelocationRecordASHLBinaryTemplate : public RelocationRecordBinaryTemplate + { + uint8_t sizeOfDataInTheHeader; + }; + + struct RelocationRecordWithOffsetBinaryTemplate : public RelocationRecordBinaryTemplate + { + UDATA _offset; + }; + struct RelocationRecordDataAddressBinaryTemplate : public RelocationRecordWithOffsetBinaryTemplate {}; + + class OMR_EXTENSIBLE RelocationRecord + { + + public: + RelocationRecord() {} + RelocationRecord(TR::RelocationRuntime *reloRuntime, TR::RelocationRecordBinaryTemplate *record) + { + _reloRuntime= reloRuntime; + _record =record; + } + + void * operator new (size_t s, RelocationRecord *p) { return p; } + TR::RelocationRecord* self(); + virtual void print(TR::RelocationRuntime *reloRuntime); + virtual char *name() { return "RelocationRecord"; } + + virtual bool isValidationRecord() { return false; } + + + static RelocationRecord *create(TR::RelocationRecord *storage, TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, TR::RelocationRecordBinaryTemplate *recordPointer); + + virtual void clean(TR::RelocationTarget *reloTarget); + virtual int32_t bytesInHeaderAndPayload(); + + virtual void preparePrivateData(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget); + + virtual int32_t applyRelocationAtAllOffsets(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *relocationOrigin); + + virtual int32_t applyRelocation(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *reloLocation) {return -1;} + virtual int32_t applyRelocation(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow) {return -1;} + + RelocationRecordBinaryTemplate *nextBinaryRecord(TR::RelocationTarget *reloTarget); + RelocationRecordBinaryTemplate *binaryRecord(); + + void setSize(TR::RelocationTarget *reloTarget, uint16_t size); + uint16_t size(TR::RelocationTarget *reloTarget); + + void setType(TR::RelocationTarget *reloTarget, TR::RelocationRecordType type); + RelocationRecordType type(TR::RelocationTarget *reloTarget); + + void setWideOffsets(TR::RelocationTarget *reloTarget); + bool wideOffsets(TR::RelocationTarget *reloTarget); + + void setEipRelative(TR::RelocationTarget *reloTarget); + bool eipRelative(TR::RelocationTarget *reloTarget); + + void setFlag(TR::RelocationTarget *reloTarget, uint8_t flag); + uint8_t flags(TR::RelocationTarget *reloTarget); + + void setReloFlags(TR::RelocationTarget *reloTarget, uint8_t reloFlags); + uint8_t reloFlags(TR::RelocationTarget *reloTarget); + + TR::RelocationRuntime *_reloRuntime; + virtual void initialize(TR::RelocationTarget *reloTarget,uint8_t* dataOne,uint8_t* dataTwo); + virtual bool ignore(TR::RelocationRuntime *reloRuntime); + + static uint32_t getSizeOfAOTRelocationHeader(TR_ExternalRelocationTargetKind k) + { + return _relocationRecordHeaderSizeTable[k]; + } + + protected: + uint8_t *computeHelperAddress(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, uint8_t *baseLocation); + + TR::RelocationRecordPrivateData *privateData() + { + return &_privateData; + } + + TR::RelocationRecordBinaryTemplate *_record; + + TR::RelocationRecordPrivateData _privateData; + + static uint32_t _relocationRecordHeaderSizeTable[TR_NumExternalRelocationKinds]; + }; + + +class RelocationRecordGroup + { + public: + RelocationRecordGroup(TR::RelocationRecordBinaryTemplate *groupData) : _dataBuffer(groupData) {}; + + void setSize(TR::RelocationTarget *reloTarget, uintptr_t size); + uintptr_t size(TR::RelocationTarget *reloTarget); + + TR::RelocationRecordBinaryTemplate *firstRecord(TR::RelocationTarget *reloTarget); + TR::RelocationRecordBinaryTemplate *pastLastRecord(TR::RelocationTarget *reloTarget); + + int32_t applyRelocations(TR::RelocationRuntime *reloRuntime, + TR::RelocationTarget *reloTarget, + uint8_t *reloOrigin); + private: + int32_t handleRelocation(TR::RelocationRuntime *reloRuntime, TR::RelocationTarget *reloTarget, TR::RelocationRecord *reloRecord, uint8_t *reloOrigin); + + TR::RelocationRecordBinaryTemplate *_dataBuffer; + }; + +} //namespace OMR + +// No class that derives from TR::RelocationRecord should define any state: all state variables should be declared +// in TR::RelocationRecord or the constructor/decode() mechanisms will not work properly + + +// Relocation record classes for "real" relocation record types +// should be defined on the level of consuming project +#endif // RELOCATION_RECORD_INCL \ No newline at end of file