Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fef9bc6
multiboot2: elf_sections: add `elf` library into cargo.toml
an-owl Apr 8, 2026
9d2e015
multiboot2: self_sections: Fixed bug where `flags` truncated bits.
an-owl Apr 8, 2026
8c7e7e6
multiboot2: self_sections: Removed ElfSectionIter, replaced with `Sec…
an-owl Apr 8, 2026
b059c4d
multiboot2: self_sections: Implemented From to cast &ElfSectionsTag i…
an-owl Apr 9, 2026
7d58983
multiboot2: elf_sections: Removed hand-rolled elf types and replaced …
an-owl Apr 14, 2026
ba8a113
multiboot2: elf_sections: Added methods for getting the section name.
an-owl Apr 15, 2026
ef0f0b9
multiboot2: builder: Fixed bug in test `build_and_parse` where ElfSec…
an-owl Apr 15, 2026
698f270
multiboot2: lib: Fixed up unit tests for changes in elf_sections
an-owl Apr 15, 2026
7e4957f
integration tests: Fixed up integration tests for changes in elf_sect…
an-owl Apr 15, 2026
627bfb4
multiboot2: elf_sections: Replaced magic numbers with constants from …
an-owl Apr 15, 2026
9579bca
multiboot2: elf_sections: Added `UserDefined` section type to `ElfSec…
an-owl Apr 15, 2026
b70df61
multiboot2: elf_sections: Added `STRINGS` and `THREAD_LOCAL` flags to…
an-owl Apr 15, 2026
272f6f1
multiboot2: elf_sections: add `elf` library into cargo.toml
an-owl Apr 8, 2026
1531d25
multiboot2: self_sections: Fixed bug where `flags` truncated bits.
an-owl Apr 8, 2026
1242b28
multiboot2: self_sections: Removed ElfSectionIter, replaced with `Sec…
an-owl Apr 8, 2026
1495736
multiboot2: self_sections: Implemented From to cast &ElfSectionsTag i…
an-owl Apr 9, 2026
67d1427
multiboot2: elf_sections: Removed hand-rolled elf types and replaced …
an-owl Apr 14, 2026
928910a
multiboot2: elf_sections: Added methods for getting the section name.
an-owl Apr 15, 2026
36b10c9
multiboot2: builder: Fixed bug in test `build_and_parse` where ElfSec…
an-owl Apr 15, 2026
c1897ae
multiboot2: lib: Fixed up unit tests for changes in elf_sections
an-owl Apr 15, 2026
cc737c9
integration tests: Fixed up integration tests for changes in elf_sect…
an-owl Apr 15, 2026
282eeca
multiboot2: elf_sections: Replaced magic numbers with constants from …
an-owl Apr 15, 2026
0b8ca24
multiboot2: elf_sections: Added `UserDefined` section type to `ElfSec…
an-owl Apr 15, 2026
089a839
multiboot2: elf_sections: Added `STRINGS` and `THREAD_LOCAL` flags to…
an-owl Apr 15, 2026
2a55795
Updated CHANGELOG.md
an-owl Jun 10, 2026
e455889
multiboot2: Tweaked ElfSectionsExt docs
an-owl Jun 10, 2026
9b87c7a
multiboot2: elf_sections: Changed pointer cast to use `core::ptr::wit…
an-owl Jun 10, 2026
6039b98
Merge remote-tracking branch 'origin/elf' into elf
an-owl Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package.license = "MIT/Apache-2.0"
[workspace.dependencies]
# Dependencies of multiboot2 et al.
bitflags = { version = "2.11", default-features = false }
elf = { version = "0.8", default-features = false }
log = { version = "~0.4", default-features = false }
ptr_meta = { version = "~0.3", default-features = false }
thiserror = { version = "2.0", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions multiboot2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ builder = ["alloc", "multiboot2-common/builder"]

[dependencies]
bitflags = { workspace = true }
elf = { workspace = true }
log = { workspace = true }
multiboot2-common = { workspace = true }
ptr_meta = { workspace = true }
Expand Down
105 changes: 27 additions & 78 deletions multiboot2/src/elf_sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::mem;
use core::str::Utf8Error;
use elf::endian::NativeEndian;
use elf::section::{SectionHeader, SectionHeaderTable};
use multiboot2_common::{MaybeDynSized, Tag};
#[cfg(feature = "builder")]
use {alloc::boxed::Box, multiboot2_common::new_boxed};
Expand All @@ -22,6 +24,9 @@ pub struct ElfSectionsTag {
sections: [u8],
}

/// Iterator over the ELF section header table.
pub type ElfSectionIter<'a> = elf::parse::ParsingIterator<'a, NativeEndian, SectionHeader>;

impl ElfSectionsTag {
/// Create a new ElfSectionsTag with the given data.
#[cfg(feature = "builder")]
Expand All @@ -39,16 +44,21 @@ impl ElfSectionsTag {

/// Get an iterator over the ELF sections.
#[must_use]
pub const fn sections(&self) -> ElfSectionIter<'_> {
let string_section_offset = (self.shndx * self.entry_size) as isize;
let string_section_ptr =
unsafe { self.sections.as_ptr().offset(string_section_offset) as *const _ };
ElfSectionIter {
current_section: self.sections.as_ptr(),
remaining_sections: self.number_of_sections,
entry_size: self.entry_size,
string_section: string_section_ptr,
_phantom_data: PhantomData,
pub fn sections(&self) -> ElfSectionIter<'_> {
SectionHeaderTable::new(NativeEndian, self.class(), &self.sections).into_iter()
}

const fn class(&self) -> elf::file::Class {
use elf::section::{Elf32_Shdr, Elf64_Shdr};
const SHDR_ELF32_SIZE: usize = size_of::<Elf32_Shdr>();
const SHDR_ELF64_SIZE: usize = size_of::<Elf64_Shdr>();

match self.entry_size as usize {
SHDR_ELF32_SIZE => elf::file::Class::ELF32,
SHDR_ELF64_SIZE => elf::file::Class::ELF64,
_ => {
panic!("Unknown ELF section entry size");
}
}
}

Expand All @@ -71,6 +81,12 @@ impl ElfSectionsTag {
}
}

impl<'a> From<&'a ElfSectionsTag> for SectionHeaderTable<'a, NativeEndian> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure about the value-add of this. It feels like a misuse of From - could you please add a motivation to the commit?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that ElfSectionTag is effectively

struct ElfSectionTag {
    multiboot_data: ...,
    header_table: SectionHeaderTable,
}

So it would be nice to implement AsRef so it can be passed to functions taking impl AsRef<SectionHeaderTable>. But this causes a use-after-free because this SectionHeaderTable::new() does not return a reference.

fn from(value: &'a ElfSectionsTag) -> Self {
SectionHeaderTable::new(NativeEndian, value.class(), &value.sections)
}
}

impl MaybeDynSized for ElfSectionsTag {
type Header = TagHeader;

Expand Down Expand Up @@ -101,73 +117,6 @@ impl Debug for ElfSectionsTag {
}
}

/// An iterator over [`ElfSection`]s.
#[derive(Clone)]
pub struct ElfSectionIter<'a> {
current_section: *const u8,
remaining_sections: u32,
entry_size: u32,
string_section: *const u8,
_phantom_data: PhantomData<&'a ()>,
}

impl<'a> Iterator for ElfSectionIter<'a> {
type Item = ElfSection<'a>;

fn next(&mut self) -> Option<ElfSection<'a>> {
while self.remaining_sections != 0 {
let section = ElfSection {
inner: self.current_section,
string_section: self.string_section,
entry_size: self.entry_size,
_phantom: PhantomData,
};

self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
self.remaining_sections -= 1;

if section.section_type() != ElfSectionType::Unused {
return Some(section);
}
}
None
}

fn size_hint(&self) -> (usize, Option<usize>) {
(
self.remaining_sections as usize,
Some(self.remaining_sections as usize),
)
}
}

impl ExactSizeIterator for ElfSectionIter<'_> {
fn len(&self) -> usize {
self.remaining_sections as usize
}
}

impl Debug for ElfSectionIter<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
/// Limit how many Elf-Sections should be debug-formatted.
/// Can be thousands of sections for a Rust binary => this is useless output.
/// If the user really wants this, they should debug-format the field directly.
const ELF_SECTIONS_LIMIT: usize = 7;

let mut debug = f.debug_list();

self.clone().take(ELF_SECTIONS_LIMIT).for_each(|ref e| {
debug.entry(e);
});

if self.clone().len() > ELF_SECTIONS_LIMIT {
debug.entry(&"...");
}

debug.finish()
}
}

/// A single generic ELF Section.
// TODO Shouldn't this be called ElfSectionPtrs, ElfSectionWrapper or so?
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -302,7 +251,7 @@ impl ElfSection<'_> {
/// Get the section's flags.
#[must_use]
pub fn flags(&self) -> ElfSectionFlags {
ElfSectionFlags::from_bits_truncate(self.get().flags())
ElfSectionFlags::from_bits_retain(self.get().flags())
}

/// Check if the `ALLOCATED` flag is set in the section flags.
Expand Down