Skip to content

Commit 5cb4ed6

Browse files
committed
Change the BootInformation and ElfSection* types into value types.
1 parent 08c6162 commit 5cb4ed6

File tree

2 files changed

+120
-85
lines changed

2 files changed

+120
-85
lines changed

src/elf_sections.rs

Lines changed: 84 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,90 @@
1+
use header::Tag;
12

23
#[derive(Debug)]
3-
#[repr(packed)] // repr(C) would add unwanted padding before first_section
44
pub struct ElfSectionsTag {
5-
typ: u32,
6-
size: u32,
5+
inner: *const ElfSectionsTagInner,
6+
}
7+
8+
pub fn elf_sections_tag(tag: &Tag) -> ElfSectionsTag {
9+
assert_eq!(9, tag.typ);
10+
let es = ElfSectionsTag {
11+
inner: unsafe { (tag as *const _).offset(1) } as *const _,
12+
};
13+
assert!((es.get().entry_size * es.get().shndx) <= tag.size);
14+
es
15+
}
16+
17+
#[derive(Debug)]
18+
#[repr(C, packed)] // only repr(C) would add unwanted padding at the end
19+
struct ElfSectionsTagInner {
720
number_of_sections: u32,
821
entry_size: u32,
922
shndx: u32, // string table
10-
first_section: ElfSection,
1123
}
1224

