From 47ad587a52f36f0d4c98a29b37e4ddfa07eb78fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 3 Apr 2026 21:02:50 +0200 Subject: [PATCH] feat: Support `--use-android-relr-tags` --- libwild/src/args/elf.rs | 22 +++++++++++++++-- libwild/src/elf_writer.rs | 52 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/libwild/src/args/elf.rs b/libwild/src/args/elf.rs index 608f38c6c..2d60e5ce2 100644 --- a/libwild/src/args/elf.rs +++ b/libwild/src/args/elf.rs @@ -115,6 +115,7 @@ pub struct ElfArgs { pub(crate) max_page_size: Option, pub(crate) trace: bool, pack_dyn_relocs: PackDynRelocs, + pub(crate) use_android_relr_tags: bool, pub(crate) relocation_model: RelocationModel, pub(crate) should_output_executable: bool, @@ -217,7 +218,6 @@ pub(super) const IGNORED_FLAGS: &[&str] = &[ "fix-cortex-a53-835769", "fix-cortex-a53-843419", "discard-all", - "use-android-relr-tags", "x", // alias for --discard-all ]; @@ -228,7 +228,6 @@ const DEFAULT_FLAGS: &[&str] = &[ "no-add-needed", "discard-locals", "no-fatal-warnings", - "no-use-android-relr-tags", ]; const DEFAULT_SHORT_FLAGS: &[&str] = &[ "X", // alias for --discard-locals @@ -292,6 +291,7 @@ impl Default for ElfArgs { hash_style: HashStyle::Both, trace: false, pack_dyn_relocs: PackDynRelocs::None, + use_android_relr_tags: false, unresolved_symbols: UnresolvedSymbols::ReportAll, error_unresolved_symbols: true, @@ -1709,6 +1709,24 @@ fn setup_argument_parser() -> ArgumentParser { Ok(()) }); + parser + .declare() + .long("use-android-relr-tags") + .help("Use Android version of SHT_RELR and DT_RELR") + .execute(|args, _modifier_stack| { + args.use_android_relr_tags = true; + Ok(()) + }); + + parser + .declare() + .long("no-use-android-relr-tags") + .help("Do not use Android version of SHT_RELR and DT_RELR (default)") + .execute(|args, _modifier_stack| { + args.use_android_relr_tags = false; + Ok(()) + }); + add_silently_ignored_flags(&mut parser); add_default_flags(&mut parser); diff --git a/libwild/src/elf_writer.rs b/libwild/src/elf_writer.rs index 525d40bd2..2eded24e7 100644 --- a/libwild/src/elf_writer.rs +++ b/libwild/src/elf_writer.rs @@ -4577,17 +4577,50 @@ const EPILOGUE_DYNAMIC_ENTRY_WRITERS: &[DynamicEntryWriter] = &[ }), DynamicEntryWriter::optional( object::elf::DT_RELR, - |inputs| inputs.has_data_in_section(output_section_id::RELR_DYN), + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) + && !has_android_relr_tags(inputs) + }, |inputs| inputs.vma_of_section(output_section_id::RELR_DYN), ), DynamicEntryWriter::optional( object::elf::DT_RELRSZ, - |inputs| inputs.has_data_in_section(output_section_id::RELR_DYN), + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) + && !has_android_relr_tags(inputs) + }, |inputs| inputs.size_of_section(output_section_id::RELR_DYN), ), DynamicEntryWriter::optional( object::elf::DT_RELRENT, - |inputs| inputs.has_data_in_section(output_section_id::RELR_DYN), + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) + && !has_android_relr_tags(inputs) + }, + |_| elf::RELR_ENTRY_SIZE, + ), + DynamicEntryWriter::optional( + // TODO(object): Not yet added + 0x6fff_e000, + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) && has_android_relr_tags(inputs) + }, + |inputs| inputs.vma_of_section(output_section_id::RELR_DYN), + ), + DynamicEntryWriter::optional( + // TODO(object): Not yet added + 0x6fff_e001, + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) && has_android_relr_tags(inputs) + }, + |inputs| inputs.size_of_section(output_section_id::RELR_DYN), + ), + DynamicEntryWriter::optional( + // TODO(object): Not yet added + 0x6fff_e003, + |inputs| { + inputs.has_data_in_section(output_section_id::RELR_DYN) && has_android_relr_tags(inputs) + }, |_| elf::RELR_ENTRY_SIZE, ), DynamicEntryWriter::optional( @@ -4849,7 +4882,14 @@ fn write_section_headers(out: &mut [u8], layout: &ElfLayout) -> Result { let entry = entries.next().unwrap(); let e = LittleEndian; entry.sh_name.set(e, name_offset); - entry.sh_type.set(e, section_type.raw()); + + let sh_type = if layout.args().use_android_relr_tags && section_type == sht::RELR { + // TODO(object): Not yet added + 0x6fffff00 + } else { + section_type.raw() + }; + entry.sh_type.set(e, sh_type); // TODO: Sections are always uncompressed and the output compression is not supported yet. entry.sh_flags.set( @@ -5267,6 +5307,10 @@ fn has_rela_dyn(inputs: &DynamicEntryInputs) -> bool { relative.mem_size > 0 || general.mem_size > 0 } +fn has_android_relr_tags(inputs: &DynamicEntryInputs) -> bool { + inputs.args.use_android_relr_tags +} + pub(crate) fn verify_resolution_allocation( output_sections: &OutputSections, output_order: &OutputOrder,