Skip to content

Commit 37d55f3

Browse files
committed
build/elf: don't require the same alignment for all load segments
1 parent d65bc75 commit 37d55f3

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

src/build/elf.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ pub struct Builder<'data> {
2828
/// Use to set the file class when writing the ELF file.
2929
pub is_64: bool,
3030
/// The alignment of [`elf::PT_LOAD`] segments.
31+
///
32+
/// This is an informational field and is not used when writing the ELF file.
33+
/// It can be optionally be used when calling [`Segments::add_load_segment`].
34+
///
35+
/// It is determined heuristically when reading the ELF file. Currently,
36+
/// if all load segments have the same alignment, that alignment is used,
37+
/// otherwise it is set to 1.
3138
pub load_align: u64,
3239
/// The file header.
3340
pub header: Header,
@@ -145,10 +152,11 @@ impl<'data> Builder<'data> {
145152
for segment in segments {
146153
if segment.p_type(endian) == elf::PT_LOAD {
147154
let p_align = segment.p_align(endian).into();
148-
if builder.load_align != 0 && builder.load_align != p_align {
149-
return Err(Error::new("Unsupported alignments for PT_LOAD segments"));
155+
if builder.load_align == 0 {
156+
builder.load_align = p_align;
157+
} else if builder.load_align != p_align {
158+
builder.load_align = 1;
150159
}
151-
builder.load_align = p_align;
152160
}
153161

154162
let id = builder.segments.next_id();
@@ -167,9 +175,8 @@ impl<'data> Builder<'data> {
167175
marker: PhantomData,
168176
});
169177
}
170-
if !builder.segments.is_empty() && builder.load_align == 0 {
171-
// There should be at least one PT_LOAD segment.
172-
return Err(Error::new("Unsupported segments without a PT_LOAD segment"));
178+
if builder.load_align == 0 {
179+
builder.load_align = 1;
173180
}
174181

175182
for (index, section) in sections.iter().enumerate().skip(1) {
@@ -2365,6 +2372,8 @@ impl<'data> Segments<'data> {
23652372
/// Add a new `PT_LOAD` segment to the table.
23662373
///
23672374
/// The file offset and address will be derived from the current maximum for any segment.
2375+
/// The address will be chosen so that `p_paddr % align == p_offset % align`.
2376+
/// You may wish to use [`Builder::load_align`] for the alignment.
23682377
pub fn add_load_segment(&mut self, flags: u32, align: u64) -> &mut Segment<'data> {
23692378
let mut max_offset = 0;
23702379
let mut max_addr = 0;

0 commit comments

Comments
 (0)