@@ -130,6 +130,132 @@ static int elf_load_tls_template_from_vfs(const char* path, elf_image_info_t* in
130130 return 0 ;
131131}
132132
133+ typedef uint64_t (* elf_ifunc_resolver_t )(void );
134+
135+ static int elf_apply_relocation_entries (const Elf64_Rela * relocs , uint64_t reloc_count )
136+ {
137+ if (!relocs || reloc_count == 0 )
138+ return 0 ;
139+
140+ for (uint64_t i = 0 ; i < reloc_count ; ++ i ) {
141+ const Elf64_Rela * reloc = & relocs [i ];
142+ uint32_t reloc_type = ELF64_R_TYPE (reloc -> r_info );
143+ uint64_t * target = (uint64_t * )reloc -> r_offset ;
144+
145+ if (!target ) {
146+ eprintf ("elf: invalid relocation target" );
147+ return -1 ;
148+ }
149+
150+ switch (reloc_type ) {
151+ case R_X86_64_RELATIVE :
152+ * target = (uint64_t )reloc -> r_addend ;
153+ break ;
154+
155+ case R_X86_64_IRELATIVE : {
156+ elf_ifunc_resolver_t resolver = (elf_ifunc_resolver_t )(uint64_t )reloc -> r_addend ;
157+ * target = resolver ? resolver () : 0 ;
158+ break ;
159+ }
160+
161+ default :
162+ break ;
163+ }
164+ }
165+
166+ return 0 ;
167+ }
168+
169+ static int elf_apply_relocations_from_memory (void * file_base_address , uint64_t file_size , const Elf64_Ehdr * header )
170+ {
171+ if (!file_base_address || !header || header -> e_shoff == 0 || header -> e_shnum == 0 )
172+ return 0 ;
173+
174+ uint64_t shdr_bytes = (uint64_t )header -> e_shnum * header -> e_shentsize ;
175+ if (header -> e_shentsize != sizeof (Elf64_Shdr ) || header -> e_shoff + shdr_bytes > file_size ) {
176+ eprintf ("elf: invalid section header table" );
177+ return -1 ;
178+ }
179+
180+ Elf64_Shdr * shdrs = (Elf64_Shdr * )((uint8_t * )file_base_address + header -> e_shoff );
181+ for (uint16_t i = 0 ; i < header -> e_shnum ; ++ i ) {
182+ Elf64_Shdr * sh = & shdrs [i ];
183+ if (sh -> sh_type != SHT_RELA || sh -> sh_size == 0 )
184+ continue ;
185+
186+ if (sh -> sh_offset + sh -> sh_size > file_size || (sh -> sh_size % sizeof (Elf64_Rela )) != 0 ) {
187+ eprintf ("elf: invalid SHT_RELA bounds" );
188+ return -1 ;
189+ }
190+
191+ if (elf_apply_relocation_entries ((Elf64_Rela * )((uint8_t * )file_base_address + sh -> sh_offset ),
192+ sh -> sh_size / sizeof (Elf64_Rela )) != 0 )
193+ return -1 ;
194+ }
195+
196+ return 0 ;
197+ }
198+
199+ static int elf_apply_relocations_from_vfs (const char * path , uint32_t file_size , const Elf64_Ehdr * header )
200+ {
201+ if (!path || !header || header -> e_shoff == 0 || header -> e_shnum == 0 )
202+ return 0 ;
203+
204+ uint64_t shdr_bytes = (uint64_t )header -> e_shnum * header -> e_shentsize ;
205+ if (header -> e_shentsize != sizeof (Elf64_Shdr ) || header -> e_shoff + shdr_bytes > file_size ) {
206+ eprintf ("elf: invalid section header table" );
207+ return -1 ;
208+ }
209+
210+ Elf64_Shdr * shdrs = kmalloc (shdr_bytes );
211+ if (!shdrs ) {
212+ eprintf ("elf: failed to allocate section headers" );
213+ return -1 ;
214+ }
215+
216+ if (elf_vfs_read_exact_path (path , (uint32_t )header -> e_shoff , shdrs , (uint32_t )shdr_bytes ) != 0 ) {
217+ eprintf ("elf: failed to read section headers" );
218+ kfree (shdrs );
219+ return -1 ;
220+ }
221+
222+ for (uint16_t i = 0 ; i < header -> e_shnum ; ++ i ) {
223+ Elf64_Shdr * sh = & shdrs [i ];
224+ if (sh -> sh_type != SHT_RELA || sh -> sh_size == 0 )
225+ continue ;
226+
227+ if (sh -> sh_offset + sh -> sh_size > file_size || (sh -> sh_size % sizeof (Elf64_Rela )) != 0 ) {
228+ eprintf ("elf: invalid SHT_RELA bounds" );
229+ kfree (shdrs );
230+ return -1 ;
231+ }
232+
233+ Elf64_Rela * relocs = kmalloc (sh -> sh_size );
234+ if (!relocs ) {
235+ eprintf ("elf: failed to allocate relocations" );
236+ kfree (shdrs );
237+ return -1 ;
238+ }
239+
240+ if (elf_vfs_read_exact_path (path , (uint32_t )sh -> sh_offset , relocs , (uint32_t )sh -> sh_size ) != 0 ) {
241+ eprintf ("elf: failed to read relocations" );
242+ kfree (relocs );
243+ kfree (shdrs );
244+ return -1 ;
245+ }
246+
247+ int rc = elf_apply_relocation_entries (relocs , sh -> sh_size / sizeof (Elf64_Rela ));
248+ kfree (relocs );
249+ if (rc != 0 ) {
250+ kfree (shdrs );
251+ return -1 ;
252+ }
253+ }
254+
255+ kfree (shdrs );
256+ return 0 ;
257+ }
258+
133259static uint64_t elf_runtime_addr_for_offset (Elf64_Phdr * headers , uint16_t phnum , uint64_t file_offset )
134260{
135261 for (uint16_t i = 0 ; i < phnum ; ++ i ) {
@@ -341,6 +467,9 @@ void* elf_load_from_memory_ex(void* file_base_address, uint64_t file_size, elf_i
341467 return NULL ;
342468 }
343469
470+ if (elf_apply_relocations_from_memory (file_base_address , file_size , & header ) != 0 )
471+ return NULL ;
472+
344473 return (void * )header .e_entry ;
345474}
346475
@@ -442,6 +571,11 @@ void* elf_load_from_vfs_ex(const char* path, elf_image_info_t* info)
442571 }
443572 }
444573
574+ if (elf_apply_relocations_from_vfs (path , size , & header ) != 0 ) {
575+ kfree (program_headers );
576+ return NULL ;
577+ }
578+
445579 kfree (program_headers );
446580 void * entry = (void * )header .e_entry ;
447581 return entry ;
0 commit comments