[PATCH] D139092: [RFC][LLD][ELF] Cortex-M Security Extensions (CMSE) Support

Amilendra Kodithuwakku via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 1 02:57:35 PST 2022


amilendra created this revision.
Herald added subscribers: mgrang, kristof.beyls, arichardson, emaste.
Herald added a reviewer: MaskRay.
Herald added a project: All.
amilendra requested review of this revision.
Herald added subscribers: llvm-commits, StephenFan.
Herald added a project: LLVM.

This is to summarize the approach and a request for comments in any constraints
the approach will break. Alternative suggestions are also very much welcome.

Arm v8-M Security Extensions: Requirements on Development Tools [1] specifies
the functionality required by the toolchain. Clang support has already been
added in [2]. This patch implements the linker requirements specified in [1].

Linker Requirements
===================

The linker acts on entry functions generated by the compiler/assembler.
An entry function has two ELF function (STT_FUNC) symbols labelling it:

1. A standard symbol ( e.g. foo)
2. A special symbol (e.g. __acle_se_foo)

See [Req.43], [Req.45].

Generation of secure gateway veneers
------------------------------------

The linker generates an SG veneer for each entry function with external linkage
that has its standard and special symbols labelling the same address
(e.g. foo == __acle_se_foo). Otherwise an SG is assumed to be present. [Req.44]

An SG veneer consists of an SG instruction followed by a B.W instruction that
targets the entry function it veneers. [Req.9], [Req.12]

An SG veneer must be labelled by an ELF symbol that has the same binding, type,
and name as the entry function it veneers. [Req.10]

SG veneer section
-----------------

A toolchain must support creating a section of SG veneers consisting of one or
more veneers placed consecutively in memory. [Req.11]

A section of SG veneers must be aligned to a 32-byte boundary, and must be zero
padded to a 32- byte boundary. [Req.13]

The position of SG veneers in a section must be controllable by the developer.
This allows the developer to fix the addresses of the SG veneers such that
secure code can be updated independently of non-secure code. [Req.14]

Generation of a SG import library
---------------------------------

The linker supports generating an SG import library (import library), which is a
relocatable file containing only copies of the (absolute) symbols of the SGs in
the secure executable. [Req.8]

The import library is used when updating non-secure code to specify to the
linker the fixed addresses of the SG veneers used by secure code [Req.14].

Implementation Notes
====================

External interface
------------------

The external interface of the linker for the CMSE functionality follows the
external interface used by the BFD ld linker.[3]

All SG veneers are placed in the special output section '.gnu.sgstubs'. The
start address of '.gnu.sgstubs' must be set, either with the command-line option
'--section-start' or in a linker script. The ld linker throws an error when the
start address is not specified.

The '--in-implib=file' specifies an input import library whose symbols must keep
the same address in the executable being produced.

ld emits a warning is given if no '--out-implib' is given but new symbols have
been introduced in the executable that should be listed in its import library.
Otherwise, if '--out-implib' is specified, the symbols are added to the output
import library. ld emits a warning is also given if some symbols present in the
input import library have disappeared from the executable.

In ld, the '--in-implib' and '--out-implib' options are effective only when
'--cmse-implib' is specified. '--cmse-implib' was needed in ld maybe because
'--out-implib' already existed for the i386 PE backend [4], so some mechanism
was needed to differentiate its use in the ARM backend. LLD does not implement
'--out-implib' so the '--cmse-implib' option seems redundant at the moment. In
fact, the linker for the proprietary Arm Compiler toolchain (armlink) only
define two options to specify the input and output import libraries,
--import_cmse_lib_in=file and --import_cmse_lib_out=file, respectively. I've
added the '--cmse-implib' option for now, but will remove it if we decide it
unnecessary.

Reading the import library
--------------------------

The input import library is a relocatable object with only a symbol table. This
is similar to the --just-symbols functionality, but is used to inform the linker
of SG veneers that must be placed at fixed addresses. So the symbols in the
input import library will not be added to the global symbol table (symtab).
Instead the information will be maintained via a separate StringMap table which
uses the symbol name as the key.

Generating the SG veneers and SG veneer section
-----------------------------------------------

Generation and positioning of SG veneers is the most complicated part.
There are two types of SG veneers.

1. SG veneers that should be generated by the linker at fixed addresses specified by the input import library.
2. SG veneers that do not have their symbols specified in the input import library which the linker can place at any location within the SG veneer section.

In both cases the standard symbol of the entry functions should be retargetted
to point to the start of the generated SG veneer.

