blob: 33041e48dcbd09172cb8301c2fbc70358cf10a58 [file]
/* ELF metadata for AArch64 architecture.
Copyright (C) 2024-2026 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#define INCLUDE_STRING
#define INCLUDE_ALGORITHM
#define INCLUDE_MEMORY
#define INCLUDE_VECTOR
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "output.h"
#include "aarch64-elf-metadata.h"
/* Defined for convenience. */
#define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
namespace aarch64 {
constexpr unsigned GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000;
constexpr unsigned GNU_PROPERTY_AARCH64_FEATURE_1_BTI = (1U << 0);
constexpr unsigned GNU_PROPERTY_AARCH64_FEATURE_1_PAC = (1U << 1);
constexpr unsigned GNU_PROPERTY_AARCH64_FEATURE_1_GCS = (1U << 2);
namespace {
std::string
gnu_property_features_to_string (unsigned feature_1_and)
{
struct flag_name
{
unsigned int mask;
const char *name;
};
static const flag_name flags[] = {
{GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI"},
{GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC"},
{GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS"},
};
const char *separator = "";
std::string s_features;
for (auto &flag : flags)
if (feature_1_and & flag.mask)
{
s_features.append (separator).append (flag.name);
separator = ", ";
}
return s_features;
};
} // namespace anonymous
section_note_gnu_property::section_note_gnu_property ()
: m_feature_1_and (0) {}
void
section_note_gnu_property::bti_enabled ()
{
m_feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
}
void
section_note_gnu_property::pac_enabled ()
{
m_feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
}
void
section_note_gnu_property::gcs_enabled ()
{
m_feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
}
void
section_note_gnu_property::write () const
{
if (m_feature_1_and)
{
/* Generate .note.gnu.property section. */
switch_to_section (
get_section (".note.gnu.property", SECTION_NOTYPE, NULL));
/* PT_NOTE header: namesz, descsz, type.
namesz = 4 ("GNU\0")
descsz = 16 (Size of the program property array)
[(12 + padding) * Number of array elements]
type = 5 (NT_GNU_PROPERTY_TYPE_0). */
assemble_align (POINTER_SIZE);
assemble_integer (GEN_INT (4), 4, 32, 1);
assemble_integer (GEN_INT (ROUND_UP (12, POINTER_BYTES)), 4, 32, 1);
assemble_integer (GEN_INT (5), 4, 32, 1);
/* PT_NOTE name. */
assemble_string ("GNU", 4);
/* PT_NOTE contents for NT_GNU_PROPERTY_TYPE_0:
type = GNU_PROPERTY_AARCH64_FEATURE_1_AND
datasz = 4
data = feature_1_and. */
fputs (integer_asm_op (4, true), asm_out_file);
fprint_whex (asm_out_file, GNU_PROPERTY_AARCH64_FEATURE_1_AND);
putc ('\n', asm_out_file);
assemble_integer (GEN_INT (4), 4, 32, 1);
fputs (integer_asm_op (4, true), asm_out_file);
fprint_whex (asm_out_file, m_feature_1_and);
if (flag_debug_asm)
{
auto const &s_features
= gnu_property_features_to_string (m_feature_1_and);
asm_fprintf (asm_out_file,
"\t%s GNU_PROPERTY_AARCH64_FEATURE_1_AND (%s)\n",
ASM_COMMENT_START, s_features.c_str ());
}
else
putc ('\n', asm_out_file);
/* Pad the size of the note to the required alignment. */
assemble_align (POINTER_SIZE);
}
}
} // namespace aarch64