Skip to content

Commit d02190e

Browse files
authored
Merge pull request #25 from ahmedcharles/elf32
Detect ELF-32 at runtime, rather than compile time.
2 parents 08c6162 + fbc05fe commit d02190e

File tree

3 files changed

+189
-99
lines changed

3 files changed

+189
-99
lines changed

Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@ name = "multiboot2"
33
version = "0.3.2"
44
authors = ["Philipp Oppermann <[email protected]>", "Calvin Lee <[email protected]>"]
55
license = "MIT/Apache-2.0"
6-
description = "An experimental Multiboot 2 crate for ELF-64 kernels."
6+
description = "An experimental Multiboot 2 crate for ELF-64/32 kernels."
77

88
[dependencies.bitflags]
99
version = "0.4.0"
1010
features = ["no_std"]
11-
12-
[features]
13-
elf32 = []

src/elf_sections.rs

Lines changed: 152 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,92 @@
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};
36-
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-
};
4742

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 u8,
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+
59+
fn next(&mut self) -> Option<ElfSection> {
6460
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) };
61+
return None;
62+
}
63+
64+
loop {
65+
let section = ElfSection {
66+
inner: self.current_section,
67+
string_section: self.string_section,
68+
entry_size: self.entry_size,
69+
};
70+
71+
self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
7072
self.remaining_sections -= 1;
71-
if section.typ == ElfSectionType::Unused as u32 {
72-
self.next()
73-
} else {
74-
Some(section)
73+
74+
if section.section_type() != ElfSectionType::Unused {
75+
return Some(section);
7576
}
7677
}
7778
}
7879
}
7980

80-
#[cfg(feature = "elf32")]
81+
pub struct ElfSection {
82+
inner: *const u8,
83+
string_section: *const u8,
84+
entry_size: u32,
85+
}
86+
8187
#[derive(Debug)]
8288
#[repr(C)]
83-
pub struct ElfSection {
89+
struct ElfSectionInner32 {
8490
name_index: u32,
8591
typ: u32,
8692
flags: u32,
@@ -93,10 +99,9 @@ pub struct ElfSection {
9399
entry_size: u32,
94100
}
95101

96-
#[cfg(not(feature = "elf32"))]
97102
#[derive(Debug)]
98103
#[repr(C)]
99-
pub struct ElfSection {
104+
struct ElfSectionInner64 {
100105
name_index: u32,
101106
typ: u32,
102107
flags: u64,
@@ -111,7 +116,7 @@ pub struct ElfSection {
111116

112117
impl ElfSection {
113118
pub fn section_type(&self) -> ElfSectionType {
114-
match self.typ {
119+
match self.get().typ() {
115120
0 => ElfSectionType::Unused,
116121
1 => ElfSectionType::ProgramSection,
117122
2 => ElfSectionType::LinkerSymbolTable,
@@ -131,28 +136,117 @@ impl ElfSection {
131136
}
132137

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

137159
pub fn start_address(&self) -> usize {
138-
self.addr as usize
160+
self.get().addr()
139161
}
140162

141163
pub fn end_address(&self) -> usize {
142-
(self.addr + self.size) as usize
164+
self.get().addr() + self.get().size()
143165
}
144166

145167
pub fn size(&self) -> usize {
146-
self.size as usize
168+
self.get().size()
147169
}
148170

149171
pub fn flags(&self) -> ElfSectionFlags {
150-
ElfSectionFlags::from_bits_truncate(self.flags)
172+
ElfSectionFlags::from_bits_truncate(self.get().flags())
151173
}
152174

153175
pub fn is_allocated(&self) -> bool {
154176
self.flags().contains(ELF_SECTION_ALLOCATED)
155177
}
178+
179+
fn get(&self) -> &ElfSectionInner {
180+
match self.entry_size {
181+
40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
182+
64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
183+
_ => panic!(),
184+
}
185+
}
186+
187+
unsafe fn string_table(&self) -> *const u8 {
188+
match self.entry_size {
189+
40 => (*(self.string_section as *const ElfSectionInner32)).addr as *const _,
190+
64 => (*(self.string_section as *const ElfSectionInner64)).addr as *const _,
191+
_ => panic!(),
192+
}
193+
}
194+
}
195+
196+
trait ElfSectionInner {
197+
fn name_index(&self) -> u32;
198+
199+
fn typ(&self) -> u32;
200+
201+
fn flags(&self) -> u32;
202+
203+
fn addr(&self) -> usize;
204+
205+
fn size(&self) -> usize;
206+
}
207+
208+
impl ElfSectionInner for ElfSectionInner32 {
209+
fn name_index(&self) -> u32 {
210+
self.name_index
211+
}
212+
213+
fn typ(&self) -> u32 {
214+
self.typ
215+
}
216+
217+
fn flags(&self) -> u32 {
218+
self.flags
219+
}
220+
221+
fn addr(&self) -> usize {
222+
self.addr as usize
223+
}
224+
225+
fn size(&self) -> usize {
226+
self.size as usize
227+
}
228+
}
229+
230+
impl ElfSectionInner for ElfSectionInner64 {
231+
fn name_index(&self) -> u32 {
232+
self.name_index
233+
}
234+
235+
fn typ(&self) -> u32 {
236+
self.typ
237+
}
238+
239+
fn flags(&self) -> u32 {
240+
self.flags as u32
241+
}
242+
243+
fn addr(&self) -> usize {
244+
self.addr as usize
245+
}
246+
247+
fn size(&self) -> usize {
248+
self.size as usize
249+
}
156250
}
157251

158252
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
@@ -174,14 +268,8 @@ pub enum ElfSectionType {
174268
ProcessorSpecific = 0x7000_0000,
175269
}
176270

177-
#[cfg(feature = "elf32")]
178-
type ElfSectionFlagsType = u32;
179-
180-
#[cfg(not(feature = "elf32"))]
181-
type ElfSectionFlagsType = u64;
182-
183271
bitflags! {
184-
flags ElfSectionFlags: ElfSectionFlagsType {
272+
flags ElfSectionFlags: u32 {
185273
const ELF_SECTION_WRITABLE = 0x1,
186274
const ELF_SECTION_ALLOCATED = 0x2,
187275
const ELF_SECTION_EXECUTABLE = 0x4,

0 commit comments

Comments
 (0)