In this patch I've modelled the problem by defining a type of SyntheticSection,
ArmCmseSGVeneer, and two specializations of it, ArmCmseFixedAddressSGVeneer and
ArmCmseVariableAddressSGVeneer. An ArmCmseSGVeneer keeps track of its
corresponding standard and special symbol pair. After the addresses are fixed,
the standard symbol should point to the start address of the ArmCmseSGVeneer,
and the veneer generated in ArmCmseSGVeneer should branch to the special symbol.

ArmCmseSGSection is another type of SyntheticSection which I've used to model
the SG veneer section and is meant to be the parent of all the ArmCmseSGVeneers.
ArmCmseSGSection maintains the range of addresses used by the input import
library. ArmCmseFixedAddressSGVeneers will be placed sparsely at fixed addresses
within that range, and ArmCmseVariableAddressSGVeneer will be placed at
consecutive addresses out of that range.

For now, finalizing the ArmCmseSGSection is done in a single pass after output
addresses have been decided. However, further testing and review may show that
multiple passes needs to be done to finalize the ArmCmseSGSection.

I briefly considered if this can be modelled using the Thunk management
mechanism, but decided against it because seemed to me that Thunks are generated
for relocations to symbols, while the CMSE veneers do not require relocations.

TODO
====

This patch is still very much a prototype that demonstrates only the most
common use cases of writing and reading an import library, placement of veneers
at fixed and variable addresses.

Much of error handling is yet to be implemented. I plan to follow the error
messages emitted by ld.

More tests related to SG veneer section positioning needs to be done.
More testing on various combinations of symbol bindings, types, visibility needs
to be done.

Writing the import library to disk is a very hacky implementation that seg
faults in multi threaded invocations. The tests workaround this by using
--threads=1. This needs to be refactored and fixed before landing.

Reference
=========

[1] Arm® v8-M Security Extensions: Requirements on Development Tools Version: 1.2
Downloadable from https://developer.arm.com/documentation/ecm0359818/latest
[2] https://reviews.llvm.org/D71129 [ARM][CMSE] Implement CMSE attributes
[3] https://sourceware.org/binutils/docs/ld/ARM.html
[4] https://sourceware.org/pipermail/binutils/2015-December/091424.html

The following are the requirements specified in [1] that are implemented by the linker.

[Req.8] A relocatable file containing only copies of the (absolute) symbols of the
secure gateways in the secure executable must be available to link non-secure
code against.
[Req.9] A toolchain must support generating a secure gateway veneer for each entry
function with external linkage. It consists of an SG instruction followed by a
B.W instruction that targets the entry function it veneers.
[Req.10] A secure gateway veneer must be labelled by an ELF symbol that has the same
binding, type, and name as the function it veneers, following the rules for C
entities as defined by [AAELF]
[Req.11] A toolchain must support creating a vector of secure gateway veneers
consisting of one or more veneers placed consecutively in memory.
[Req.12] Excluding the first instruction of a secure gateway veneer, a veneer
must not contain the bit pattern of the SG instruction on a 2-byte boundary.
[Req.13] A vector of secure gateway veneers must be aligned to a 32-byte
boundary, and must be zero padded to a 32-byte boundary.
[Req.14] You must have granted control of the position of secure gateway veneers
in a vector.
[Req.43] An entry function has two ELF function ( STT_FUNC ) symbols labelling it:

  • A symbol that follows the standard naming for C entities as defined by
    [AAELF] labels the function’s inline secure gateway if it has one, otherwise
    the function’s first instruction.
  • A special symbol that prefixes the standard function name with __acle_se_
    labels the function’s first non-SG instruction.

[Req.44] A toolchain must generate a secure gateway veneer for an entry function
that has both its symbols labelling the same address. Otherwise a secure gateway
is assumed to be present.
[Req.45] The address of an entry function must be the address labelled by its
standard symbol.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139092

Files:
  lld/ELF/Arch/ARM.cpp
  lld/ELF/Config.h
  lld/ELF/Driver.cpp
  lld/ELF/InputFiles.cpp
  lld/ELF/InputFiles.h
  lld/ELF/Options.td
  lld/ELF/SymbolTable.cpp
  lld/ELF/SymbolTable.h
  lld/ELF/SyntheticSections.cpp
  lld/ELF/SyntheticSections.h
  lld/ELF/Target.h
  lld/ELF/Writer.cpp
  lld/test/ELF/Inputs/arm-cmse-implib-1.s
  lld/test/ELF/Inputs/arm-cmse-implib-2.s
  lld/test/ELF/aarch64-cmse.s
  lld/test/ELF/arm-cmse-error.s
  lld/test/ELF/arm-cmse-implib.s
  lld/test/ELF/arm-cmse-veneers.s

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D139092.479223.patch
Type: text/x-patch
Size: 42239 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20221201/8bb0cc9f/attachment.bin>


More information about the llvm-commits mailing list