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
-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
#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
gcc -c -fPIC -I/path/to/kernel/headers module.c -o module.o
Example of compiling a kernel module, which typically requires PIC.