Combine data/text sections: Pad sections to alignment (#197)

* Combine data/text sections: Pad all sections to 4-byte minimum alignment

* Update x86 test snapshot

* Read and store object section alignment

* Combine data/text sections: Pad sections to more than 4-byte alignment if they have alignment specified
This commit is contained in:
LagoLunatic
2025-05-06 23:47:08 -04:00
committed by GitHub
parent d0e6c5c057
commit f263e490e3
14 changed files with 431 additions and 65 deletions

View File

@@ -9,7 +9,10 @@ use alloc::{
vec,
vec::Vec,
};
use core::{fmt, num::NonZeroU32};
use core::{
fmt,
num::{NonZeroU32, NonZeroU64},
};
use flagset::{FlagSet, flags};
@@ -70,6 +73,7 @@ pub struct Section {
pub kind: SectionKind,
pub data: SectionData,
pub flags: SectionFlagSet,
pub align: Option<NonZeroU64>,
pub relocations: Vec<Relocation>,
/// Line number info (.line or .debug_line section)
pub line_info: BTreeMap<u64, u32>,
@@ -105,6 +109,12 @@ impl Section {
}
}
// The alignment to use when "Combine data/text sections" is enabled.
pub fn combined_alignment(&self) -> u64 {
const MIN_ALIGNMENT: u64 = 4;
self.align.map(|align| align.get().max(MIN_ALIGNMENT)).unwrap_or(MIN_ALIGNMENT)
}
pub fn relocation_at<'obj>(
&'obj self,
obj: &'obj Object,
@@ -363,6 +373,7 @@ static DUMMY_SECTION: Section = Section {
kind: SectionKind::Unknown,
data: SectionData(Vec::new()),
flags: SectionFlagSet::empty(),
align: None,
relocations: Vec::new(),
line_info: BTreeMap::new(),
virtual_address: None,

View File

@@ -4,7 +4,7 @@ use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::cmp::Ordering;
use core::{cmp::Ordering, num::NonZeroU64};
use anyhow::{Context, Result, anyhow, bail, ensure};
use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
@@ -17,7 +17,7 @@ use crate::{
Symbol, SymbolFlag, SymbolKind,
split_meta::{SPLITMETA_SECTION, SplitMeta},
},
util::{read_u16, read_u32},
util::{align_data_slice_to, align_u64_to, read_u16, read_u32},
};
fn map_section_kind(section: &object::Section) -> SectionKind {
@@ -257,6 +257,7 @@ fn map_sections(
kind,
data: SectionData(data),
flags: Default::default(),
align: NonZeroU64::new(section.align()),
relocations: Default::default(),
virtual_address,
line_info: Default::default(),
@@ -739,7 +740,10 @@ fn do_combine_sections(
}
offsets.push(current_offset);
current_offset += section.size;
let align = section.combined_alignment();
current_offset = align_u64_to(current_offset, align);
data_size += section.data.len();
data_size = align_u64_to(data_size as u64, align) as usize;
num_relocations += section.relocations.len();
}
if data_size > 0 {
@@ -754,6 +758,7 @@ fn do_combine_sections(
let section = &mut sections[i];
section.size = 0;
data.append(&mut section.data.0);
align_data_slice_to(&mut data, section.combined_alignment());
section.relocations.iter_mut().for_each(|r| r.address += offset);
relocations.append(&mut section.relocations);
line_info.append(&mut section.line_info.iter().map(|(&a, &l)| (a + offset, l)).collect());

View File

@@ -14,6 +14,7 @@ expression: "(sections, symbols)"
8,
),
flags: FlagSet(),
align: None,
relocations: [
Relocation {
flags: Elf(
@@ -53,6 +54,7 @@ expression: "(sections, symbols)"
12,
),
flags: FlagSet(Combined),
align: None,
relocations: [
Relocation {
flags: Elf(
@@ -87,6 +89,7 @@ expression: "(sections, symbols)"
0,
),
flags: FlagSet(Hidden),
align: None,
relocations: [],
line_info: {},
virtual_address: None,
@@ -101,6 +104,7 @@ expression: "(sections, symbols)"
0,
),
flags: FlagSet(Hidden),
align: None,
relocations: [],
line_info: {},
virtual_address: None,

View File

@@ -3,6 +3,10 @@ use alloc::{string::String, vec, vec::Vec};
use anyhow::{Result, anyhow};
use object::{Endian, ObjectSection, elf::SHT_NOTE};
#[cfg(feature = "std")]
use crate::util::align_data_to_4;
use crate::util::align_size_to_4;
pub const SPLITMETA_SECTION: &str = ".note.split";
pub const SHT_SPLITMETA: u32 = SHT_NOTE;
pub const ELF_NOTE_SPLIT: &[u8] = b"Split";
@@ -190,17 +194,6 @@ where E: Endian
}
}
fn align_size_to_4(size: usize) -> usize { (size + 3) & !3 }
#[cfg(feature = "std")]
fn align_data_to_4<W: std::io::Write + ?Sized>(writer: &mut W, len: usize) -> std::io::Result<()> {
const ALIGN_BYTES: &[u8] = &[0; 4];
if len % 4 != 0 {
writer.write_all(&ALIGN_BYTES[..4 - len % 4])?;
}
Ok(())
}
// ELF note format:
// Name Size | 4 bytes (integer)
// Desc Size | 4 bytes (integer)