Generate BTI information to SP manifest
For raw binary SPs the SP manifest needs to capture if for executable
regions GP bit needs to be enabled. Extend elf_segments_to_manifest.py
to generate the needed attributes based on the elf input file.
Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
Change-Id: Ic0abfa977d67c15925c2dda8db8a81608f5c56c6
diff --git a/tools/python/elf_segments_to_manifest.py b/tools/python/elf_segments_to_manifest.py
index 5528164..378c318 100644
--- a/tools/python/elf_segments_to_manifest.py
+++ b/tools/python/elf_segments_to_manifest.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-3-Clause
#
-# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
"""
This module's goal is to take an ELF file as an input and extract the memory
@@ -12,9 +12,11 @@
from enum import IntFlag
from math import ceil
+from elftools import __version__ as module_version
from elftools.elf.elffile import ELFFile
from elftools.elf.constants import P_FLAGS
+assert module_version == "0.31"
class ElfSegmentsToManifest:
"""
@@ -23,6 +25,33 @@
"""
PAGE_SIZE = 4096
+ class GnuNotePropertySection:
+ """ Provides an API to process GNU note property section. """
+
+ GNU_PROPERTY_AARCH64_FEATURE_1_BTI = 1
+
+ def __init__(self, section):
+ self.section = section
+
+ def is_bti_enabled(self):
+ """ Returns whether any of the notes has a BTI enable property """
+
+ def is_bti_property(prop):
+ return prop['pr_type'] == "GNU_PROPERTY_AARCH64_FEATURE_1_AND" and \
+ prop['pr_data'] & self.GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+
+ def has_bti_property(note):
+ return note["n_name"] == 'GNU' and note["n_type"] == "NT_GNU_PROPERTY_TYPE_0" and \
+ any(is_bti_property(p) for p in note["n_desc"])
+
+ return any(has_bti_property(n) for n in self.section.iter_notes())
+
+ @staticmethod
+ def is_matching_section(section):
+ """ Checks if the section is a GNU note property section """
+ return section.name == '.note.gnu.property'
+
+
class Region:
""" Describes a memory region and its attributes. """
@@ -31,6 +60,8 @@
R = 0x01
W = 0x02
X = 0x04
+ S = 0x08
+ GP = 0x10
def get_attr(self):
""" Queries the value of the attributes in manifest format. """
@@ -82,6 +113,11 @@
self.end_address = region.end_address
self.sections += region.sections
+ def set_bti_if_executable(self):
+ """ Sets GP flag if the region is executable. """
+ if self.attributes & self.ManifestMemAttr.X:
+ self.attributes |= self.ManifestMemAttr.GP
+
def write_manifest(self, load_base_addr, manifest_file):
"""
Writes the region into the manifest file. The address is adjusted by load_base_address.
@@ -131,7 +167,16 @@
return segment.header.p_align == ElfSegmentsToManifest.PAGE_SIZE
assert is_aligned(segment), "Segments must be 4k aligned, check LD script"
self.segment = segment
- self.sections = [s for s in sections if self.segment.section_in_segment(s)]
+ self.sections = []
+ self.gnu_note = None
+
+ for section in sections:
+ if self.segment.section_in_segment(section):
+ if ElfSegmentsToManifest.GnuNotePropertySection.is_matching_section(section):
+ self.gnu_note = ElfSegmentsToManifest.GnuNotePropertySection(section)
+ else:
+ self.sections.append(section)
+
self.regions = []
self.merge_sections_to_regions()
@@ -150,6 +195,11 @@
self.regions.append(region)
current_region = region
+ # Set GP only for the executable regions if BTI is enabled in the segment
+ if self.gnu_note and self.gnu_note.is_bti_enabled():
+ for region in self.regions:
+ region.set_bti_if_executable()
+
def write_manifest(self, load_base_addr, manifest_file):
""" Writes the regions into the manifest file. """
for region in self.regions:
diff --git a/tools/python/requirements.txt b/tools/python/requirements.txt
index 81bf605..208c74f 100644
--- a/tools/python/requirements.txt
+++ b/tools/python/requirements.txt
@@ -1,7 +1,7 @@
#
-# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
-pyelftools==0.28
+pyelftools==0.31