Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT] ARM: Implement the EABI #97604

Merged
merged 8 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,28 @@ struct Registers_REGDISPLAY : REGDISPLAY
void setFP(uint32_t value, uint32_t location) { pR11 = (PTR_UIntNative)location;}
};

struct ArmUnwindCursor : public libunwind::AbstractUnwindCursor
{
Registers_REGDISPLAY *_registers;
public:
ArmUnwindCursor(Registers_REGDISPLAY *registers) : _registers(registers) {}
virtual bool validReg(int num) { return _registers->validRegister(num); }
virtual unw_word_t getReg(int num) { return _registers->getRegister(num); }
virtual void setReg(int num, unw_word_t value, unw_word_t location) { _registers->setRegister(num, value, location); }
virtual unw_word_t getRegLocation(int num) {abort();}
virtual bool validFloatReg(int num) { return _registers->validFloatRegister(num); }
virtual unw_fpreg_t getFloatReg(int num) { return _registers->getFloatRegister(num); }
virtual void setFloatReg(int num, unw_fpreg_t value) { _registers->setFloatRegister(num, value); }
virtual int step(bool stage2 = false) {abort();}
virtual void getInfo(unw_proc_info_t *) {abort();}
virtual void jumpto() {abort();}
virtual bool isSignalFrame() { return false; }
virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off) {abort();}
virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false) {abort();}
virtual const char *getRegisterName(int num) {abort();}
virtual void saveVFPAsX() {abort();}
};

