-mfpu
The -mfpu option in GCC (GNU Compiler Collection) specifies the floating-point unit (FPU) used for floating-point operations. This option is particularly used in ARM architectures. Here are some common ARM processors along with their corresponding -mfpu options:
- Cortex-M0/M0+: -mfpu=none
- Cortex-M4: -mfpu=fpv4-sp-d16
- Cortex-A7: -mfpu=neon-vfpv4
- Cortex-A8: -mfpu=neon
- Cortex-A9: -mfpu=vfpv3-d16
- Cortex-A15: -mfpu=neon-vfpv4
- Cortex-A53: -mfpu=crypto-neon-fp-armv8
- Cortex-A57: -mfpu=crypto-neon-fp-armv8 These options enable the compiler to generate optimized code tailored for the specific floating-point unit available on each processor. The -mfpu option also allows you to specify an FPU that supports SIMD, for executing multiple operations simultaneously.
-mfloat-abi The -mfloat-abi option in GCC defines the floating-point ABI (Application Binary Interface) to be used for floating-point operations. In ARM architecture, it dictates how floating-point values are passed between functions and how floating-point operations are executed.
-mfloat-abi Options
- -mfloat-abi=soft: Utilizes software floating-point library calls for floating-point operations. No hardware floating-point unit (FPU) is required, making it suitable for processors lacking an FPU.
- -mfloat-abi=softfp: Uses hardware floating-point instructions but passes floating-point arguments in integer registers. This option provides compatibility with -mfloat-abi=soft while still leveraging the FPU for improved performance.
- -mfloat-abi=hard: Uses hardware floating-point instructions and passes floating-point arguments in floating-point registers.
Example:
gcc -mfloat-abi=hard -mfpu=neon -o myprogram myprogram.c
-march
The -march option in GCC specifies the target architecture for which the code should be generated. This option enables the compiler to optimize the code for a specific CPU type, capitalizing on the features and instructions available for that architecture.
Common -march Options
- -march=armv7-a: Targets the ARMv7-A architecture, commonly found in Cortex-A series processors.
- -march=armv8-a: Targets the ARMv8-A architecture, which supports 64-bit instructions and is used in Cortex-A53, Cortex-A57, and other ARMv8 processors.
- -march=x86–64: Targets the 64-bit x86 architecture, used in modern Intel and AMD processors.
- -march=native: Optimizes the code for the architecture of the host machine on which the compiler is running, automatically detecting the host architecture for the most optimized code generation.
-mcpu The -mcpu option in GCC specifies the target CPU for which the code should be optimized. This option allows the compiler to generate code that fully exploits the specific features and instructions of the target CPU.
Common -mcpu Options
- -mcpu=cortex-m0: Targets the ARM Cortex-M0 processor.
- -mcpu=cortex-m4: Targets the ARM Cortex-M4 processor.
- -mcpu=cortex-a53: Targets the ARM Cortex-A53 processor.
- -mcpu=cortex-a57: Targets the ARM Cortex-A57 processor.
- -mcpu=generic: Generates code for a generic ARM CPU without specific optimizations for any particular model.
-fPIC
The -fPIC option in GCC stands for “Position Independent Code.” This option generates machine code that is not dependent on a specific memory address, making it particularly useful for creating shared libraries.
When creating shared libraries, -fPIC ensures that the code can be loaded at any memory address without modification. This capability allows multiple programs to share a single copy of the library in memory, thereby reducing overall memory usage.
Position-independent code can enhance security by making it more challenging for attackers to predict the location of specific functions or data, thus mitigating certain types of attacks. Example:
gcc -fPIC -c mysource.c
gcc -shared -o libmylibrary.so mysource.o
-fno-stack-protector The -fno-stack-protector option in GCC disables the stack protection mechanisms that are enabled by default with the -fstack-protector option. Stack protection is a security feature designed to prevent stack buffer overflows, which can be exploited to execute arbitrary code.
Disabling stack protection removes the Stack Canary: special values placed on the stack to detect buffer overflows. When -fno-stack-protector is used, these canaries are not inserted.
While disabling stack protection can slightly enhance performance by eliminating the overhead of checking canary values, it comes at the cost of reduced security. In embedded systems and in legacy code disabling stack protection may be necessary for compatibility.
-fstack-protector-strong This option protects not only functions with character arrays but also those with local variables that are arrays, references, or pointers. This broader scope increases the likelihood of detecting and preventing stack buffer overflows.
Stack Protection Options
- -fstack-protector: Protects functions with character arrays larger than 8 bytes.
- -fstack-protector-all: Protects all functions, regardless of whether they have arrays.
- -fstack-protector-strong: Provides a balance by protecting a wider range of functions than -fstack-protector but fewer than -fstack-protector-all.
Stack protection mechanisms enabled by -fstack-protector and -fstack-protector-strong are active at runtime.
When a function is called, a special value known as a “canary” is placed on the stack just before the return address. This canary value is a known, random value that is difficult for an attacker to predict. Before returning from the function, the compiler-generated code checks if the canary value has been altered.
- If the canary value remains unchanged, the function proceeds to return normally.
- If the canary value has been modified, it indicates a potential buffer overflow, and the program typically aborts to prevent further damage.
Utilizing stack protection options like -fstack-protector-strong enhances the security of your applications by providing an additional layer of defense against stack-based attacks.