From 1f36a730518cb5813968d7b47f6a0865ac91354c Mon Sep 17 00:00:00 2001 From: Georgiy Krylov Date: Fri, 4 Oct 2019 11:16:51 -0300 Subject: [PATCH] Relocation Record files addition The added files are: OMRRelocationRecord.hpp, OMRRelocationRecord.cpp, OMRExternalRelocationsKindToHeaderSizeMap.hpp. These files contain RelocationRecord, RelocationRecordGroup,RelocationRecordBinaryTemplate classes. The RelocationRecordGroup is an iterator for application of relocations. The RelocationRecordBinaryTemplate is the class that has RelocationRecord information. Those classes realize core relocations storage functionality in OpenJ9, but are language independent and thus are worth including into OMR. The OMRExternalRelocationsKindToHeaderSizeMap.hpp is an attempt for improving extension, similarly to codeGenPhases, by including headers with relocation sizes from consuming projects. Compared to OpenJ9, the RelocationRecord classes became extensible. Another proposed change is in the creation of relocation records: the implementation of TR::RelocationRecord::create function is proposed to be done as a function in corresponding relocationRecord class. The RelocationRecordBinaryTemplate, has undergone changes to improve readability and portability: the setSize() and setType(), as well as x64 architecture specific setExtra() and their corresponding accessor methods are now RelocationTarget API calls, as advised in Issue #3031 [skip ci] Signed-off-by: Georgiy Krylov --- ...ExternalRelocationsKindToHeaderSizeMap.hpp | 190 +++++++++ compiler/runtime/OMRRelocationRecord.cpp | 402 ++++++++++++++++++ compiler/runtime/OMRRelocationRecord.hpp | 235 ++++++++++ 3 files changed, 827 insertions(+) create mode 100644 compiler/runtime/OMRExternalRelocationsKindToHeaderSizeMap.hpp create mode 100644 compiler/runtime/OMRRelocationRecord.cpp create mode 100644 compiler/runtime/OMRRelocationRecord.hpp 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