This commit provides linker support for Cortex-M Security Extensions (CMSE).
The specification for this feature can be found in ARM v8-M Security Extensions:
Requirements on Development Tools.
The linker synthesizes a security gateway veneer in a special section;
.gnu.sgstubs, when it finds non-local symbols __acle_se_<entry> and <entry>,
defined relative to the same text section and having the same address. The
address of <entry> is retargeted to the starting address of the
linker-synthesized security gateway veneer in section .gnu.sgstubs.
In summary, the linker translates input:
.text entry: __acle_se_entry: [entry_code]
into:
.section .gnu.sgstubs entry: SG B.W __acle_se_entry .text __acle_se_entry: [entry_code]
If addresses of __acle_se_<entry> and <entry> are not equal, the linker
considers that <entry> already defines a secure gateway veneer so does not
synthesize one.
If --out-implib=<out.lib> is specified, the linker writes the list of secure
gateway veneers into a CMSE import library <out.lib>. The CMSE import library
will have 3 sections: .symtab, .strtab, .shstrtab. For every secure gateway
veneer <entry> at address <addr>, .symtab contains a SHN_ABS symbol <entry> with
value <addr>.
If --in-implib=<in.lib> is specified, the linker reads the existing CMSE import
library <in.lib> and preserves the entry function addresses in the resulting
executable and new import library.
For the benefit of our future selves I think it would be useful to put a summary comment about how the LLD CMSE code fits together.
The Arm Cortex-M Security Extensions (CMSE) splits a system into two parts, the non-secure and secure states with the secure state inaccessible from the non-secure state, apart from an area of memory in secure state called the secure gateway which is accessible from non-secure state. The secure gateway contains one or more entry points which must start with a landing pad instruction SG. Arm recommends that the secure gateway consists only of secure gateway veneers, which are made up of a SG instruction followed by a branch to the destination in secure state. Full details can be found in Arm v8-M Security Extensions Requirements on Development Tools.
The CMSE model of software development requires the non-secure and secure states to be developed as two separate programs. The non-secure developer is provided with an import library defining symbols describing the entry points in the secure gateway. No additional linker support is required for the non-secure state.
Development of the secure state requires linker support to manage the secure gateway veneers. The management consists of:
The secure gateway veneers are created in an import library, which is just an ELF object with a symbol table. The import library is controlled by two command line options:
--in-implib (specify an input import library from a previous revision of the program).
--out-implib (specify an output import library to be created by the linker).
The input import library is used to manage consistency of the secure entry points. The output import library is for new and updated secure entry points.
The symbol convention that identifies secure entry functions is the prefix acle_se_ for a symbol called name the linker is expected to create a secure gateway veneer if symbols acles_se_name and name have the same address. After creating a secure gateway veneer the symbol name labels the secure gateway veneer and the __acle_se_name labels the function definition.
The LLD implementation: