Skip to content

Commit 142b49d

Browse files
committed
Update
1 parent 9e42628 commit 142b49d

3 files changed

Lines changed: 111 additions & 9 deletions

File tree

kernel/src/loader.rs

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
use core::mem::size_of;
12
use core::slice;
23

4+
use ftl_elf::DT_NULL;
5+
use ftl_elf::DT_RELA;
6+
use ftl_elf::DT_RELASZ;
7+
use ftl_elf::Dyn;
38
use ftl_elf::Elf;
49
use ftl_elf::PhdrType;
10+
use ftl_elf::R_X86_64_RELATIVE;
11+
use ftl_elf::Rela;
512
use ftl_server::start::StartInfo;
613
use ftl_utils::alignment::align_up;
714

@@ -22,8 +29,7 @@ fn load_elf(elf_file: &[u8]) {
2229
let elf = match Elf::parse(elf_file, ftl_elf::ET_DYN) {
2330
Ok(elf) => elf,
2431
Err(e) => {
25-
error!("failed to parse ELF file: {:?}", e);
26-
return;
32+
panic!("failed to parse ELF file: {:?}", e);
2733
}
2834
};
2935

@@ -39,8 +45,7 @@ fn load_elf(elf_file: &[u8]) {
3945
let image_paddr = match PAGE_ALLOCATOR.alloc(image_size, PageType::Zeroed) {
4046
Some(paddr) => paddr,
4147
None => {
42-
error!("out of memory: {} bytes", image_size);
43-
return;
48+
panic!("out of memory: {} bytes", image_size);
4449
}
4550
};
4651

@@ -66,7 +71,66 @@ fn load_elf(elf_file: &[u8]) {
6671
let zeroed_len = phdr.p_memsz as usize - copy_len;
6772
if zeroed_len > 0 {
6873
let zeroed_range = (zeroed_off)..(zeroed_off + zeroed_len);
69-
dst[zeroed_range].fill(0);
74+
image[zeroed_range].fill(0);
75+
}
76+
}
77+
78+
// Find the relocation table.
79+
let mut rela_addr = 0;
80+
let mut rela_size = 0;
81+
for phdr in elf.phdrs {
82+
if phdr.p_type != PhdrType::Dynamic as u32 {
83+
continue;
84+
}
85+
86+
if phdr.p_memsz as usize % size_of::<Dyn>() != 0 {
87+
panic!("invalid dynamic segment size");
88+
}
89+
90+
let dynamic = unsafe {
91+
slice::from_raw_parts(
92+
image.as_ptr().add(phdr.p_vaddr as usize) as *const Dyn,
93+
phdr.p_memsz as usize / size_of::<Dyn>(),
94+
)
95+
};
96+
97+
for entry in dynamic {
98+
match entry.d_tag {
99+
DT_NULL => break,
100+
DT_RELA => rela_addr = entry.d_val as usize,
101+
DT_RELASZ => rela_size = entry.d_val as usize,
102+
_ => {}
103+
}
104+
}
105+
}
106+
107+
// Apply relocations.
108+
if rela_addr != 0 && rela_size > 0 {
109+
if rela_size % size_of::<Rela>() != 0 {
110+
panic!("invalid relocation table size: {} bytes", rela_size);
111+
}
112+
113+
let relocations = unsafe {
114+
slice::from_raw_parts(
115+
image.as_ptr().add(rela_addr) as *const Rela,
116+
rela_size / size_of::<Rela>(),
117+
)
118+
};
119+
120+
for rela in relocations {
121+
let target_off = rela.r_offset as usize;
122+
if rela.r_sym() != 0 || rela.r_type() != R_X86_64_RELATIVE {
123+
panic!("unexpected relocation type: {}", rela.r_type());
124+
}
125+
126+
let target_end = match target_off.checked_add(size_of::<u64>()) {
127+
Some(end) if end <= image.len() => end,
128+
_ => panic!("invalid relocation target offset: {}", target_off),
129+
};
130+
131+
let base = image.as_ptr() as u64;
132+
let value = base.wrapping_add(rela.r_addend as u64);
133+
image[target_off..target_end].copy_from_slice(&value.to_le_bytes());
70134
}
71135
}
72136

libs/rust/ftl_elf/src/lib.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,44 @@ pub const PF_W: u32 = 0x2;
5858
/// Readable segment.
5959
pub const PF_R: u32 = 0x4;
6060

61+
#[derive(Debug, Clone, Copy)]
62+
#[repr(C)]
63+
pub struct Dyn64 {
64+
pub d_tag: i64,
65+
pub d_val: u64,
66+
}
67+
68+
#[cfg(target_pointer_width = "64")]
69+
pub type Dyn = Dyn64;
70+
71+
pub const DT_NULL: i64 = 0;
72+
pub const DT_RELA: i64 = 7;
73+
pub const DT_RELASZ: i64 = 8;
74+
75+
#[derive(Debug, Clone, Copy)]
76+
#[repr(C)]
77+
pub struct Rela64 {
78+
pub r_offset: u64,
79+
pub r_info: u64,
80+
pub r_addend: i64,
81+
}
82+
83+
#[cfg(target_pointer_width = "64")]
84+
pub type Rela = Rela64;
85+
86+
impl Rela {
87+
pub fn r_sym(&self) -> u32 {
88+
(self.r_info >> 32) as u32
89+
}
90+
91+
pub fn r_type(&self) -> u32 {
92+
self.r_info as u32
93+
}
94+
}
95+
96+
#[cfg(target_arch = "x86_64")]
97+
pub const R_X86_64_RELATIVE: u32 = 8;
98+
6199
#[derive(Debug)]
62100
#[repr(C)]
63101
pub struct Phdr64 {

libs/rust/ftl_server/src/arch/x64/server.ld

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ PHDRS {
99
rodata PT_LOAD;
1010
data PT_LOAD;
1111
bss PT_LOAD;
12+
dynamic PT_DYNAMIC;
1213
}
1314

1415
SECTIONS {
@@ -28,8 +29,7 @@ SECTIONS {
2829
*(.bss .bss.*)
2930
} : bss
3031

31-
ASSERT(SIZEOF(.rel.dyn) == 0, "server image must not contain REL relocations")
32-
ASSERT(SIZEOF(.rela.dyn) == 0, "server image must not contain RELA relocations")
33-
ASSERT(SIZEOF(.rel.plt) == 0, "server image must not contain REL relocations")
34-
ASSERT(SIZEOF(.rela.plt) == 0, "server image must not contain RELA relocations")
32+
.dynamic : {
33+
*(.dynamic)
34+
} : bss : dynamic
3535
}

0 commit comments

Comments
 (0)