| ============================ | |
| Aligned Instruction Bundling | |
| ============================ | |
| Overview | |
| ======== | |
| *Aligned instruction bundling* partitions the instructions in a section into | |
| fixed-size, naturally aligned groups called bundles, and guarantees that no | |
| instruction ever crosses a bundle boundary. Consecutive instructions can also | |
| be grouped so that the assembler guarantees the whole group resides within a | |
| single bundle. | |
| Bundling is a building block for software-based fault isolation (SFI) and | |
| sandboxing schemes. Forcing every instruction to begin at one of a statically | |
| known set of offsets gives the instruction stream a single canonical decoding: | |
| control flow cannot jump into the middle of an instruction to manufacture a | |
| different, unchecked instruction sequence. When combined with masking of | |
| indirect branch targets to bundle-aligned addresses, this constrains all | |
| control flow to a statically verifiable set of locations and instructions. | |
| Bundling is used by the x86-64 implementation of :doc:`Lightweight Fault | |
| Isolation (LFI) <LFI>`. | |
| .. note:: | |
| The current LLVM implementation supports bundling only for x86 ELF targets. | |
| Other targets and object file formats reject the directives below rather | |
| than emit unbundled code silently. | |
| ``.bundle_align_mode`` | |
| ====================== | |
| :: | |
| .bundle_align_mode abs-expr | |
| Enables aligned bundle mode and sets the bundle size to ``2^abs-expr`` bytes, | |
| where ``abs-expr`` is a power-of-two exponent between 1 and 30 (as for the | |
| ``.p2align`` directive). For example, ``.bundle_align_mode 5`` selects 32-byte | |
| bundles. Unlike GNU as, ``.bundle_align_mode 0`` is rejected: bundling cannot be | |
| turned off once enabled. | |
| While bundling is enabled, the assembler ensures that no single instruction | |
| spans a boundary between two bundles. When an instruction would not fit in the | |
| space remaining in the current bundle, that space is filled with no-op | |
| instructions so the instruction starts at the beginning of the next bundle. | |
| Enabling bundle mode also raises the alignment of every text section that | |
| receives instructions to at least the bundle size. | |
| Once enabled, bundle mode stays in effect for the rest of the file and its | |
| bundle size is fixed. | |
| ``.bundle_lock`` and ``.bundle_unlock`` | |
| ======================================= | |
| :: | |
| .bundle_lock [align_to_end] | |
| ...instructions... | |
| .bundle_unlock | |
| A ``.bundle_lock`` / ``.bundle_unlock`` pair encloses a sequence of | |
| instructions that must all be placed in a single bundle. The assembler inserts | |
| padding before the sequence, if necessary, so that the entire group lands | |
| within one bundle rather than straddling a boundary. | |
| The enclosed sequence must fit within a single bundle -- it is an error if the | |
| total size of the locked instructions exceeds the bundle size. | |
| Both directives are only valid in an executable section after bundle mode has | |
| been enabled with ``.bundle_align_mode``. A ``.bundle_unlock`` must be matched | |
| by a preceding ``.bundle_lock``, and a section may not be switched while a | |
| ``.bundle_lock`` is open. A group may not end in a bare instruction prefix, | |
| which the assembler could not keep attached to the instruction it modifies. | |
| ``align_to_end`` | |
| ---------------- | |
| By default a locked group is padded at the front so that it starts far enough | |
| into the bundle to fit. With the ``align_to_end`` option the group is instead | |
| padded so that its last instruction ends exactly on a bundle boundary. | |
| Padding | |
| ======= | |
| By default, bundle padding is emitted as no-op instructions, and neither an | |
| instruction nor a padding no-op is ever allowed to cross a bundle boundary. | |
| Prefix padding (x86) | |
| -------------------- | |
| On x86 the assembler can instead absorb some of the required padding into | |
| neighboring instructions by prepending otherwise-ignored instruction prefixes | |
| to them, avoiding standalone no-ops. This is controlled by: | |
| .. option:: --x86-pad-max-prefix-size=<N> | |
| Maximum number of prefixes the assembler may add to an instruction for | |
| padding. ``0`` (the default) disables prefix padding, so only no-op | |
| instructions are used. | |
| Padding is only ever traded for instruction bytes within the bundle that holds | |
| it, so this cannot move an instruction or a locked group across a boundary. It | |
| does change where labels land, so it may break assumptions about labels | |
| corresponding to particular instructions. |