Blame SOURCES/buildflags.md

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