Blame SOURCES/buildflags.md

7b79ae
This document contains documentation of the individual compiler flags
7b79ae
and how to use them.
7b79ae
7b79ae
[TOC]
7b79ae
7b79ae
# Using RPM build flags
7b79ae
7b79ae
For packages which use autoconf to set up the build environment, use
7b79ae
the `%configure` macro to obtain the full complement of flags, like
7b79ae
this:
7b79ae
7b79ae
    %configure
7b79ae
7b79ae
This will invoke the `./configure` with arguments (such as
7b79ae
`--prefix=/usr`) to adjust the paths to the packaging defaults.
7b79ae
7b79ae
As a side effect, this will set the environment variables `CFLAGS`,
7b79ae
`CXXFLAGS`, `FFLAGS`, `FCFLAGS`, and `LDFLAGS`, so they can be used by
7b79ae
makefiles and other build tools.  (However, existing values for this
7b79ae
variables are not overwritten.)
7b79ae
7b79ae
If your package does not use autoconf, you can still set the same
7b79ae
environment variables using
7b79ae
7b79ae
    %set_build_flags
7b79ae
7b79ae
early in the `%build` section.  (Again, existing environment variables
7b79ae
are not overwritten.)
7b79ae
7b79ae
Individual build flags are also available through RPM macros:
7b79ae
7b79ae
* `%{build_cflags}` for the C compiler flags (also known as the
7b79ae
  `CFLAGS` variable).  Also historically available as `%{optflags}`.
7b79ae
  Furthermore, at the start of the `%build` section, the environment
7b79ae
  variable `RPM_OPT_FLAGS` is set to this value.
7b79ae
* `%{build_cxxflags}` for the C++ compiler flags (usually assigned to
7b79ae
  the `CXXFLAGS` shell variable).
