* -fPIE : Compile as a 'position-independent executable'. This allows code and data sections of the executable to be installed at random locations in the address space, and comes with a mild cost due to needing extra indirections to handle position-independent code.
* -Wformat-security: adds some extra warnings around possible misuse of printf and scanf.
* -fstack-protector-strong --param=ssp-buffer-size=4: adds extra code in functions to check that stack buffer overflows likely haven't occurred. The second bit does it for every variable at least 4 bytes in size.
* -fcf-protection: this enables Intel CET instructions to check control flow integrity. This essentially causes the hardware to have a shadow stack and other tracking bits to prevent ROP attacks from occurring, but it does require very new hardware to work correctly.
* -Wimplicit-fallthrough: warns if switch cases don't have breaks.
* -D_FORTIFY_SOURCE=2: this causes several basic C functions (such as memcpy) in glibc to compile in a somewhat more secure manner, namely aborting the program if it can detect that it's going to overflow the bounds of an object. The '2' level adds extra checks that prohibits some legal C behavior (for example, buffer overflows that run into a different subobject of the same object).
* -s: Strip the resulting binary after linking.
* -fomit-frame-pointer: This is already the default on x86-64, and maybe ARM/AArch64 as well (I don't have those ABIs thoroughly memorized).
* -Wl,-z,now: Dynamic symbol resolution has to happen at load time rather than lazily. This can cause issues if you're relying on a symbol to be provided by a shared library you're loading dynamically (not a common case, as most people are liable to use dladdr instead).
* -Wl,-z,relro: Make sections that need to be writable only for dynamic relocations be read-only post-relocation-fixup phase.
* -Wl,-z,defs: Make it a linker error if there's a symbol that isn't available in the main executable/library you're building or any of the dynamic libraries you've linked. (Like -Wl,-z,now, this is again something that is unlikely to cause you issues).
* -Wl,-pie: This again enables position-independent executables (and should be triggered by -fPIE, so I'm somewhat curious why -fPIE isn't being passed here instead of -Wl,-pie).
* -Wl,--no-copy-dt-needed-entries: The secondary effect here is likely what is intended. If you're linking against liba.so, and liba.so depends on libb.so, this prevents the application from using libb.so to provide symbols, at least for the purposes of deciding whether to cause an error for -Wl,-z,defs (it should still load those symbols at runtime anyways).