From Fedora Project Wiki

Packaging Static Libraries

Summary

MUST: Packages that install static library archives (.a files) must do exactly one of:

  • build them as PIC objects
  • document why the static libraries are not built PIC AND receive explicit approval from FESCo.
  • build both PIC and non-PIC libraries, with a .pc file for each for dependent packages to use

Definitions

PIC

Position-independent code (PIC) is machine instruction code that executes properly regardless of where in memory it resides. PIC is commonly used for shared libraries, so that the same library code can be loaded in a location in each program address space where it won't overlap any other uses of memory (for example, other shared libraries). Position-independent code can be copied to any memory location and executed without modification. This differs from relocatable code, which requires special processing by a link editor or program loader to make it suitable for execution at a given location. Position independent code must adhere to a specific set of semantics in the source code, and compiler support is required. Instructions that refer to specific memory addresses, such as absolute branches, must be replaced with equivalent program counter relative instructions.

PIE

Position-independent executables (PIE) are executable binaries made entirely from position-independent code. PIE binaries are used in Fedora to allow Exec Shield to use address space layout randomization to prevent attackers from knowing where existing executable code is during an exploit that relies on knowing the offset of the executable code in the binary, such as return-to-libc attacks.

Rationale

Some architectures (including i386, but not including x86_64) permit non-position-independent code. A static library may, through subsequent linking, be included in any of another static library, an application, or a shared library.

On architectures that permit it, non-PIC code comes with a tradeoff. Since the load address is assumed, the compiler has an additional register to use, which can be a - usually small - performance benefit. However, any otherwise relocatable object (shared library or PIE executable) that the non-PIC code is linked into will require text relocations. Text relocations impose a performance penalty on executable startup, and effectively make the code unshareable, thus negating the benefits of making the code into a shared library in the first place.

In general, it is preferable to err on the side of PIC. Text relocations are incompatible with some of the security measures in Fedora, and the performance benefit of actually being able to share your shared library code in memory outweighs any performance benefit from the additional register. Static libraries in particular should be built PIC, since if not their non-PIC-ness effectively poisons any shared libraries they are included in.

Exceptions

Non-PIE applications may legitimately include non-PIC code with no performance penalty. If a static library is only included in non-PIE applications, it need not be built PIC. This case is expected to be rare, limited mostly to numeric computation libraries like atlas or fftw where performance is critical.

In any case, non-PIC static libraries need explicit approval from FESCo.

Packages that install non-PIC static libraries should be explicitly listed in the wiki somewhere.

Documentation

Typically all that's needed to build a library PIC is to add -fPIC to CFLAGS. If a library contains assembly code, adding -fPIC won't make the assembly magically become PIC; code changes will be necessary in this case.

Autotools-based projects can usually disable static library creation by configuring with --disable-static, and can force PIC static libraries by configuring with --with-pic.

Templates for packaging PIC and non-PIC static libraries

PIC static library

The library must be renamed to libfoo-pic.a, where libfoo.a is the original name.

Here is a template for the necessary libfoo-pic.pc file:

prefix=/usr
exec_prefix=/usr
libdir=/usr/lib64
includedir=/usr/include

Name: foo
Description: Does foo type operations
Version: 1.0.0
Requires: xproto
Cflags: -I${includedir}
Libs: -L${libdir} -lfoo
Libs.private: -lfoo-pic

Be sure to adjust the variables appropriately, depending on the architecture target (e.g. libdir=).

non-PIC static library

The library must be renamed to libfoo-nonpic.a, where libfoo.a is the original name.

Here is a template for the necessary libfoo-nonpic.pc file:

prefix=/usr
exec_prefix=/usr
libdir=/usr/lib64
includedir=/usr/include

Name: foo
Description: Does foo type operations
Version: 1.0.0
Requires: xproto
Cflags: -I${includedir}
Libs: -L${libdir} -lfoo
Libs.private: -lfoo-nonpic

Be sure to adjust the variables appropriately, depending on the architecture target (e.g. libdir=).