|
@@ -1,36 +1,42 @@
|
|
|
-use crate::tag_type::Tag;
|
|
|
-use crate::TagType;
|
|
|
+use crate::{Tag, TagTrait, TagType, TagTypeId};
|
|
|
+
|
|
|
use core::fmt::{Debug, Formatter};
|
|
|
+use core::mem::size_of;
|
|
|
use core::str::Utf8Error;
|
|
|
|
|
|
+#[cfg(feature = "builder")]
|
|
|
+use {crate::builder::boxed_dst_tag, alloc::boxed::Box};
|
|
|
+
|
|
|
+const METADATA_SIZE: usize = size_of::<TagTypeId>() + 4 * size_of::<u32>();
|
|
|
+
|
|
|
/// This tag contains section header table from an ELF kernel.
|
|
|
///
|
|
|
/// The sections iterator is provided via the `sections` method.
|
|
|
-#[derive(Debug)]
|
|
|
+#[derive(Debug, ptr_meta::Pointee)]
|
|
|
+#[repr(C, packed)]
|
|
|
pub struct ElfSectionsTag {
|
|
|
- inner: *const ElfSectionsTagInner,
|
|
|
- offset: usize,
|
|
|
-}
|
|
|
-
|
|
|
-pub unsafe fn elf_sections_tag(tag: &Tag, offset: usize) -> ElfSectionsTag {
|
|
|
- assert_eq!(TagType::ElfSections.val(), tag.typ);
|
|
|
- let es = ElfSectionsTag {
|
|
|
- inner: (tag as *const Tag).offset(1) as *const ElfSectionsTagInner,
|
|
|
- offset,
|
|
|
- };
|
|
|
- assert!((es.get().entry_size * es.get().shndx) <= tag.size);
|
|
|
- es
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Clone, Copy, Debug)]
|
|
|
-#[repr(C, packed)] // only repr(C) would add unwanted padding at the end
|
|
|
-struct ElfSectionsTagInner {
|
|
|
+ typ: TagTypeId,
|
|
|
+ pub(crate) size: u32,
|
|
|
number_of_sections: u32,
|
|
|
- entry_size: u32,
|
|
|
- shndx: u32, // string table
|
|
|
+ pub(crate) entry_size: u32,
|
|
|
+ pub(crate) shndx: u32, // string table
|
|
|
+ sections: [u8],
|
|
|
}
|
|
|
|
|
|
impl ElfSectionsTag {
|
|
|
+ /// Create a new ElfSectionsTag with the given data.
|
|
|
+ #[cfg(feature = "builder")]
|
|
|
+ pub fn new(number_of_sections: u32, entry_size: u32, shndx: u32, sections: &[u8]) -> Box<Self> {
|
|
|
+ let mut bytes = [
|
|
|
+ number_of_sections.to_le_bytes(),
|
|
|
+ entry_size.to_le_bytes(),
|
|
|
+ shndx.to_le_bytes(),
|
|
|
+ ]
|
|
|
+ .concat();
|
|
|
+ bytes.extend_from_slice(sections);
|
|
|
+ boxed_dst_tag(TagType::ElfSections, &bytes)
|
|
|
+ }
|
|
|
+
|
|
|
/// Get an iterator of loaded ELF sections.
|
|
|
///
|
|
|
/// # Examples
|
|
@@ -39,31 +45,34 @@ impl ElfSectionsTag {
|
|
|
/// # let boot_info = unsafe { multiboot2::load(0xdeadbeef).unwrap() };
|
|
|
/// if let Some(elf_tag) = boot_info.elf_sections_tag() {
|
|
|
/// let mut total = 0;
|
|
|
- /// for section in elf_tag.sections() {
|
|
|
+ /// for section in elf_tag.sections(0) {
|
|
|
/// println!("Section: {:?}", section);
|
|
|
/// total += 1;
|
|
|
/// }
|
|
|
/// }
|
|
|
/// ```
|
|
|
- pub fn sections(&self) -> ElfSectionIter {
|
|
|
- let string_section_offset = (self.get().shndx * self.get().entry_size) as isize;
|
|
|
+ pub fn sections(&self, offset: usize) -> ElfSectionIter {
|
|
|
+ let string_section_offset = (self.shndx * self.entry_size) as isize;
|
|
|
let string_section_ptr =
|
|
|
unsafe { self.first_section().offset(string_section_offset) as *const _ };
|
|
|
ElfSectionIter {
|
|
|
current_section: self.first_section(),
|
|
|
- remaining_sections: self.get().number_of_sections,
|
|
|
- entry_size: self.get().entry_size,
|
|
|
+ remaining_sections: self.number_of_sections,
|
|
|
+ entry_size: self.entry_size,
|
|
|
string_section: string_section_ptr,
|
|
|
- offset: self.offset,
|
|
|
+ offset,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn first_section(&self) -> *const u8 {
|
|
|
- (unsafe { self.inner.offset(1) }) as *const _
|
|
|
+ &(self.sections[0]) as *const _
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- fn get(&self) -> &ElfSectionsTagInner {
|
|
|
- unsafe { &*self.inner }
|
|
|
+impl TagTrait for ElfSectionsTag {
|
|
|
+ fn dst_size(base_tag: &Tag) -> usize {
|
|
|
+ assert!(base_tag.size as usize >= METADATA_SIZE);
|
|
|
+ base_tag.size as usize - METADATA_SIZE
|
|
|
}
|
|
|
}
|
|
|
|