gcc -fPIC Option

The -fPIC (Position-Independent Code) option in gcc is crucial for generating code that can be loaded at any arbitrary memory address without modification. This is a fundamental requirement for creating shared libraries (.so files) in Linux and other Unix-like systems.

Syntax

gcc -fPIC source.c -o source.o

-fPIC Option Details

  • Purpose: Generate position-independent code
  • Requirement: Essential for shared libraries (.so)
  • Mechanism: Uses indirect addressing for global data and function calls
  • Benefit: Allows a single copy of the library code to be shared among multiple processes

Description

When a program uses a shared library, the library's code is loaded into the program's memory space. Since multiple programs might use the same shared library, and each might load it at a different memory address, the library's code must be able to execute correctly regardless of where it is loaded. This is where position-independent code comes in.

Key behaviors:

  • Generates code that does not rely on fixed memory addresses.
  • Uses global offset table (GOT) and procedure linkage table (PLT) for addressing.
  • Enables efficient memory usage by allowing code sharing.
  • Slightly larger code size and potential minor performance overhead compared to non-PIC.

Benefits of Position-Independent Code (PIC)

  • Memory Efficiency: Shared libraries can be loaded once and mapped into multiple processes.
  • Reduced Disk I/O: Less code needs to be loaded from disk for each process.
  • Dynamic Linking: Allows programs to link with libraries at runtime.
  • Security: Important for Address Space Layout Randomization (ASLR).

Common Examples

Command Description Output
gcc -c -fPIC source.c Compile source to PIC object file source.o
gcc -shared -o libmylib.so obj1.o obj2.o Create shared library from PIC objects libmylib.so
gcc main.c -L. -lmylib -o myprogram Link executable with shared library myprogram

Detailed Examples

Creating a simple shared library

// mylib.c
#include <stdio.h>

void hello_from_lib() {   printf("Hello from shared library!\n"); }
// Compile to PIC object
gcc -c -fPIC mylib.c -o mylib.o

// Create shared library
gcc -shared -o libmylib.so mylib.o
// main.c
#include <stdio.h>
void hello_from_lib(); // Function prototype

int main() {   hello_from_lib();   return 0; }
# Compile and link with shared library
gcc main.c -L. -lmylib -o myprogram # Run: LD_LIBRARY_PATH=. ./myprogram # Output: Hello from shared library!

Step-by-step process to create and use a shared library.

Compiling a module for a kernel

# Kernel modules often require PIC
gcc -c -fPIC -I/path/to/kernel/headers module.c -o module.o

Example of compiling a kernel module, which typically requires PIC.

See also