| File: Compiler\ObjectWriter\Dwarf\DwarfFde.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Buffers; using System.Diagnostics; using Internal.Text; using static ILCompiler.ObjectWriter.DwarfNative; namespace ILCompiler.ObjectWriter { internal readonly struct DwarfFde { public readonly DwarfCie Cie; public readonly byte[] Instructions; public readonly Utf8String PcStartSymbolName; public readonly long PcStartSymbolOffset; public readonly ulong PcLength; public readonly Utf8String LsdaSymbolName; public readonly Utf8String PersonalitySymbolName; public DwarfFde( DwarfCie cie, byte[] blobData, Utf8String pcStartSymbolName, long pcStartSymbolOffset, ulong pcLength, Utf8String lsdaSymbolName, Utf8String personalitySymbolName) { Cie = cie; Instructions = CfiCodeToInstructions(cie, blobData); PcStartSymbolName = pcStartSymbolName; PcStartSymbolOffset = pcStartSymbolOffset; PcLength = pcLength; LsdaSymbolName = lsdaSymbolName; PersonalitySymbolName = personalitySymbolName; } /// <summary> /// Convert JIT version of CFI blob into the DWARF byte code form. /// </summary> private static byte[] CfiCodeToInstructions(DwarfCie cie, byte[] blobData) { int cfaOffset = cie.InitialCFAOffset; var cfiCode = ArrayPool<byte>.Shared.Rent(4096); int cfiCodeOffset = 0; byte codeOffset = 0; byte lastCodeOffset = 0; int offset = 0; while (offset < blobData.Length) { codeOffset = Math.Max(codeOffset, blobData[offset++]); CFI_OPCODE opcode = (CFI_OPCODE)blobData[offset++]; short dwarfReg = BitConverter.ToInt16(blobData, offset); offset += sizeof(short); int cfiOffset = BitConverter.ToInt32(blobData, offset); offset += sizeof(int); if (codeOffset != lastCodeOffset) { // Advance int diff = (int)((codeOffset - lastCodeOffset) / cie.CodeAlignFactor); if (diff <= 0x3F) { cfiCode[cfiCodeOffset++] = (byte)(DW_CFA_advance_loc | diff); } else { Debug.Assert(diff <= 0xFF); cfiCode[cfiCodeOffset++] = DW_CFA_advance_loc1; cfiCode[cfiCodeOffset++] = (byte)diff; } lastCodeOffset = codeOffset; } switch (opcode) { case CFI_OPCODE.CFI_DEF_CFA_REGISTER: cfiCode[cfiCodeOffset++] = DW_CFA_def_cfa_register; cfiCode[cfiCodeOffset++] = (byte)dwarfReg; break; case CFI_OPCODE.CFI_REL_OFFSET: int absOffset = ((cfiOffset - cfaOffset) / cie.DataAlignFactor); if (absOffset < 0) { cfiCode[cfiCodeOffset++] = DW_CFA_offset_extended_sf; cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)dwarfReg); cfiCodeOffset += DwarfHelper.WriteSLEB128(cfiCode.AsSpan(cfiCodeOffset), absOffset); } else if (dwarfReg <= 0x3F) { cfiCode[cfiCodeOffset++] = (byte)(DW_CFA_offset | (byte)dwarfReg); cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)absOffset); } else { cfiCode[cfiCodeOffset++] = DW_CFA_offset_extended; cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)dwarfReg); cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)absOffset); } break; case CFI_OPCODE.CFI_ADJUST_CFA_OFFSET: cfiCode[cfiCodeOffset++] = DW_CFA_def_cfa_offset; cfaOffset += cfiOffset; cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)cfaOffset); break; case CFI_OPCODE.CFI_DEF_CFA: cfiCode[cfiCodeOffset++] = DW_CFA_def_cfa; cfiCode[cfiCodeOffset++] = (byte)dwarfReg; cfaOffset = cfiOffset; cfiCodeOffset += DwarfHelper.WriteULEB128(cfiCode.AsSpan(cfiCodeOffset), (uint)cfaOffset); break; case CFI_OPCODE.CFI_NEGATE_RA_STATE: cfiCode[cfiCodeOffset++] = DW_CFA_AARCH64_negate_ra_state; break; } } var result = cfiCode[0..cfiCodeOffset]; ArrayPool<byte>.Shared.Return(cfiCode); return result; } } }