7b79ae
* `%{build_fflags} for `FFLAGS` (the Fortran compiler flags, also
7b79ae
  known as the `FCFLAGS` variable).
7b79ae
* `%{build_ldflags}` for the link editor (ld) flags, usually known as
7b79ae
  `LDFLAGS`.  Note that the contents quotes linker arguments using
7b79ae
  `-Wl`, so this variable is intended for use with the `gcc` compiler
7b79ae
  driver.  At the start of the `%build` section, the environment
7b79ae
  variable `RPM_LD_FLAGS` is set to this value.
7b79ae
7b79ae
These RPM macros do not alter shell environment variables.
7b79ae
7b79ae
For some other build tools separate mechanisms exist:
7b79ae
7b79ae
* CMake builds use the the `%cmake` macro from the `cmake-rpm-macros`
7b79ae
  package.
7b79ae
7b79ae
Care must be taking not to compile the current selection of compiler
7b79ae
flags into any RPM package besides `redhat-rpm-config`, so that flag
7b79ae
changes are picked up automatically once `redhat-rpm-config` is
7b79ae
updated.
7b79ae
7b79ae
# Flag selection for the build type
7b79ae
7b79ae
The default flags are suitable for building applications.
7b79ae
7b79ae
For building shared objects, you must compile with `-fPIC` in
7b79ae
(`CFLAGS` or `CXXFLAGS`) and link with `-shared` (in `LDFLAGS`).
7b79ae
7b79ae
For other considerations involving shared objects, see:
7b79ae
7b79ae
* [Fedora Packaging Guidelines: Shared Libraries](https://fedoraproject.org/wiki/Packaging:Guidelines#Shared_Libraries)
7b79ae
7b79ae
# Customizing compiler flags
7b79ae
7b79ae
It is possible to set RPM macros to change some aspects of the
7b79ae
compiler flags.  Changing these flags should be used as a last
7b79ae
recourse if other workarunds are not available.
7b79ae
7b79ae
### Lazy binding
7b79ae
7b79ae
If your package depends on the semantics of lazy binding (e.g., it has
7b79ae
plugins which load additional plugins to complete their dependencies,
7b79ae
before which some referenced functions are undefined), you should put
7b79ae
`-Wl,-z,lazy` at the end of the `LDFLAGS` setting when linking objects
7b79ae
which have such requirements.  Under these circumstances, it is
7b79ae
unnecessary to disable hardened builds (and thus lose full ASLR for
7b79ae
executables), or link everything without `-Wl,z,now` (non-lazy
7b79ae
binding).
7b79ae
7b79ae
### Hardened builds
7b79ae
7b79ae
By default, the build flags enable fully hardened builds.  To change
7b79ae
this, include this in the RPM spec file:
7b79ae
7b79ae
    %undefine _hardened_build
7b79ae
7b79ae
This turns off certain hardening features, as described in detail
7b79ae
below.  The main difference is that executables will be
7b79ae
position-dependent (no full ASLR) and use lazy binding.
7b79ae
7b79ae
### Annotated builds/watermarking
7b79ae
7b79ae
By default, the build flags cause a special output section to be
7b79ae
included in ELF files which describes certain aspects of the build.
7b79ae
To change this for all compiler invocations, include this in the RPM
7b79ae
spec file:
7b79ae
7b79ae
    %undefine _annotated_build
7b79ae
7b79ae
Be warned that this turns off watermarking, making it impossible to do
7b79ae
full hardening coverage analysis for any binaries produced.
7b79ae
7b79ae
It is possible to disable annotations for individual compiler
7b79ae
invocations, using the `-fplugin-arg-annobin-disable` flag.  However,
7b79ae
the annobin plugin must still be loaded for this flag to be
7b79ae
recognized, so it has to come after the hardening flags on the command
7b79ae
line (it has to be added at the end of `CFLAGS`, or specified after
7b79ae
the `CFLAGS` variable contents).
7b79ae
7b79ae
### Strict symbol checks in the link editor (ld)
7b79ae
7b79ae
Optionally, the link editor will refuse to link shared objects which
7b79ae
contain undefined symbols.  Such symbols lack symbol versioning
7b79ae
information and can be bound to the wrong (compatibility) symbol
7b79ae
version at run time, and not the actual (default) symbol version which
7b79ae
would have been used if the symbol definition had been available at
7b79ae
static link time.  Furthermore, at run time, the dynamic linker will
7b79ae
not have complete dependency information (in the form of DT_NEEDED
7b79ae
entries), which can lead to errors (crashes) if IFUNC resolvers are
7b79ae
executed before the shared object containing them is fully relocated.
7b79ae
7b79ae
To switch on these checks, define this macro in the RPM spec file:
7b79ae
7b79ae
    %define _strict_symbol_defs_build 1
7b79ae
7b79ae
If this RPM spec option is active, link failures will occur if the
7b79ae
linker command line does not list all shared objects which are needed.
7b79ae
In this case, you need to add the missing DSOs (with linker arguments
7b79ae
such as `-lm`).  As a result, the link editor will also generated the
7b79ae
necessary DT_NEEDED entries.
7b79ae
7b79ae
In some cases (such as when a DSO is loaded as a plugin and is
7b79ae
expected to bind to symbols in the main executable), undefined symbols
7b79ae
are expected.  In this case, you can add
7b79ae
7b79ae
    %undefine _strict_symbol_defs_build
7b79ae
7b79ae
to the RPM spec file to disable these strict checks.  Alternatively,
7b79ae
you can pass `-z undefs` to ld (written as `-Wl,-z,undefs` on the gcc
7b79ae
command line).  The latter needs binutils 2.29.1-12.fc28 or later.
7b79ae
7b79ae
# Individual compiler flags
7b79ae
7b79ae
Compiler flags end up in the environment variables `CFLAGS`,
7b79ae
`CXXFLAGS`, `FFLAGS`, and `FCFLAGS`.
7b79ae
7b79ae
The general (architecture-independent) build flags are:
7b79ae
7b79ae
* `-O2`: Turn on various GCC optimizations.  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O2).
7b79ae
  Optimization improves performance, the accuracy of warnings, and the
7b79ae
  reach of toolchain-based hardening, but it makes debugging harder.
7b79ae
* `-g`: Generate debugging information (DWARF).  In Fedora, this data
7b79ae
  is separated into `-debuginfo` RPM packages whose installation is
7b79ae
  optional, so debuging information does not increase the size of
7b79ae
  installed binaries by default.
7b79ae
* `-pipe`: Run compiler and assembler in parallel and do not use a
7b79ae
  temporary file for the assembler input.  This can improve
7b79ae
  compilation performance.  (This does not affect code generation.)
7b79ae
* `-Wall`: Turn on various GCC warnings.
7b79ae
  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wall).
7b79ae
* `-Werror=format-security`: Turn on format string warnings and treat
7b79ae
  them as errors.
7b79ae
  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat-security).
7b79ae
  This can occasionally result in compilation errors.  In this case,
7b79ae
  the best option is to rewrite the source code so that only constant
7b79ae
  format strings (string literals) are used.
7b79ae
* `-Wp,-D_FORTIFY_SOURCE=2`: Source fortification activates various
7b79ae
  hardening features in glibc:
7b79ae
    * String functions such as `memcpy` attempt to detect buffer lengths
7b79ae
      and terminate the process if a buffer overflow is detected.
7b79ae
    * `printf` format strings may only contain the `%n` format specifier
7b79ae
      if the format string resides in read-only memory.
7b79ae
    * `open` and `openat` flags are checked for consistency with the
7b79ae
      presence of a *mode* argument.
7b79ae
    * Plus other minor hardening changes.
7b79ae
  (These changes can occasionally break valid programs.)
7b79ae
* `-fexceptions`: Provide exception unwinding support for C programs.
7b79ae
  See the [`-fexceptions` option in the GCC
7b79ae
  manual](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fexceptions)
7b79ae
  and the [`cleanup` variable
7b79ae
  attribute](https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute).
7b79ae
  This also hardens cancellation handling in C programs because
7b79ae
  it is not required to use an on-stack jump buffer to install
7b79ae
  a cancellation handler with `pthread_cleanup_push`.  It also makes
7b79ae
  it possible to unwind the stack (using C++ `throw` or Rust panics)
7b79ae
  from C callback functions if a C library supports non-local exits
7b79ae
  from them (e.g., via `longjmp`).
7b79ae
* `-Wp,-D_GLIBCXX_ASSERTIONS`: Enable lightweight assertions in the
7b79ae
  C++ standard library, such as bounds checking for the subscription
7b79ae
  operator on vectors.  (This flag is added to both `CFLAGS` and
7b79ae
  `CXXFLAGS`; C compilations will simply ignore it.)
7b79ae
* `-fstack-protector-strong`: Instrument functions to detect
7b79ae
  stack-based buffer overflows before jumping to the return address on
7b79ae
  the stack.  The *strong* variant only performs the instrumentation
7b79ae
  for functions whose stack frame contains addressable local
7b79ae
  variables.  (If the address of a variable is never taken, it is not
7b79ae
  possible that a buffer overflow is caused by incorrect pointer
7b79ae
  arithmetic involving a pointer to that variable.)
7b79ae
* `-grecord-gcc-switches`: Include select GCC command line switches in
7b79ae
  the DWARF debugging information.  This is useful for detecting the
7b79ae
  presence of certain build flags and general hardening coverage.
7b79ae
7b79ae
For hardened builds (which are enabled by default, see above for how
7b79ae
to disable them), the flag
7b79ae
`-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1` is added to the
7b79ae
command line.  It adds the following flag to the command line:
7b79ae
7b79ae
*   `-fPIE`: Compile for a position-independent executable (PIE),
7b79ae
    enabling full address space layout randomization (ASLR).  This is
7b79ae
    similar to `-fPIC`, but avoids run-time indirections on certain
7b79ae
    architectures, resulting in improved performance and slightly
7b79ae
    smaller executables.  However, compared to position-dependent code
7b79ae
    (the default generated by GCC), there is still a measurable
7b79ae
    performance impact.
7b79ae
7b79ae
    If the command line also contains `-r` (producing a relocatable
7b79ae
    object file), `-fpic` or `-fPIC`, this flag is automatically
7b79ae
    dropped.  (`-fPIE` can only be used for code which is linked into
7b79ae
    the main program.) Code which goes into static libraries should be
7b79ae
    compiled with `-fPIE`, except when this code is expected to be
7b79ae
    linked into DSOs, when `-fPIC` must be used.
7b79ae
7b79ae
    To be effective, `-fPIE` must be used with the `-pie` linker flag
7b79ae
    when producing an executable, see below.
7b79ae
7b79ae
To support [binary watermarks for ELF
7b79ae
objects](https://fedoraproject.org/wiki/Toolchain/Watermark) using
7b79ae
annobin, the `-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1` flag is
7b79ae
added by default.  This can be switched off by undefining the
7b79ae
`%_annotated_build` RPM macro (see above).
7b79ae
7b79ae
### Architecture-specific compiler flags
7b79ae
7b79ae
These compiler flags are enabled for all builds (hardened/annotated or
7b79ae
not), but their selection depends on the architecture:
7b79ae
7b79ae
*   `-fstack-clash-protection`: Turn on instrumentation to avoid
7b79ae
    skipping the guard page in large stack frames.  (Without this flag,
7b79ae
    vulnerabilities can result where the stack overlaps with the heap,
7b79ae
    or thread stacks spill into other regions of memory.)  This flag is
7b79ae
    fully ABI-compatible and has adds very little run-time overhead, but
7b79ae
    is only available on certain architectures (currently aarch64, i386,
7b79ae
    ppc64, ppc64le, s390x, x86_64).
7b79ae
*   `-fcf-protection`: Instrument binaries to guard against
7b79ae
    ROP/JOP attacks.  Used on i686 and x86_64.
7b79ae
*   `-m64` and `-m32`: Some GCC builds support both 32-bit and 64-bit in
7b79ae
    the same compilation.  For such architectures, the RPM build process
7b79ae
    explicitly selects the architecture variant by passing this compiler
7b79ae
    flag.
7b79ae
*   `-fasynchronous-unwind-tables`: Generate full unwind information
7b79ae
    covering all program points.  This is required for support of
7b79ae
    asynchronous cancellation and proper unwinding from signal
7b79ae
    handlers.  It also makes performance and debugging tools more
7b79ae
    useful because unwind information is available without having to
7b79ae
    install (and load) debugging ienformation.
7b79ae
    Asynchronous unwind tables are enabled for aarch64, i686, s390x,
7b79ae
    and x86_64.  They are not needed on armhfp, ppc64 and ppc64le due
7b79ae
    to architectural differences in stack management.  On these
7b79ae
    architectures, `-fexceptions` (see above) still enables regular
7b79ae
    unwind tables (or they are enabled by default even without this
7b79ae
    option).
7b79ae
*   `-funwind-tables`: A subset of the unwind information restricted
7b79ae
    to actual call sites.  Used on ppc64, ppc64le.  Also implied by
7b79ae
    `-fexceptions`.
7b79ae
7b79ae
In addition, `redhat-rpm-config` re-selects the built-in default
7b79ae
tuning in the `gcc` package.  These settings are:
7b79ae
7b79ae
*   **armhfp**: `-march=armv7-a -mfpu=vfpv3-d16  -mfloat-abi=hard`
7b79ae
    selects an Arm subarchitecture based on the ARMv7-A architecture
7b79ae
    with 16 64-bit floating point registers.  `-mtune=cortex-8a` selects
7b79ae
    tuning for the Cortex-A8 implementation (while preserving compatibility
7b79ae
    with other ARMv7-A implementations).  `-mabi=aapcs-linux` switches to
7b79ae
    the AAPCS ABI for GNU/Linux.
7b79ae
*   **i686**: `-march=x86-64` is used to select a minimum supported
7b79ae
    CPU level matching the baseline for the x86_64 architecture.
7b79ae
    `-mtune=generic` activates tuning for a current blend of CPUs.
7b79ae
    `-mfpmath=sse` uses the SSE2 unit for floating point math,
7b79ae
    instead of the legacy i387 FPU, avoiding issues related to excess
7b79ae
    precision.  `-mstackrealign` ensures that the generated code
7b79ae
    does not assume 16-byte stack alignment (as required by the current
7b79ae
    i386 ABI), but stays compatible with application code compiled
7b79ae
    before the introduction of 16-byte stack alignment along with SSE2
7b79ae
    support.
7b79ae
*   **ppc64le**: `-mcpu=power8 -mtune=power8` selects a minimum supported
7b79ae
    CPU level of POWER8 (the first CPU with ppc64le support) and tunes
7b79ae
    for POWER8.
7b79ae
*   **s390x**: `-march=z13 -mtune=z14` specifies a minimum supported CPU
7b79ae
    level of z13, while optimizing for a subsequent CPU generation
7b79ae
    (z14).
7b79ae
*   **x86_64**: `-mtune=generic` selects tuning which is expected to
7b79ae
     beneficial for a broad range of current CPUs.
7b79ae
*   **ppc64** and **aarch64** do not have any architecture-specific tuning.
7b79ae
7b79ae
# Individual linker flags
7b79ae
7b79ae
Linker flags end up in the environment variable `LDFLAGS`.
7b79ae
7b79ae
The linker flags listed below are injected.  Note that they are
7b79ae
prefixed with `-Wl` because it is expected that these flags are passed
7b79ae
to the compiler driver `gcc`, and not directly to the link editor
7b79ae
`ld`.
7b79ae
7b79ae
* `-z relro`: Activate the *read-only after relocation* feature.
7b79ae
  Constant data and relocations are placed on separate pages, and the
7b79ae
  dynamic linker is instructed to revoke write permissions after
7b79ae
  dynamic linking.  Full protection of relocation data requires the
7b79ae
  `-z now` flag (see below).
7b79ae
* `-z defs`: Refuse to link shared objects (DSOs) with undefined symbols
7b79ae
  (optional, see above).
7b79ae
7b79ae
For hardened builds, the
7b79ae
`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld` flag is added to the
7b79ae
compiler driver command line.  (This can be disabled by undefining the
7b79ae
`%_hardened_build` macro; see above) This activates the following
7b79ae
linker flags:
7b79ae
7b79ae
* `-pie`: Produce a PIE binary.  This is only activated for the main
7b79ae
  executable, and only if it is dynamically linked.  This requires
7b79ae
  that all objects which are linked in the main executable have been
7b79ae
  compiled with `-fPIE` or `-fPIC` (or `-fpie` or `-fpic`; see above).
7b79ae
  By itself, `-pie` has only a slight performance impact because it
7b79ae
  disables some link editor optimization, however the `-fPIE` compiler
7b79ae
  flag has some overhead.
7b79ae
* `-z now`: Disable lazy binding and turn on the `BIND_NOW` dynamic
7b79ae
  linker feature.  Lazy binding involves an array of function pointers
7b79ae
  which is writable at run time (which could be overwritten as part of
7b79ae
  security exploits, redirecting execution).  Therefore, it is
7b79ae
  preferable to turn of lazy binding, although it increases startup
7b79ae
  time.
7b79ae
7b79ae
# Support for extension builders
7b79ae
7b79ae
Some packages include extension builders that allow users to build
7b79ae
extension modules (which are usually written in C and C++) under the
7b79ae
control of a special-purpose build system.  This is a common
7b79ae
functionality provided by scripting languages such as Python and Perl.
7b79ae
Traditionally, such extension builders captured the Fedora build flags
7b79ae
when these extension were built.  However, these compiler flags are
7b79ae
adjusted for a specific Fedora release and toolchain version and
7b79ae
therefore do not work with a custom toolchain (e.g., different C/C++
7b79ae
compilers), and users might want to build their own extension modules
7b79ae
with such toolchains.
7b79ae
7b79ae
The macros `%{extension_cflags}`, `%{extension_cxxflags}`,
7b79ae
`%{extension_fflags}`, `%{extension_ldflags}` contain a subset of
7b79ae
flags that have been adjusted for compatibility with alternative
7b79ae
toolchains, while still preserving some of the compile-time security
7b79ae
hardening that the standard Fedora build flags provide.
7b79ae
7b79ae
The current set of differences are:
7b79ae
7b79ae
* No GCC plugins (such as annobin) are activated.
7b79ae
* No GCC spec files (`-specs=` arguments) are used.
7b79ae
7b79ae
Additional flags may be removed in the future if they prove to be
7b79ae
incompatible with alternative toolchains.
7b79ae
7b79ae
Extension builders should detect whether they are performing a regular
7b79ae
RPM build (e.g., by looking for an `RPM_OPT_FLAGS` variable).  In this
7b79ae
case, they should use the *current* set of Fedora build flags (that
7b79ae
is, the output from `rpm --eval '%{build_cflags}'` and related
7b79ae
commands).  Otherwise, when not performing an RPM build, they can
7b79ae
either use hard-coded extension builder flags (thus avoiding a
7b79ae
run-time dependency on `redhat-rpm-config`), or use the current
7b79ae
extension builder flags (with a run-time dependency on
7b79ae
`redhat-rpm-config`).
7b79ae
7b79ae
As a result, extension modules built for Fedora will use the official
7b79ae
Fedora build flags, while users will still be able to build their own
7b79ae
extension modules with custom toolchains.