public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } LayoutMethodsWithEHInfo(); ObjectDataBuilder exceptionInfoLookupBuilder = new ObjectDataBuilder(factory, relocsOnly); exceptionInfoLookupBuilder.RequireInitialAlignment(2 * sizeof(uint)); // Add the symbol representing this object node exceptionInfoLookupBuilder.AddSymbol(this); // First, emit the actual EH records in sequence and store map from methods to the EH record symbols for (int index = 0; index < _methodNodes.Count; index++) { exceptionInfoLookupBuilder.EmitReloc(_methodNodes[index], RelocType.IMAGE_REL_BASED_ADDR32NB); exceptionInfoLookupBuilder.EmitReloc(_ehInfoNode, RelocType.IMAGE_REL_BASED_ADDR32NB, _ehInfoOffsets[index]); } // Sentinel record - method RVA = -1, EH info offset = end of the EH info block exceptionInfoLookupBuilder.EmitUInt(~0u); exceptionInfoLookupBuilder.EmitReloc(_ehInfoNode, RelocType.IMAGE_REL_BASED_ADDR32NB, _ehInfoNode.Count); return(exceptionInfoLookupBuilder.ToObjectData()); }
private ObjectNode.ObjectData EncodeEHInfo() { var builder = new ObjectDataBuilder(); builder.RequireInitialAlignment(1); int totalClauses = _ehClauses.Length; // Count the number of special markers that will be needed for (int i = 1; i < _ehClauses.Length; i++) { ref CORINFO_EH_CLAUSE clause = ref _ehClauses[i]; ref CORINFO_EH_CLAUSE previousClause = ref _ehClauses[i - 1];
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } if (_methodNodes == null) { LayoutRuntimeFunctions(); } ObjectDataBuilder runtimeFunctionsBuilder = new ObjectDataBuilder(factory, relocsOnly); runtimeFunctionsBuilder.RequireInitialAlignment(4); // Add the symbol representing this object node runtimeFunctionsBuilder.AddSymbol(this); foreach (MethodWithGCInfo method in _methodNodes) { int[] funcletOffsets = method.GCInfoNode.CalculateFuncletOffsets(factory); for (int frameIndex = 0; frameIndex < method.FrameInfos.Length; frameIndex++) { FrameInfo frameInfo = method.FrameInfos[frameIndex]; // StartOffset of the runtime function int codeDelta = 0; if (Target.Architecture == TargetArchitecture.ARM) { // THUMB_CODE codeDelta = 1; } runtimeFunctionsBuilder.EmitReloc(method, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.StartOffset + codeDelta); if (!relocsOnly && Target.Architecture == TargetArchitecture.X64) { // On Amd64, the 2nd word contains the EndOffset of the runtime function runtimeFunctionsBuilder.EmitReloc(method, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.EndOffset); } runtimeFunctionsBuilder.EmitReloc(factory.RuntimeFunctionsGCInfo.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, funcletOffsets[frameIndex]); } } // Emit sentinel entry runtimeFunctionsBuilder.EmitUInt(~0u); _tableSize = runtimeFunctionsBuilder.CountBytes; return(runtimeFunctionsBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); byte[] rvaData = GetRvaData(factory.Target.PointerSize, out int requiredAlignment); builder.RequireInitialAlignment(requiredAlignment); builder.AddSymbol(this); builder.EmitBytes(rvaData); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(4); builder.AddSymbol(this); DirectoryEntry resourcesDirectory = _module.PEReader.PEHeaders.CorHeader.ResourcesDirectory; PEMemoryBlock block = _module.PEReader.GetSectionData(resourcesDirectory.RelativeVirtualAddress); builder.EmitBytes(block.GetReader().ReadBytes(resourcesDirectory.Size)); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } List <CustomAttributeEntry> customAttributeEntries = GetCustomAttributeEntries(); int countOfEntries = customAttributeEntries.Count; if (countOfEntries == 0) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Buckets have 8 entries uint minTableBucketCount = (uint)(countOfEntries / 8) + 1; uint bucketCount = 1; // Bucket count must be power of two while (bucketCount < minTableBucketCount) { bucketCount *= 2; } // Resize the array. bool tryAgainWithBiggerTable = false; int countOfRetries = 0; ushort[] pTable; do { tryAgainWithBiggerTable = false; uint actualSizeOfTable = bucketCount * 8; // Buckets have 8 entries in them pTable = new ushort[actualSizeOfTable]; uint[] state = new uint[] { 729055690, 833774698, 218408041, 493449127 }; // Attempt to fill table foreach (var customAttributeEntry in customAttributeEntries) { string name = customAttributeEntry.TypeNamespace + "." + customAttributeEntry.TypeName; // This hashing algorithm MUST match exactly the logic in NativeCuckooFilter int hashOfAttribute = ReadyToRunHashCode.NameHashCode(name); uint hash = unchecked ((uint)ReadyToRunHashCode.CombineTwoValuesIntoHash((uint)hashOfAttribute, (uint)customAttributeEntry.Parent)); ushort fingerprint = (ushort)(hash >> 16); if (fingerprint == 0) { fingerprint = 1; } uint bucketAIndex = hash % bucketCount; uint fingerprintHash = (uint)fingerprint; uint bucketBIndex = (bucketAIndex ^ (fingerprintHash % bucketCount)); Debug.Assert(bucketAIndex == (bucketBIndex ^ (fingerprintHash % bucketCount))); if ((XorShift128(state) & 1) != 0) // Randomly choose which bucket to attempt to fill first { uint temp = bucketAIndex; bucketAIndex = bucketBIndex; bucketBIndex = temp; } Func <uint, ushort, bool> hasEntryInBucket = (uint bucketIndex, ushort fprint) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == fprint) { return(true); } } return(false); }; Func <uint, bool> isEmptyEntryInBucket = (uint bucketIndex) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == 0) { return(true); } } return(false); }; Action <uint, ushort> fillEmptyEntryInBucket = (uint bucketIndex, ushort fprint) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == 0) { pTable[(bucketIndex * 8) + i] = fprint; return; } } Debug.Assert(false, "Not possible to reach here"); }; // Scan for pre-existing fingerprint entry in buckets if (hasEntryInBucket(bucketAIndex, fingerprint) || hasEntryInBucket(bucketBIndex, fingerprint)) { continue; } // Determine if there is space in a bucket to add a new entry if (isEmptyEntryInBucket(bucketAIndex)) { fillEmptyEntryInBucket(bucketAIndex, fingerprint); continue; } if (isEmptyEntryInBucket(bucketBIndex)) { fillEmptyEntryInBucket(bucketBIndex, fingerprint); continue; } bool success = false; int MaxNumKicks = 256; // Note, that bucketAIndex itself was chosen randomly above. for (int n = 0; !success && n < MaxNumKicks; n++) { // Randomly swap an entry in bucket bucketAIndex with fingerprint uint entryIndexInBucket = XorShift128(state) & 0x7; ushort temp = fingerprint; fingerprint = pTable[(bucketAIndex * 8) + entryIndexInBucket]; pTable[(bucketAIndex * 8) + entryIndexInBucket] = temp; // Find other bucket fingerprintHash = (uint)fingerprint; bucketAIndex = bucketAIndex ^ (fingerprintHash % bucketCount); if (isEmptyEntryInBucket(bucketAIndex)) { fillEmptyEntryInBucket(bucketAIndex, fingerprint); success = true; } } if (success) { continue; } tryAgainWithBiggerTable = true; } if (tryAgainWithBiggerTable) { // bucket entry kicking path requires bucket counts to be power of two in size due to use of xor to retrieve second hash bucketCount *= 2; } }while(tryAgainWithBiggerTable && ((countOfRetries++) < 2)); byte[] result; if (tryAgainWithBiggerTable) { result = Array.Empty <byte>(); } else { result = new byte[pTable.Length * 2]; for (int i = 0; i < pTable.Length; i++) { result[i * 2] = (byte)(pTable[i] % 256); result[i * 2 + 1] = (byte)(pTable[i] >> 8); } } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(16); builder.AddSymbol(this); builder.EmitBytes(result); return(builder.ToObjectData());; }