inline bool Registers_REGDISPLAY::validRegister(int num) const {
if (num == UNW_REG_SP || num == UNW_ARM_SP)
return true;
Expand Down Expand Up @@ -798,7 +820,14 @@ bool UnwindHelpers::StepFrame(REGDISPLAY *regs, unw_word_t start_ip, uint32_t fo
}

#elif defined(_LIBUNWIND_ARM_EHABI)
PORTABILITY_ASSERT("StepFrame");
size_t len = 0;
size_t off = 0;
const uint32_t *ehtp = decode_eht_entry(reinterpret_cast<const uint32_t *>(unwind_info), &off, &len);
ArmUnwindCursor unwindCursor((Registers_REGDISPLAY*)regs);
if (_Unwind_VRS_Interpret((_Unwind_Context *)&unwindCursor, ehtp, off, len) != _URC_CONTINUE_UNWIND)
{
return false;
}
#else
PORTABILITY_ASSERT("StepFrame");
#endif
Expand Down Expand Up @@ -853,7 +882,10 @@ bool UnwindHelpers::GetUnwindProcInfo(PCODE pc, UnwindInfoSections &uwInfoSectio
}

#elif defined(_LIBUNWIND_ARM_EHABI)
PORTABILITY_ASSERT("GetUnwindProcInfo");
if (uwInfoSections.arm_section == 0 || !uc.getInfoFromEHABISection(pc, uwInfoSections))
{
return false;
}
#else
PORTABILITY_ASSERT("GetUnwindProcInfo");
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public enum SectionType
Executable,
Uninitialized,
Debug,
UnwindData,
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public enum RelocType
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x10B,
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x10C,

// Linux arm32
IMAGE_REL_ARM_PREL31 = 0x10D,

//
// Relocations for R2R image production
//
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace ILCompiler.ObjectWriter
{
/// <summary>
/// JIT enum used in the CFI code blob.
/// </summary>
internal enum CFI_OPCODE
{
CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one.
CFI_DEF_CFA_REGISTER, // New register is used to compute CFA
CFI_REL_OFFSET, // Register is saved at offset from the current CFA
CFI_DEF_CFA // Take address from register and add offset to it.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ public DwarfFde(
PersonalitySymbolName = personalitySymbolName;
}

private enum CFI_OPCODE
{
CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one.
CFI_DEF_CFA_REGISTER, // New register is used to compute CFA
CFI_REL_OFFSET, // Register is saved at offset from the current CFA
CFI_DEF_CFA // Take address from register and add offset to it.
}

/// <summary>
/// Convert JIT version of CFI blob into the the DWARF byte code form.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;

using static ILCompiler.ObjectWriter.EabiNative;

namespace ILCompiler.ObjectWriter
{
/// <summary>
/// Builder class for constructing the .ARM.attributes table that
/// describes the parameters of the emitted ARM code for use by the
/// linker or debugger.
/// </summary>
internal sealed class EabiAttributesBuilder
{
private readonly SectionWriter _sectionWriter;
private long _sectionSizePosition;
private byte[] _sectionSize;
private long _subsectionSizePosition;
private byte[] _subsectionSize;

public EabiAttributesBuilder(SectionWriter sectionWriter)
{
_sectionWriter = sectionWriter;

// Version
_sectionWriter.WriteByte(0x41);
}

public void StartSection(string vendor)
{
Debug.Assert(_sectionSize is null);
Debug.Assert(_subsectionSize is null);

_sectionSizePosition = _sectionWriter.Position;
_sectionSize = new byte[4];
_sectionWriter.EmitData(_sectionSize);

_sectionWriter.WriteUtf8String(vendor);

_sectionWriter.WriteByte((byte)Tag_File);

_subsectionSizePosition = _sectionWriter.Position;
_subsectionSize = new byte[4];
_sectionWriter.EmitData(_subsectionSize);
}

public void EndSection()
{
Debug.Assert(_sectionSize is not null);
Debug.Assert(_subsectionSize is not null);

BinaryPrimitives.WriteUInt32LittleEndian(_subsectionSize, (uint)(_sectionWriter.Position - _subsectionSizePosition));
BinaryPrimitives.WriteUInt32LittleEndian(_sectionSize, (uint)(_sectionWriter.Position - _sectionSizePosition));

_sectionSize = null;
_subsectionSize = null;
}

public void WriteAttribute(uint tag, ulong value)
{
Debug.Assert(_subsectionSize is not null);

_sectionWriter.WriteULEB128(tag);
_sectionWriter.WriteULEB128(value);
}

public void WriteAttribute(uint tag, string value)
{
Debug.Assert(_subsectionSize is not null);

_sectionWriter.WriteULEB128(tag);
_sectionWriter.WriteUtf8String(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace ILCompiler.ObjectWriter
{
/// <summary>
/// Native constants and enumerations for ARM EABI binary format.
/// </summary>
internal static class EabiNative
{
public const uint Tag_File = 1;
public const uint Tag_CPU_raw_name = 4;
public const uint Tag_CPU_name = 5;
public const uint Tag_CPU_arch = 6;
public const uint Tag_CPU_arch_profile = 7;
public const uint Tag_ARM_ISA_use = 8;
public const uint Tag_THUMB_ISA_use = 9;
public const uint Tag_FP_arch = 10;
public const uint Tag_ABI_PCS_R9_use = 14;
public const uint Tag_ABI_PCS_RW_data = 15;
public const uint Tag_ABI_PCS_RO_data = 16;
public const uint Tag_ABI_PCS_GOT_use = 17;
public const uint Tag_ABI_PCS_wchar_t = 18;
public const uint Tag_ABI_FP_rounding = 19;
public const uint Tag_ABI_FP_denormal = 20;
public const uint Tag_ABI_FP_exceptions = 21;
public const uint Tag_ABI_FP_user_exceptions = 22;
public const uint Tag_ABI_FP_number_model = 23;
public const uint Tag_ABI_align_needed = 24;
public const uint Tag_ABI_align_preserved = 25;
public const uint Tag_ABI_enum_size = 26;
public const uint Tag_ABI_optimization_goals = 30;
public const uint Tag_CPU_unaligned_access = 34;
public const uint Tag_ABI_FP_16bit_format = 38;
public const uint Tag_conformance = 67;
}
}
Loading