1+ use core:: mem:: size_of;
12use 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 ;
38use ftl_elf:: Elf ;
49use ftl_elf:: PhdrType ;
10+ use ftl_elf:: R_X86_64_RELATIVE ;
11+ use ftl_elf:: Rela ;
512use ftl_server:: start:: StartInfo ;
613use 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
0 commit comments