From 61ff50ec5844b0d5ba0fced1899fee582626f158 Mon Sep 17 00:00:00 2001 From: Petteri Kangaslampi Date: Tue, 27 May 2025 20:39:30 +0000 Subject: [PATCH] Do not duplicate relocation data Skip relocation data while processing segments since it will be added separately at the end of the file. Note that this logic skips entire segments if they contain nothing but relocation data so may break if a segment contains both relocations an other sections (but is that possible?) Also handle .rela relocation sections --- src/convert.rs | 127 ++++++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 50 deletions(-) diff --git a/src/convert.rs b/src/convert.rs index 80e8830..9979827 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -663,37 +663,22 @@ pub fn elf_to_tbf( } // Insert padding between segments if needed. - if let Some(last_segment_address_end) = last_segment_address_end { + let padding = if let Some(last_segment_address_end) = last_segment_address_end { // We have a previous segment. Now, check if there is any padding // between the segments in the .elf. let chk_padding = (segment.p_paddr as usize).checked_sub(last_segment_address_end); - if let Some(padding) = chk_padding { - if padding > 0 { - if verbose { - println!(" Including padding between segments size={}", padding); - } - - if padding >= 4096 { - // Warn the user that we're inserting a large amount of - // padding (>= 4096, which is the ELF file segment padding) - // into the binary. This can be a sign of an incorrect / - // broken ELF file (where not all LOADed non-zero sized - // sections are marked to be loaded from flash). - println!(" Warning! Inserting a large amount of padding."); - } - - // Insert the padding into the generated binary. - binary.extend(vec![0; padding]); - binary_index += padding; - } + padding } else { println!( " Warning! Expecting ELF sections to be in physical (load) address order." ); println!(" Not inserting padding, the resulting TBF may be broken."); + 0 } - } + } else { + 0 + }; if verbose { println!( @@ -743,10 +728,13 @@ pub fn elf_to_tbf( // Iterate all sections that are in the segment we just loaded. // - // We need two things: + // We need three things: // 1. To find all relevant relocation data we need to add. // 2. To find if there are any writeable flash regions we need to set in // the TBF header. + // 3. To figure out if this segment contains relocation data only. + // If so, skip it, since we'll add relocation data at the end. + let mut reloc_only = true; for (sh_name, shdr) in elf_sections.iter() { // Skip zero size sections. if shdr.sh_size == 0 { @@ -765,34 +753,46 @@ pub fn elf_to_tbf( ); } + // If this section contains relocations we should skip it now, + // since we're gathering relocs below to output at the end of + // the file. Otherwise we'd duplicate the data. + if sh_name.starts_with(".rel.") || sh_name.starts_with(".rela.") { + continue; + } else { + reloc_only = false; + } + // First, determine if we need to check for relocation data for // this section. The section must be marked `SHF_WRITE`, as to // use the relocations at runtime requires being able to update // the contents of the section. if shdr.sh_flags as u32 & elf::abi::SHF_WRITE > 0 { - // Then check if there is a ".rel.
" section - // that we need to include in the relocation data. - - // relocation_section_name = ".rel" + section_name - let mut relocation_section_name: String = ".rel".to_owned(); - relocation_section_name.push_str(sh_name); - - // Get the contents of the relocation data if it exists and - // add that data to a buffer of relocation data. - let rel_data = elf_sections - .iter() - .find(|(sh_name, _)| *sh_name == relocation_section_name) - .map_or(&[] as &[u8], |(_, shdr)| { - elf_file.section_data(shdr).map_or(&[], |(data, _)| data) - }); - relocation_binary.extend(rel_data); - - if verbose && !rel_data.is_empty() { - println!( - " Including relocation data ({0}). Length: {1} ({1:#x}) bytes.", - relocation_section_name, - rel_data.len(), - ); + // Check for both .rel and .rela + for prefix in [".rel", ".rela"] { + // Then check if there is a ".rel[a].
" section + // that we need to include in the relocation data. + + // relocation_section_name = ".rel[a]" + section_name + let mut relocation_section_name: String = prefix.to_owned(); + relocation_section_name.push_str(sh_name); + + // Get the contents of the relocation data if it exists and + // add that data to a buffer of relocation data. + let rel_data = elf_sections + .iter() + .find(|(sh_name, _)| *sh_name == relocation_section_name) + .map_or(&[] as &[u8], |(_, shdr)| { + elf_file.section_data(shdr).map_or(&[], |(data, _)| data) + }); + relocation_binary.extend(rel_data); + + if verbose && !rel_data.is_empty() { + println!( + " Including relocation data ({0}). Length: {1} ({1:#x}) bytes.", + relocation_section_name, + rel_data.len(), + ); + } } } @@ -814,12 +814,39 @@ pub fn elf_to_tbf( } } - // Save the end of this segment so we can check if padding is required - // between segments. - last_segment_address_end = Some(end_segment as usize); + if reloc_only { + if verbose { + println!(" Skipping segment since it only contains relocs"); + } + } else { + // Handle padding now that we know we want something from this + // segment + if padding > 0 { + if verbose { + println!(" Including padding between segments size={}", padding); + } + + if padding >= 4096 { + // Warn the user that we're inserting a large amount of + // padding (>= 4096, which is the ELF file segment padding) + // into the binary. This can be a sign of an incorrect / + // broken ELF file (where not all LOADed non-zero sized + // sections are marked to be loaded from flash). + println!(" Warning! Inserting a large amount of padding."); + } + + // Insert the padding into the generated binary. + binary.extend(vec![0; padding]); + binary_index += padding; + } + // Save the end of this segment so we can check if padding is required + // between segments. + last_segment_address_end = Some((segment.p_paddr + segment.p_filesz) as usize); - binary.extend(content); - binary_index += segment.p_filesz as usize; + // Finally add the actual content + binary.extend(content); + binary_index += segment.p_filesz as usize; + } } // Now that we know where the end of the section data is, we can check for