Skip to content

Commit

Permalink
Add -Z no-unique-section-names to reduce ELF header bloat.
Browse files Browse the repository at this point in the history
This change adds a new compiler flag that can help reduce the size of
ELF binaries that contain many functions.

By default, when enabling function sections (which is the default for most
targets), the LLVM backend will generate different section names for each
function. For example, a function "func" would generate a section called
".text.func". Normally this is fine because the linker will merge all those
sections into a single one in the binary. However, starting with LLVM 12
(llvm/llvm-project@ee5d1a0), the backend will
also generate unique section names for exception handling, resulting in
thousands of ".gcc_except_table.*" sections ending up in the final binary
because some linkers don't currently merge or strip these EH sections.
This can bloat the ELF headers and string table significantly in
binaries that contain many functions.

The new option is analogous to Clang's -fno-unique-section-names, and
instructs LLVM to generate the same ".text" and ".gcc_except_table"
section for each function, resulting in smaller object files and
potentially a smaller final binary.
  • Loading branch information
jblazquez committed Oct 11, 2021
1 parent 25ec827 commit 4ed846a
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Expand Up @@ -161,6 +161,7 @@ pub fn target_machine_factory(
let ffunction_sections =
sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.function_sections);
let fdata_sections = ffunction_sections;
let funique_section_names = !sess.opts.debugging_opts.no_unique_section_names;

let code_model = to_llvm_code_model(sess.code_model());

Expand Down Expand Up @@ -205,6 +206,7 @@ pub fn target_machine_factory(
use_softfp,
ffunction_sections,
fdata_sections,
funique_section_names,
trap_unreachable,
singlethread,
asm_comments,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Expand Up @@ -2153,6 +2153,7 @@ extern "C" {
UseSoftFP: bool,
FunctionSections: bool,
DataSections: bool,
UniqueSectionNames: bool,
TrapUnreachable: bool,
Singlethread: bool,
AsmComments: bool,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Expand Up @@ -740,6 +740,7 @@ fn test_debugging_options_tracking_hash() {
tracked!(new_llvm_pass_manager, Some(true));
tracked!(no_generate_arange_section, true);
tracked!(no_link, true);
tracked!(no_unique_section_names, true);
tracked!(no_profiler_runtime, true);
tracked!(osx_rpath_install_name, true);
tracked!(panic_abort_tests, true);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Expand Up @@ -459,6 +459,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
bool FunctionSections,
bool DataSections,
bool UniqueSectionNames,
bool TrapUnreachable,
bool Singlethread,
bool AsmComments,
Expand Down Expand Up @@ -488,6 +489,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
}
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.MCOptions.AsmVerbose = AsmComments;
Options.MCOptions.PreserveAsmComments = AsmComments;
Options.MCOptions.ABIName = ABIStr;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Expand Up @@ -1188,6 +1188,8 @@ options! {
"compile without linking"),
no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
"run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
no_unique_section_names: bool = (false, parse_bool, [TRACKED],
"do not use unique names for text and data sections when -Z function-sections is used"),
no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
"prevent automatic injection of the profiler_builtins crate"),
normalize_docs: bool = (false, parse_bool, [TRACKED],
Expand Down
@@ -0,0 +1,9 @@
# `no-unique-section-names`

------------------------

This flag currently applies only to ELF-based targets using the LLVM codegen backend. It prevents the generation of unique ELF section names for each separate code and data item when `-Z function-sections` is also in use, which is the default for most targets. This option can reduce the size of object files, and depending on the linker, the final ELF binary as well.

For example, a function `func` will by default generate a code section called `.text.func`. Normally this is fine because the linker will merge all those `.text.*` sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, so you would see a section name of `.gcc_except_table.func` in the object file and potentially in the final ELF binary, which could add significant bloat to programs that contain many functions.

This flag instructs LLVM to use the same `.text` and `.gcc_except_table` section name for each function, and it is analogous to Clang's `-fno-unique-section-names` option.

0 comments on commit 4ed846a

Please sign in to comment.