[llvm] [BinaryFormat] Add "SFrame" structures and constants (PR #147264)
Pavel Labath via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 8 03:24:14 PDT 2025
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/147264
>From a8205c966b3812be925613ea4b5259f8b412ffe7 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 4 Jul 2025 12:09:49 +0200
Subject: [PATCH 1/2] [BinaryFormat] Add "SFrame" structures and constants
This patch defines the structures and constants used by the SFrame
unwind info format supported by GNU binutils. For more information about
the format, see https://sourceware.org/binutils/wiki/sframe and
https://discourse.llvm.org/t/rfc-adding-sframe-support-to-llvm/86900
In the patch, I've used the naming convention for everything that has a
direct equivalent to the specification (modulo changing macros to
constants), and used the llvm convention for everything else.
---
llvm/include/llvm/BinaryFormat/SFrame.h | 165 +++++++++++++++++++++
llvm/unittests/BinaryFormat/CMakeLists.txt | 1 +
llvm/unittests/BinaryFormat/SFrameTest.cpp | 98 ++++++++++++
3 files changed, 264 insertions(+)
create mode 100644 llvm/include/llvm/BinaryFormat/SFrame.h
create mode 100644 llvm/unittests/BinaryFormat/SFrameTest.cpp
diff --git a/llvm/include/llvm/BinaryFormat/SFrame.h b/llvm/include/llvm/BinaryFormat/SFrame.h
new file mode 100644
index 0000000000000..c73553756bc23
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/SFrame.h
@@ -0,0 +1,165 @@
+//===-- llvm/BinaryFormat/SFrame.h ---SFrame Data Structures ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file contains data-structure definitions and constants to support
+/// unwinding based on .sframe sections. This only supports SFRAME_VERSION_2
+/// as described at https://sourceware.org/binutils/docs/sframe-spec.html
+///
+/// Naming conventions follow the spec document. #defines converted to constants
+/// and enums for better C++ compatibility.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_SFRAME_H
+#define LLVM_BINARYFORMAT_SFRAME_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+namespace sframe {
+
+constexpr uint16_t SFRAME_MAGIC = 0xDEE2;
+
+enum : uint8_t {
+ SFRAME_VERSION_1 = 1,
+ SFRAME_VERSION_2 = 2,
+};
+
+/// sframe_preable.sfp_flags flags.
+enum : uint8_t {
+ SFRAME_F_FDE_SORTED = 0x1,
+ SFRAME_F_FRAME_POINTER = 0x2,
+};
+
+/// Possible values for sframe_header.sfh_abi_arch.
+enum : uint8_t {
+ SFRAME_ABI_AARCH64_ENDIAN_BIG = 1,
+ SFRAME_ABI_AARCH64_ENDIAN_LITTLE = 2,
+ SFRAME_ABI_AMD64_ENDIAN_LITTLE = 3
+};
+
+/// SFrame FRE Types. Bits 0-3 of sframe_func_desc_entry.sfde_func_info.
+enum : uint8_t {
+ SFRAME_FRE_TYPE_ADDR1 = 0,
+ SFRAME_FRE_TYPE_ADDR2 = 1,
+ SFRAME_FRE_TYPE_ADDR4 = 2,
+};
+
+/// SFrame FDE Types. Bit 4 of sframe_func_desc_entry.sfde_func_info.
+enum : uint8_t {
+ SFRAME_FDE_TYPE_PCINC = 0,
+ SFRAME_FDE_TYPE_PCMASK = 1,
+};
+
+/// Speficies key used for signing return addresses. Bit 5 of
+/// sframe_func_desc_entry.sfde_func_info.
+enum : uint8_t {
+ SFRAME_AARCH64_PAUTH_KEY_A = 0,
+ SFRAME_AARCH64_PAUTH_KEY_B = 1,
+};
+
+/// Size of stack offsets. Bits 5-6 of sframe_fre_info.fre_info.
+enum : uint8_t {
+ SFRAME_FRE_OFFSET_1B = 0,
+ SFRAME_FRE_OFFSET_2B = 1,
+ SFRAME_FRE_OFFSET_4B = 2,
+};
+
+/// Stack frame base register. Bit 0 of sframe_fre_info.fre_info.
+enum : uint8_t { SFRAME_BASE_REG_FP = 0, SFRAME_BASE_REG_SP = 1 };
+
+LLVM_PACKED_START
+
+struct sframe_preamble {
+ uint16_t sfp_magic;
+ uint8_t sfp_version;
+ uint8_t sfp_flags;
+};
+
+struct sframe_header {
+ sframe_preamble sfh_preamble;
+ uint8_t sfh_abi_arch;
+ int8_t sfh_cfa_fixed_fp_offset;
+ int8_t sfh_cfa_fixed_ra_offset;
+ uint8_t sfh_auxhdr_len;
+ uint32_t sfh_num_fdes;
+ uint32_t sfh_num_fres;
+ uint32_t sfh_fre_len;
+ uint32_t sfh_fdeoff;
+ uint32_t sfh_freoff;
+};
+
+struct sframe_func_desc_entry {
+ int32_t sfde_func_start_address;
+ uint32_t sfde_func_size;
+ uint32_t sfde_func_start_fre_off;
+ uint32_t sfde_func_num_fres;
+ uint8_t sfde_func_info;
+ uint8_t sfde_func_rep_size;
+ uint16_t sfde_func_padding2;
+
+ uint8_t getPAuthKey() const { return (sfde_func_info >> 5) & 1; }
+ uint8_t getFDEType() const { return (sfde_func_info >> 4) & 1; }
+ uint8_t getFREType() const { return sfde_func_info & 0xf; }
+ void setPAuthKey(uint8_t P) { setFuncInfo(P, getFDEType(), getFREType()); }
+ void setFDEType(uint8_t D) { setFuncInfo(getPAuthKey(), D, getFREType()); }
+ void setFREType(uint8_t R) { setFuncInfo(getPAuthKey(), getFDEType(), R); }
+ void setFuncInfo(uint8_t PAuthKey, uint8_t FDEType, uint8_t FREType) {
+ sfde_func_info =
+ ((PAuthKey & 1) << 5) | ((FDEType & 1) << 4) | (FREType & 0xf);
+ }
+};
+
+struct sframe_fre_info {
+ uint8_t fre_info;
+
+ bool isReturnAddressSigned() const { return fre_info >> 7; }
+ uint8_t getOffsetSize() const { return (fre_info >> 5) & 3; }
+ uint8_t getOffsetCount() const { return (fre_info >> 1) & 0xf; }
+ uint8_t getBaseRegister() const { return fre_info & 1; }
+ void setReturnAddressSigned(bool RA) {
+ setFREInfo(RA, getOffsetSize(), getOffsetCount(), getBaseRegister());
+ }
+ void setOffsetSize(uint8_t Sz) {
+ setFREInfo(isReturnAddressSigned(), Sz, getOffsetCount(),
+ getBaseRegister());
+ }
+ void setOffsetCount(uint8_t N) {
+ setFREInfo(isReturnAddressSigned(), getOffsetSize(), N, getBaseRegister());
+ }
+ void setBaseRegister(uint8_t Reg) {
+ setFREInfo(isReturnAddressSigned(), getOffsetSize(), getOffsetCount(), Reg);
+ }
+ void setFREInfo(bool RA, uint8_t Sz, uint8_t N, uint8_t Reg) {
+ fre_info = ((RA & 1) << 7) | ((Sz & 3) << 5) | ((N & 0xf) << 1) | (Reg & 1);
+ }
+};
+
+struct sframe_frame_row_entry_addr1 {
+ uint8_t sfre_start_address;
+ sframe_fre_info sfre_info;
+};
+
+struct sframe_frame_row_entry_addr2 {
+ uint16_t sfre_start_address;
+ sframe_fre_info sfre_info;
+};
+
+struct sframe_frame_row_entry_addr4 {
+ uint32_t sfre_start_address;
+ sframe_fre_info sfre_info;
+};
+
+LLVM_PACKED_END
+
+} // namespace sframe
+} // namespace llvm
+
+#endif // LLVM_BINARYFORMAT_SFRAME_H
diff --git a/llvm/unittests/BinaryFormat/CMakeLists.txt b/llvm/unittests/BinaryFormat/CMakeLists.txt
index 40d3bc4dca0b6..eac5977a2c1c3 100644
--- a/llvm/unittests/BinaryFormat/CMakeLists.txt
+++ b/llvm/unittests/BinaryFormat/CMakeLists.txt
@@ -10,6 +10,7 @@ add_llvm_unittest(BinaryFormatTests
MsgPackDocumentTest.cpp
MsgPackReaderTest.cpp
MsgPackWriterTest.cpp
+ SFrameTest.cpp
TestFileMagic.cpp
)
diff --git a/llvm/unittests/BinaryFormat/SFrameTest.cpp b/llvm/unittests/BinaryFormat/SFrameTest.cpp
new file mode 100644
index 0000000000000..3c8d843d50389
--- /dev/null
+++ b/llvm/unittests/BinaryFormat/SFrameTest.cpp
@@ -0,0 +1,98 @@
+//===- SFrameTest.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/SFrame.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::sframe;
+
+namespace {
+// Test structure sizes and triviality.
+static_assert(std::is_trivial_v<sframe_preamble>);
+static_assert(sizeof(sframe_preamble) == 4);
+
+static_assert(std::is_trivial_v<sframe_header>);
+static_assert(sizeof(sframe_header) == 28);
+
+static_assert(std::is_trivial_v<sframe_func_desc_entry>);
+static_assert(sizeof(sframe_func_desc_entry) == 20);
+
+static_assert(std::is_trivial_v<sframe_frame_row_entry_addr1>);
+static_assert(sizeof(sframe_frame_row_entry_addr1) == 2);
+
+static_assert(std::is_trivial_v<sframe_frame_row_entry_addr2>);
+static_assert(sizeof(sframe_frame_row_entry_addr2) == 3);
+
+static_assert(std::is_trivial_v<sframe_frame_row_entry_addr4>);
+static_assert(sizeof(sframe_frame_row_entry_addr4) == 5);
+
+TEST(SFrameTest, FDEFlags) {
+ sframe_func_desc_entry FDE = {};
+ EXPECT_EQ(FDE.sfde_func_info, 0u);
+ EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_A);
+ EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCINC);
+ EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
+
+ FDE.setPAuthKey(SFRAME_AARCH64_PAUTH_KEY_B);
+ EXPECT_EQ(FDE.sfde_func_info, 0x20u);
+ EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
+ EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCINC);
+ EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
+
+ FDE.setFDEType(SFRAME_FDE_TYPE_PCMASK);
+ EXPECT_EQ(FDE.sfde_func_info, 0x30u);
+ EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
+ EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCMASK);
+ EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
+
+ FDE.setFREType(SFRAME_FRE_TYPE_ADDR4);
+ EXPECT_EQ(FDE.sfde_func_info, 0x32u);
+ EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
+ EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCMASK);
+ EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR4);
+}
+
+TEST(SFrameTest, FREFlags) {
+ sframe_fre_info Info = {};
+ EXPECT_EQ(Info.fre_info, 0u);
+ EXPECT_FALSE(Info.isReturnAddressSigned());
+ EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_1B);
+ EXPECT_EQ(Info.getOffsetCount(), 0u);
+ EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+
+ Info.setReturnAddressSigned(true);
+ EXPECT_EQ(Info.fre_info, 0x80u);
+ EXPECT_TRUE(Info.isReturnAddressSigned());
+ EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_1B);
+ EXPECT_EQ(Info.getOffsetCount(), 0u);
+ EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+
+ Info.setOffsetSize(SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.fre_info, 0xc0u);
+ EXPECT_TRUE(Info.isReturnAddressSigned());
+ EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetCount(), 0u);
+ EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+
+ Info.setOffsetCount(3);
+ EXPECT_EQ(Info.fre_info, 0xc6u);
+ EXPECT_TRUE(Info.isReturnAddressSigned());
+ EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetCount(), 3u);
+ EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+
+ Info.setBaseRegister(SFRAME_BASE_REG_SP);
+ EXPECT_EQ(Info.fre_info, 0xc7u);
+ EXPECT_TRUE(Info.isReturnAddressSigned());
+ EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetCount(), 3u);
+ EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_SP);
+}
+
+} // namespace
>From 5a14521ba43cf4de5553091ae184eae61b2f9a05 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Tue, 8 Jul 2025 12:08:14 +0200
Subject: [PATCH 2/2] llvm-ify
---
llvm/include/llvm/BinaryFormat/SFrame.h | 186 +++++++++++----------
llvm/unittests/BinaryFormat/SFrameTest.cpp | 106 ++++++------
2 files changed, 147 insertions(+), 145 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/SFrame.h b/llvm/include/llvm/BinaryFormat/SFrame.h
index c73553756bc23..272fff332daaa 100644
--- a/llvm/include/llvm/BinaryFormat/SFrame.h
+++ b/llvm/include/llvm/BinaryFormat/SFrame.h
@@ -1,4 +1,4 @@
-//===-- llvm/BinaryFormat/SFrame.h ---SFrame Data Structures ----*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -10,156 +10,158 @@
/// This file contains data-structure definitions and constants to support
/// unwinding based on .sframe sections. This only supports SFRAME_VERSION_2
/// as described at https://sourceware.org/binutils/docs/sframe-spec.html
-///
-/// Naming conventions follow the spec document. #defines converted to constants
-/// and enums for better C++ compatibility.
//===----------------------------------------------------------------------===//
#ifndef LLVM_BINARYFORMAT_SFRAME_H
#define LLVM_BINARYFORMAT_SFRAME_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
-namespace llvm {
+namespace llvm::sframe {
-namespace sframe {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
-constexpr uint16_t SFRAME_MAGIC = 0xDEE2;
+constexpr uint16_t MagicSignature = 0xDEE2;
-enum : uint8_t {
- SFRAME_VERSION_1 = 1,
- SFRAME_VERSION_2 = 2,
+enum class Version : uint8_t {
+ V1 = 1,
+ V2 = 2,
};
-/// sframe_preable.sfp_flags flags.
-enum : uint8_t {
- SFRAME_F_FDE_SORTED = 0x1,
- SFRAME_F_FRAME_POINTER = 0x2,
+enum class Flags : uint8_t {
+ FDESorted = 0x01,
+ FramePointer = 0x02,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xff),
};
-/// Possible values for sframe_header.sfh_abi_arch.
-enum : uint8_t {
- SFRAME_ABI_AARCH64_ENDIAN_BIG = 1,
- SFRAME_ABI_AARCH64_ENDIAN_LITTLE = 2,
- SFRAME_ABI_AMD64_ENDIAN_LITTLE = 3
+enum class ABI : uint8_t {
+ AArch64EndianBig = 1,
+ AArch64EndianLittle = 2,
+ AMD64EndianLittle = 3,
};
-/// SFrame FRE Types. Bits 0-3 of sframe_func_desc_entry.sfde_func_info.
-enum : uint8_t {
- SFRAME_FRE_TYPE_ADDR1 = 0,
- SFRAME_FRE_TYPE_ADDR2 = 1,
- SFRAME_FRE_TYPE_ADDR4 = 2,
+/// SFrame FRE Types. Bits 0-3 of FuncDescEntry.Info.
+enum class FREType : uint8_t {
+ Addr1 = 0,
+ Addr2 = 1,
+ Addr4 = 2,
};
-/// SFrame FDE Types. Bit 4 of sframe_func_desc_entry.sfde_func_info.
-enum : uint8_t {
- SFRAME_FDE_TYPE_PCINC = 0,
- SFRAME_FDE_TYPE_PCMASK = 1,
+/// SFrame FDE Types. Bit 4 of FuncDescEntry.Info.
+enum class FDEType : uint8_t {
+ PCInc = 0,
+ PCMask = 1,
};
/// Speficies key used for signing return addresses. Bit 5 of
-/// sframe_func_desc_entry.sfde_func_info.
-enum : uint8_t {
- SFRAME_AARCH64_PAUTH_KEY_A = 0,
- SFRAME_AARCH64_PAUTH_KEY_B = 1,
+/// FuncDescEntry.Info.
+enum class AArch64PAuthKey : uint8_t {
+ A = 0,
+ B = 1,
};
-/// Size of stack offsets. Bits 5-6 of sframe_fre_info.fre_info.
-enum : uint8_t {
- SFRAME_FRE_OFFSET_1B = 0,
- SFRAME_FRE_OFFSET_2B = 1,
- SFRAME_FRE_OFFSET_4B = 2,
+/// Size of stack offsets. Bits 5-6 of FREInfo.Info.
+enum class FREOffset : uint8_t {
+ B1 = 0,
+ B2 = 1,
+ B4 = 2,
};
-/// Stack frame base register. Bit 0 of sframe_fre_info.fre_info.
-enum : uint8_t { SFRAME_BASE_REG_FP = 0, SFRAME_BASE_REG_SP = 1 };
+/// Stack frame base register. Bit 0 of FREInfo.Info.
+enum class BaseReg : uint8_t {
+ FP = 0,
+ SP = 1,
+};
LLVM_PACKED_START
-struct sframe_preamble {
- uint16_t sfp_magic;
- uint8_t sfp_version;
- uint8_t sfp_flags;
+struct Preamble {
+ uint16_t Magic;
+ enum Version Version;
+ enum Flags Flags;
};
-struct sframe_header {
- sframe_preamble sfh_preamble;
- uint8_t sfh_abi_arch;
- int8_t sfh_cfa_fixed_fp_offset;
- int8_t sfh_cfa_fixed_ra_offset;
- uint8_t sfh_auxhdr_len;
- uint32_t sfh_num_fdes;
- uint32_t sfh_num_fres;
- uint32_t sfh_fre_len;
- uint32_t sfh_fdeoff;
- uint32_t sfh_freoff;
+struct Header {
+ struct Preamble Preamble;
+ uint8_t AbiArch;
+ int8_t CFAFixedFPOffset;
+ int8_t CFAFixedRAOffset;
+ uint8_t AuxHdrLen;
+ uint32_t NumFDEs;
+ uint32_t NumFREs;
+ uint32_t FRELen;
+ uint32_t FDEOff;
+ uint32_t FREOff;
};
-struct sframe_func_desc_entry {
- int32_t sfde_func_start_address;
- uint32_t sfde_func_size;
- uint32_t sfde_func_start_fre_off;
- uint32_t sfde_func_num_fres;
- uint8_t sfde_func_info;
- uint8_t sfde_func_rep_size;
- uint16_t sfde_func_padding2;
-
- uint8_t getPAuthKey() const { return (sfde_func_info >> 5) & 1; }
- uint8_t getFDEType() const { return (sfde_func_info >> 4) & 1; }
- uint8_t getFREType() const { return sfde_func_info & 0xf; }
+struct FuncDescEntry {
+ int32_t StartAddress;
+ uint32_t Size;
+ uint32_t StartFREOff;
+ uint32_t NumFREs;
+ uint8_t Info;
+ uint8_t RepSize;
+ uint16_t Padding2;
+
+ uint8_t getPAuthKey() const { return (Info >> 5) & 1; }
+ FDEType getFDEType() const { return static_cast<FDEType>((Info >> 4) & 1); }
+ FREType getFREType() const { return static_cast<FREType>(Info & 0xf); }
void setPAuthKey(uint8_t P) { setFuncInfo(P, getFDEType(), getFREType()); }
- void setFDEType(uint8_t D) { setFuncInfo(getPAuthKey(), D, getFREType()); }
- void setFREType(uint8_t R) { setFuncInfo(getPAuthKey(), getFDEType(), R); }
- void setFuncInfo(uint8_t PAuthKey, uint8_t FDEType, uint8_t FREType) {
- sfde_func_info =
- ((PAuthKey & 1) << 5) | ((FDEType & 1) << 4) | (FREType & 0xf);
+ void setFDEType(FDEType D) { setFuncInfo(getPAuthKey(), D, getFREType()); }
+ void setFREType(FREType R) { setFuncInfo(getPAuthKey(), getFDEType(), R); }
+ void setFuncInfo(uint8_t PAuthKey, FDEType FDE, FREType FRE) {
+ Info = ((PAuthKey & 1) << 5) | ((static_cast<uint8_t>(FDE) & 1) << 4) |
+ (static_cast<uint8_t>(FRE) & 0xf);
}
};
-struct sframe_fre_info {
- uint8_t fre_info;
+struct FREInfo {
+ uint8_t Info;
- bool isReturnAddressSigned() const { return fre_info >> 7; }
- uint8_t getOffsetSize() const { return (fre_info >> 5) & 3; }
- uint8_t getOffsetCount() const { return (fre_info >> 1) & 0xf; }
- uint8_t getBaseRegister() const { return fre_info & 1; }
+ bool isReturnAddressSigned() const { return Info >> 7; }
+ FREOffset getOffsetSize() const {
+ return static_cast<FREOffset>((Info >> 5) & 3);
+ }
+ uint8_t getOffsetCount() const { return (Info >> 1) & 0xf; }
+ BaseReg getBaseRegister() const { return static_cast<BaseReg>(Info & 1); }
void setReturnAddressSigned(bool RA) {
setFREInfo(RA, getOffsetSize(), getOffsetCount(), getBaseRegister());
}
- void setOffsetSize(uint8_t Sz) {
+ void setOffsetSize(FREOffset Sz) {
setFREInfo(isReturnAddressSigned(), Sz, getOffsetCount(),
getBaseRegister());
}
void setOffsetCount(uint8_t N) {
setFREInfo(isReturnAddressSigned(), getOffsetSize(), N, getBaseRegister());
}
- void setBaseRegister(uint8_t Reg) {
+ void setBaseRegister(BaseReg Reg) {
setFREInfo(isReturnAddressSigned(), getOffsetSize(), getOffsetCount(), Reg);
}
- void setFREInfo(bool RA, uint8_t Sz, uint8_t N, uint8_t Reg) {
- fre_info = ((RA & 1) << 7) | ((Sz & 3) << 5) | ((N & 0xf) << 1) | (Reg & 1);
+ void setFREInfo(bool RA, FREOffset Sz, uint8_t N, BaseReg Reg) {
+ Info = ((RA & 1) << 7) | ((static_cast<uint8_t>(Sz) & 3) << 5) |
+ ((N & 0xf) << 1) | (static_cast<uint8_t>(Reg) & 1);
}
};
-struct sframe_frame_row_entry_addr1 {
- uint8_t sfre_start_address;
- sframe_fre_info sfre_info;
+struct FrameRowEntryAddr1 {
+ uint8_t StartAddress;
+ FREInfo Info;
};
-struct sframe_frame_row_entry_addr2 {
- uint16_t sfre_start_address;
- sframe_fre_info sfre_info;
+struct FrameRowEntryAddr2 {
+ uint16_t StartAddress;
+ FREInfo Info;
};
-struct sframe_frame_row_entry_addr4 {
- uint32_t sfre_start_address;
- sframe_fre_info sfre_info;
+struct FrameRowEntryAddr4 {
+ uint32_t StartAddress;
+ FREInfo Info;
};
LLVM_PACKED_END
-} // namespace sframe
-} // namespace llvm
+} // namespace llvm::sframe
#endif // LLVM_BINARYFORMAT_SFRAME_H
diff --git a/llvm/unittests/BinaryFormat/SFrameTest.cpp b/llvm/unittests/BinaryFormat/SFrameTest.cpp
index 3c8d843d50389..c3b7154b3a882 100644
--- a/llvm/unittests/BinaryFormat/SFrameTest.cpp
+++ b/llvm/unittests/BinaryFormat/SFrameTest.cpp
@@ -14,85 +14,85 @@ using namespace llvm::sframe;
namespace {
// Test structure sizes and triviality.
-static_assert(std::is_trivial_v<sframe_preamble>);
-static_assert(sizeof(sframe_preamble) == 4);
+static_assert(std::is_trivial_v<Preamble>);
+static_assert(sizeof(Preamble) == 4);
-static_assert(std::is_trivial_v<sframe_header>);
-static_assert(sizeof(sframe_header) == 28);
+static_assert(std::is_trivial_v<Header>);
+static_assert(sizeof(Header) == 28);
-static_assert(std::is_trivial_v<sframe_func_desc_entry>);
-static_assert(sizeof(sframe_func_desc_entry) == 20);
+static_assert(std::is_trivial_v<FuncDescEntry>);
+static_assert(sizeof(FuncDescEntry) == 20);
-static_assert(std::is_trivial_v<sframe_frame_row_entry_addr1>);
-static_assert(sizeof(sframe_frame_row_entry_addr1) == 2);
+static_assert(std::is_trivial_v<FrameRowEntryAddr1>);
+static_assert(sizeof(FrameRowEntryAddr1) == 2);
-static_assert(std::is_trivial_v<sframe_frame_row_entry_addr2>);
-static_assert(sizeof(sframe_frame_row_entry_addr2) == 3);
+static_assert(std::is_trivial_v<FrameRowEntryAddr2>);
+static_assert(sizeof(FrameRowEntryAddr2) == 3);
-static_assert(std::is_trivial_v<sframe_frame_row_entry_addr4>);
-static_assert(sizeof(sframe_frame_row_entry_addr4) == 5);
+static_assert(std::is_trivial_v<FrameRowEntryAddr4>);
+static_assert(sizeof(FrameRowEntryAddr4) == 5);
TEST(SFrameTest, FDEFlags) {
- sframe_func_desc_entry FDE = {};
- EXPECT_EQ(FDE.sfde_func_info, 0u);
- EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_A);
- EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCINC);
- EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
-
- FDE.setPAuthKey(SFRAME_AARCH64_PAUTH_KEY_B);
- EXPECT_EQ(FDE.sfde_func_info, 0x20u);
- EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
- EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCINC);
- EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
-
- FDE.setFDEType(SFRAME_FDE_TYPE_PCMASK);
- EXPECT_EQ(FDE.sfde_func_info, 0x30u);
- EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
- EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCMASK);
- EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR1);
-
- FDE.setFREType(SFRAME_FRE_TYPE_ADDR4);
- EXPECT_EQ(FDE.sfde_func_info, 0x32u);
- EXPECT_EQ(FDE.getPAuthKey(), SFRAME_AARCH64_PAUTH_KEY_B);
- EXPECT_EQ(FDE.getFDEType(), SFRAME_FDE_TYPE_PCMASK);
- EXPECT_EQ(FDE.getFREType(), SFRAME_FRE_TYPE_ADDR4);
+ FuncDescEntry FDE = {};
+ EXPECT_EQ(FDE.Info, 0u);
+ EXPECT_EQ(FDE.getPAuthKey(), 0);
+ EXPECT_EQ(FDE.getFDEType(), FDEType::PCInc);
+ EXPECT_EQ(FDE.getFREType(), FREType::Addr1);
+
+ FDE.setPAuthKey(1);
+ EXPECT_EQ(FDE.Info, 0x20u);
+ EXPECT_EQ(FDE.getPAuthKey(), 1);
+ EXPECT_EQ(FDE.getFDEType(), FDEType::PCInc);
+ EXPECT_EQ(FDE.getFREType(), FREType::Addr1);
+
+ FDE.setFDEType(FDEType::PCMask);
+ EXPECT_EQ(FDE.Info, 0x30u);
+ EXPECT_EQ(FDE.getPAuthKey(), 1);
+ EXPECT_EQ(FDE.getFDEType(), FDEType::PCMask);
+ EXPECT_EQ(FDE.getFREType(), FREType::Addr1);
+
+ FDE.setFREType(FREType::Addr4);
+ EXPECT_EQ(FDE.Info, 0x32u);
+ EXPECT_EQ(FDE.getPAuthKey(), 1);
+ EXPECT_EQ(FDE.getFDEType(), FDEType::PCMask);
+ EXPECT_EQ(FDE.getFREType(), FREType::Addr4);
}
TEST(SFrameTest, FREFlags) {
- sframe_fre_info Info = {};
- EXPECT_EQ(Info.fre_info, 0u);
+ FREInfo Info = {};
+ EXPECT_EQ(Info.Info, 0u);
EXPECT_FALSE(Info.isReturnAddressSigned());
- EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_1B);
+ EXPECT_EQ(Info.getOffsetSize(), FREOffset::B1);
EXPECT_EQ(Info.getOffsetCount(), 0u);
- EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+ EXPECT_EQ(Info.getBaseRegister(), BaseReg::FP);
Info.setReturnAddressSigned(true);
- EXPECT_EQ(Info.fre_info, 0x80u);
+ EXPECT_EQ(Info.Info, 0x80u);
EXPECT_TRUE(Info.isReturnAddressSigned());
- EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_1B);
+ EXPECT_EQ(Info.getOffsetSize(), FREOffset::B1);
EXPECT_EQ(Info.getOffsetCount(), 0u);
- EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+ EXPECT_EQ(Info.getBaseRegister(), BaseReg::FP);
- Info.setOffsetSize(SFRAME_FRE_OFFSET_4B);
- EXPECT_EQ(Info.fre_info, 0xc0u);
+ Info.setOffsetSize(FREOffset::B4);
+ EXPECT_EQ(Info.Info, 0xc0u);
EXPECT_TRUE(Info.isReturnAddressSigned());
- EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetSize(), FREOffset::B4);
EXPECT_EQ(Info.getOffsetCount(), 0u);
- EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+ EXPECT_EQ(Info.getBaseRegister(), BaseReg::FP);
Info.setOffsetCount(3);
- EXPECT_EQ(Info.fre_info, 0xc6u);
+ EXPECT_EQ(Info.Info, 0xc6u);
EXPECT_TRUE(Info.isReturnAddressSigned());
- EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetSize(), FREOffset::B4);
EXPECT_EQ(Info.getOffsetCount(), 3u);
- EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_FP);
+ EXPECT_EQ(Info.getBaseRegister(), BaseReg::FP);
- Info.setBaseRegister(SFRAME_BASE_REG_SP);
- EXPECT_EQ(Info.fre_info, 0xc7u);
+ Info.setBaseRegister(BaseReg::SP);
+ EXPECT_EQ(Info.Info, 0xc7u);
EXPECT_TRUE(Info.isReturnAddressSigned());
- EXPECT_EQ(Info.getOffsetSize(), SFRAME_FRE_OFFSET_4B);
+ EXPECT_EQ(Info.getOffsetSize(), FREOffset::B4);
EXPECT_EQ(Info.getOffsetCount(), 3u);
- EXPECT_EQ(Info.getBaseRegister(), SFRAME_BASE_REG_SP);
+ EXPECT_EQ(Info.getBaseRegister(), BaseReg::SP);
}
} // namespace
More information about the llvm-commits
mailing list