1325
impl ElfSectionsTag {
14-
pub fn sections(&'static self) -> ElfSectionIter {
26+
pub fn sections(&self) -> ElfSectionIter {
27+
let string_section_offset = (self.get().shndx * self.get().entry_size) as isize;
28+
let string_section_ptr = unsafe {
29+
self.first_section().offset(string_section_offset) as *const _
30+
};
1531
ElfSectionIter {
16-
current_section: &self.first_section,
17-
remaining_sections: self.number_of_sections - 1,
18-
entry_size: self.entry_size,
32+
current_section: self.first_section(),
33+
remaining_sections: self.get().number_of_sections - 1,
34+
entry_size: self.get().entry_size,
35+
string_section: string_section_ptr,
1936
}
2037
}
2138

22-
pub fn string_table(&self) -> &'static StringTable {
23-
unsafe {
24-
let string_table_ptr =
25-
(&self.first_section as *const ElfSection).offset(self.shndx as isize);
26-
&*((*string_table_ptr).addr as *const StringTable)
27-
}
39+
fn first_section(&self) -> *const u8 {
40+
(unsafe { self.inner.offset(1) }) as *const _
2841
}
29-
}
30-
31-
pub struct StringTable(u8);
32-
33-
impl StringTable {
34-
pub fn section_name(&self, section: &ElfSection) -> &'static str {
35-
use core::{str, slice};
3642

37-
let name_ptr = unsafe {
38-
(&self.0 as *const u8).offset(section.name_index as isize)
39-
};
40-
let strlen = {
41-
let mut len = 0;
42-
while unsafe { *name_ptr.offset(len) } != 0 {
43-
len += 1;
44-
}
45-
len as usize
46-
};
47-
48-
str::from_utf8( unsafe {
49-
slice::from_raw_parts(name_ptr, strlen)
50-
}).unwrap()
43+
fn get(&self) -> &ElfSectionsTagInner {
44+
unsafe { &*self.inner }
5145
}
5246
}
5347

5448
#[derive(Clone)]
5549
pub struct ElfSectionIter {
56-
current_section: &'static ElfSection,
50+
current_section: *const u8,
5751
remaining_sections: u32,
5852
entry_size: u32,
53+
string_section: *const ElfSectionInner,
5954
}
6055

6156
impl Iterator for ElfSectionIter {
62-
type Item = &'static ElfSection;
63-
fn next(&mut self) -> Option<&'static ElfSection> {
57+
type Item = ElfSection;
58+
fn next(&mut self) -> Option<ElfSection> {
6459
if self.remaining_sections == 0 {
65-
None
66-
} else {
67-
let section = self.current_section;
68-
let next_section_addr = (self.current_section as *const _ as u64) + self.entry_size as u64;
69-
self.current_section = unsafe{ &*(next_section_addr as *const ElfSection) };
60+
return None;
61+
}
62+
63+
loop {
64+
let section = ElfSection {
65+
inner: self.current_section as *const ElfSectionInner,
66+
string_section: self.string_section,
67+
};
68+
69+
self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
7070
self.remaining_sections -= 1;
71-
if section.typ == ElfSectionType::Unused as u32 {
72-
self.next()
73-
} else {
74-
Some(section)
71+
72+
if section.section_type() != ElfSectionType::Unused {
73+
return Some(section);
7574
}
7675
}
7776
}
7877
}
7978

79+
pub struct ElfSection {
80+
inner: *const ElfSectionInner,
81+
string_section: *const ElfSectionInner,
82+
}
83+
8084
#[cfg(feature = "elf32")]
8185
#[derive(Debug)]
8286
#[repr(C)]
83-
pub struct ElfSection {
87+
struct ElfSectionInner {
8488
name_index: u32,
8589
typ: u32,
8690
flags: u32,
@@ -96,7 +100,7 @@ pub struct ElfSection {
96100
#[cfg(not(feature = "elf32"))]
97101
#[derive(Debug)]
98102
#[repr(C)]
99-
pub struct ElfSection {
103+
struct ElfSectionInner {
100104
name_index: u32,
101105
typ: u32,
102106
flags: u64,
@@ -111,7 +115,7 @@ pub struct ElfSection {
111115

112116
impl ElfSection {
113117
pub fn section_type(&self) -> ElfSectionType {
114-
match self.typ {
118+
match self.get().typ {
115119
0 => ElfSectionType::Unused,
116120
1 => ElfSectionType::ProgramSection,
117121
2 => ElfSectionType::LinkerSymbolTable,
@@ -131,28 +135,53 @@ impl ElfSection {
131135
}
132136

133137
pub fn section_type_raw(&self) -> u32 {
134-
self.typ
138+
self.get().typ
139+
}
140+
141+
pub fn name(&self) -> &str {
142+
use core::{str, slice};
143+
144+
let name_ptr = unsafe {
145+
self.string_table().offset(self.get().name_index as isize)
146+
};
147+
let strlen = {
148+
let mut len = 0;
149+
while unsafe { *name_ptr.offset(len) } != 0 {
150+
len += 1;
151+
}
152+
len as usize
153+
};
154+
155+
str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
135156
}
136157

137158
pub fn start_address(&self) -> usize {
138-
self.addr as usize
159+
self.get().addr as usize
139160
}
140161

141162
pub fn end_address(&self) -> usize {
142-
(self.addr + self.size) as usize
163+
(self.get().addr + self.get().size) as usize
143164
}
144165

145166
pub fn size(&self) -> usize {
146-
self.size as usize
167+
self.get().size as usize
147168
}
148169

149170
pub fn flags(&self) -> ElfSectionFlags {
150-
ElfSectionFlags::from_bits_truncate(self.flags)
171+
ElfSectionFlags::from_bits_truncate(self.get().flags)
151172
}
152173

153174
pub fn is_allocated(&self) -> bool {
154175
self.flags().contains(ELF_SECTION_ALLOCATED)
155176
}
177+
178+
fn get(&self) -> &ElfSectionInner {
179+
unsafe { &*self.inner }
180+
}
181+
182+
unsafe fn string_table(&self) -> *const u8 {
183+
(*self.string_section).addr as *const _
184+
}
156185
}
157186

158187
#[derive(PartialEq, Eq, Debug, Copy, Clone)]

src/lib.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::fmt;
44

55
use header::{Tag, TagIter};
66
pub use boot_loader_name::BootLoaderNameTag;
7-
pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags, StringTable};
7+
pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
88
pub use elf_sections::{ELF_SECTION_WRITABLE, ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE};
99
pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
1010
pub use module::{ModuleTag, ModuleIter};
@@ -20,38 +20,41 @@ mod memory_map;
2020
mod module;
2121
mod command_line;
2222

23-
pub unsafe fn load(address: usize) -> &'static BootInformation {
23+
pub unsafe fn load(address: usize) -> BootInformation {
2424
if !cfg!(test) {
2525
assert_eq!(0, address & 0b111);
2626
}
27-
let multiboot = &*(address as *const BootInformation);
27+
let multiboot = &*(address as *const BootInformationInner);
2828
assert_eq!(0, multiboot.total_size & 0b111);
2929
assert!(multiboot.has_valid_end_tag());
30-
multiboot
30+
BootInformation { inner: multiboot }
3131
}
3232

33-
#[repr(C)]
3433
pub struct BootInformation {
34+
inner: *const BootInformationInner,
35+
}
36+
37+
#[repr(C)]
38+
struct BootInformationInner {
3539
total_size: u32,
3640
_reserved: u32,
37-
first_tag: Tag,
3841
}
3942

4043
impl BootInformation {
4144
pub fn start_address(&self) -> usize {
42-
self as *const _ as usize
45+
self.inner as usize
4346
}
4447

4548
pub fn end_address(&self) -> usize {
4649
self.start_address() + self.total_size()
4750
}
4851

4952
pub fn total_size(&self) -> usize {
50-
self.total_size as usize
53+
self.get().total_size as usize
5154
}
5255

53-
pub fn elf_sections_tag(&self) -> Option<&'static ElfSectionsTag> {
54-
self.get_tag(9).map(|tag| unsafe { &*(tag as *const Tag as *const ElfSectionsTag) })
56+
pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
57+
self.get_tag(9).map(|tag| elf_sections::elf_sections_tag(tag))
5558
}
5659

5760
pub fn memory_map_tag(&self) -> Option<&'static MemoryMapTag> {
@@ -70,22 +73,28 @@ impl BootInformation {
7073
self.get_tag(1).map(|tag| unsafe { &*(tag as *const Tag as *const CommandLineTag) })
7174
}
7275

73-
fn has_valid_end_tag(&self) -> bool {
74-
const END_TAG: Tag = Tag{typ:0, size:8};
75-
76-
let self_ptr = self as *const _;
77-
let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
78-
let end_tag = unsafe{&*(end_tag_addr as *const Tag)};
79-
80-
end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
76+
fn get(&self) -> &BootInformationInner {
77+
unsafe { &*self.inner }
8178
}
8279

8380
fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
8481
self.tags().find(|tag| tag.typ == typ)
8582
}
8683

8784
fn tags(&self) -> TagIter {
88-
TagIter { current: &self.first_tag as *const _ }
85+
TagIter { current: unsafe { self.inner.offset(1) } as *const _ }
86+
}
87+
}
88+
89+
impl BootInformationInner {
90+
fn has_valid_end_tag(&self) -> bool {
91+
const END_TAG: Tag = Tag { typ: 0, size: 8 };
92+
93+
let self_ptr = self as *const _;
94+
let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
95+
let end_tag = unsafe { &*(end_tag_addr as *const Tag) };
96+
97+
end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
8998
}
9099
}
91100

@@ -113,11 +122,10 @@ impl fmt::Debug for BootInformation {
113122
}
114123

115124
if let Some(elf_sections_tag) = self.elf_sections_tag() {
116-
let string_table = elf_sections_tag.string_table();
117125
writeln!(f, "kernel sections:")?;
118126
for s in elf_sections_tag.sections() {
119127
writeln!(f, " name: {:15}, S: {:#08X}, E: {:#08X}, L: {:#08X}, F: {:#04X}",
120-
string_table.section_name(s), s.start_address(),
128+
s.name(), s.start_address(),
121129
s.start_address() + s.size(), s.size(), s.flags().bits())?;
122130
}
123131
}
@@ -500,53 +508,51 @@ mod tests {
500508
assert_eq!(addr + bytes.len(), bi.end_address());
501509
assert_eq!(bytes.len(), bi.total_size() as usize);
502510
let es = bi.elf_sections_tag().unwrap();
503-
let st = es.string_table();
504-
assert_eq!(string_addr, st as *const _ as u64);
505511
let mut s = es.sections();
506512
let s1 = s.next().unwrap();
507-
assert_eq!(".rodata", st.section_name(s1));
513+
assert_eq!(".rodata", s1.name());
508514
assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
509515
assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
510516
assert_eq!(0x0000_0000_0000_3000, s1.size());
511517
assert_eq!(ELF_SECTION_ALLOCATED, s1.flags());
512518
assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
513519
let s2 = s.next().unwrap();
514-
assert_eq!(".text", st.section_name(s2));
520+
assert_eq!(".text", s2.name());
515521
assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
516522
assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
517523
assert_eq!(0x0000_0000_0000_9000, s2.size());
518524
assert_eq!(ELF_SECTION_EXECUTABLE | ELF_SECTION_ALLOCATED, s2.flags());
519525
assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
520526
let s3 = s.next().unwrap();
521-
assert_eq!(".data", st.section_name(s3));
527+
assert_eq!(".data", s3.name());
522528
assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
523529
assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
524530
assert_eq!(0x0000_0000_0000_2000, s3.size());
525531
assert_eq!(ELF_SECTION_ALLOCATED | ELF_SECTION_WRITABLE, s3.flags());
526532
assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
527533
let s4 = s.next().unwrap();
528-
assert_eq!(".bss", st.section_name(s4));
534+
assert_eq!(".bss", s4.name());
529535
assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
530536
assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
531537
assert_eq!(0x0000_0000_0000_5000, s4.size());
532538
assert_eq!(ELF_SECTION_ALLOCATED | ELF_SECTION_WRITABLE, s4.flags());
533539
assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
534540
let s5 = s.next().unwrap();
535-
assert_eq!(".data.rel.ro", st.section_name(s5));
541+
assert_eq!(".data.rel.ro", s5.name());
536542
assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
537543
assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
538544
assert_eq!(0x0000_0000_0000_0000, s5.size());
539545
assert_eq!(ELF_SECTION_ALLOCATED | ELF_SECTION_WRITABLE, s5.flags());
540546
assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
541547
let s6 = s.next().unwrap();
542-
assert_eq!(".symtab", st.section_name(s6));
548+
assert_eq!(".symtab", s6.name());
543549
assert_eq!(0x0000_0000_0011_3000, s6.start_address());
544550
assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
545551
assert_eq!(0x0000_0000_0000_2BE0, s6.size());
546552
assert_eq!(ElfSectionFlags::empty(), s6.flags());
547553
assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
548554
let s7 = s.next().unwrap();
549-
assert_eq!(".strtab", st.section_name(s7));
555+
assert_eq!(".strtab", s7.name());
550556
assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
551557
assert_eq!(0x0000_0000_0011_9371, s7.end_address());
552558
assert_eq!(0x0000_0000_0000_3791, s7.size());

0 commit comments

Comments
 (0)