1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ELF Loader
3 File: elf_loader.c
4
5 Copyright 2006-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2010-01-08#$
14 $Rev: 11276 $
15 $Author: shirait $
16 *---------------------------------------------------------------------------*/
17
18 #include "types.h"
19 #include "elf.h"
20 #include "elf_loader.h"
21 #include "arch.h"
22 #include "loader_subset.h"
23 #include <string.h>
24 #include <stdlib.h>
25
26
27 //OSHeapHandle EL_Heap;
28 ELAdrEntry* ELAdrEntStart = NULL;
29 ELUnresolvedEntry* ELUnrEntStart = NULL;
30
31 extern u16 dbg_print_flag;
32 extern u32 unresolved_table_block_flag;
33 extern u32 ELi_ALIGN( u32 addr, u32 align_size);
34
35 extern u16 ELi_LoadObject2( ELHandle* ElfHandle, void* obj_offset, void* buf);
36
37
38 #define MAKELST_DS_API " elAddAdrEntry" //API function name to add to the address table on DS
39
40 extern char c_source_line_str[256];
41 extern FILE* NewElfFilep;
42
43
44 /*------------------------------------------------------
45 Local Function Declarations
46 -----------------------------------------------------*/
47 // Relocate ELF object or that archive in a buffer
48 u16 ELi_LoadLibrary( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf, u16 type);
49 // Core function that relocates ELF object to buffer
50 u16 ELi_LoadObject( ELHandle* ElfHandle, void* obj_offset, void* buf);
51 // Stub functions that read data from the ELF object
52 void ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size);
53 void ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size);
54
55
56
57 /*Express hex value with decimal string*/
ELi_SetDecSize(char * dec,u32 hex)58 void ELi_SetDecSize( char* dec, u32 hex)
59 {
60 u16 i;
61 u32 tmp = 1000000000;
62 u16 ptr = 0;
63
64 memset( dec, 0x20, 10);
65 for( i=0; i<10; i++) {
66 if( ((hex / tmp) != 0) || (ptr != 0)) {
67 dec[ptr++] = 0x30 + (hex/tmp);
68 hex -= (hex/tmp) * tmp;
69 }
70 tmp /= 10;
71 }
72 }
73
74
75
76 /*---------------------------------------------------------
77 Find size of the ELF object
78
79 buf: Address of ELF image
80 --------------------------------------------------------*/
EL_GetElfSize(const void * buf)81 u32 EL_GetElfSize( const void* buf)
82 {
83 Elf32_Ehdr Ehdr;
84 u32 size;
85
86 if( ELF_LoadELFHeader( buf, &Ehdr) == NULL) {
87 return 0;
88 }
89 size = (u32)(Ehdr.e_shoff + (Ehdr.e_shentsize * Ehdr.e_shnum));
90 return size;
91 }
92
93
94 /*------------------------------------------------------
95 Initializes the dynamic link system.
96 -----------------------------------------------------*/
EL_Init(void)97 void EL_Init( void)
98 {
99 // void* heap_start;
100 printf( "\n");
101 /*--- Memory allocation related settings ---*/
102 /* OS_InitArena();
103 heap_start = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
104 OS_SetMainArenaLo( heap_start );
105 EL_Heap = OS_CreateHeap( OS_ARENA_MAIN, heap_start, (void*)((u32)(OS_GetMainArenaHi())+1));
106 OS_SetCurrentHeap( OS_ARENA_MAIN, EL_Heap);*/
107 /*--------------------------------------*/
108 }
109
110 /*------------------------------------------------------
111 Initialize the ELHandle structure
112 -----------------------------------------------------*/
EL_InitHandle(ELHandle * ElfHandle)113 BOOL EL_InitHandle( ELHandle* ElfHandle)
114 {
115 if( ElfHandle == NULL) { /*NULL check*/
116 return FALSE;
117 }
118
119 /*Set default values*/
120 ElfHandle->ShdrEx = NULL;
121 ElfHandle->SymEx = NULL;
122 ElfHandle->SymExTbl = NULL;
123 ElfHandle->SymExTarget = 0xFFFFFFFF;
124
125 ElfHandle->process = EL_INITIALIZED; /*Set the flag*/
126
127 return TRUE;
128 }
129
130 /*------------------------------------------------------
131 Relocate ELF object or that archive in a buffer
132
133 ElfHandle: Header structure
134 ObjFile: Object file or archive file structure
135 buf: Buffer for loading
136 type: 0: Create elf with debug information removed, 1: Create elf for debugging
137 -----------------------------------------------------*/
EL_LoadLibraryfromFile(ELHandle * ElfHandle,FILE * ObjFile,void * buf,u16 type)138 u16 EL_LoadLibraryfromFile( ELHandle* ElfHandle, FILE* ObjFile, void* buf, u16 type)
139 {
140 u16 result;
141 u32 len;
142
143 /*Set read function*/
144 ElfHandle->ELi_ReadStub = ELi_ReadFile;
145 ElfHandle->FileStruct = ObjFile;
146
147 fseek( ObjFile, 0, SEEK_END);
148 len = ftell( ObjFile);
149 fseek( ObjFile, 0, SEEK_SET);
150 result = ELi_LoadLibrary( ElfHandle, NULL, len, buf, type);
151
152 return result;
153 }
154
155 /*------------------------------------------------------
156 Relocate ELF object or the archive in a buffer
157
158 ElfHandle: Header structure
159 obj_image: RAM image address for OBJ file or archive file
160 buf: Buffer for loading
161 -----------------------------------------------------*/
EL_LoadLibraryfromMem(ELHandle * ElfHandle,void * obj_image,u32 obj_len,void * buf)162 u16 EL_LoadLibraryfromMem( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf)
163 {
164 u16 result;
165
166 /*Set read function*/
167 ElfHandle->ELi_ReadStub = ELi_ReadMem;
168 ElfHandle->FileStruct = NULL;
169
170 result = ELi_LoadLibrary( ElfHandle, obj_image, obj_len, buf, 0);
171
172 return result;
173 }
174
175 /*------------------------------------------------------
176 Relocate ELF object or the archive in a buffer
177
178 ElfHandle: Header structure
179 obj_image: RAM image address for OBJ file or archive file
180 buf: Buffer for loading
181 -----------------------------------------------------*/
ELi_LoadLibrary(ELHandle * ElfHandle,void * obj_image,u32 obj_len,void * buf,u16 type)182 u16 ELi_LoadLibrary( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf, u16 type)
183 {
184 u16 result, all_result;
185 u32 image_pointer;
186 u32 new_image_pointer;
187 u32 arch_size;
188 u32 elf_num = 0; /*Number of ELF objects*/
189 u32 obj_size;
190 u32 newarch_size = 0;
191 ArchHdr ArHdr;
192 char OBJMAG[8];
193 char ELFMAG[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3};
194
195
196 all_result = EL_RELOCATED;
197 ElfHandle->ar_head = obj_image;
198 image_pointer = 0;
199
200
201 ElfHandle->ELi_ReadStub( OBJMAG, ElfHandle->FileStruct, (u32)obj_image, 0, 8); /*Get the OBJ string*/
202 /*--------------- For archive files ---------------*/
203 if( strncmp( OBJMAG, ARMAG, 8) == 0) {
204 arch_size = sizeof( ArchHdr);
205 image_pointer += 8; /*To first entry*/
206
207
208 new_image_pointer = (u32)buf;
209 memcpy( buf, OBJMAG, 8); //Copy to stripped ELF
210 new_image_pointer += 8;
211 newarch_size += 8;
212
213
214 ElfHandle->buf_current = (void*)new_image_pointer;
215 while( image_pointer < obj_len) {
216 ElfHandle->ELi_ReadStub( &ArHdr, ElfHandle->FileStruct, (u32)(obj_image), image_pointer, arch_size);
217 ElfHandle->ELi_ReadStub( OBJMAG, ElfHandle->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4); /*Get the OBJ string*/
218 if( strncmp( OBJMAG, ELFMAG, 4) == 0) {
219 elf_num++;
220
221 memcpy( (void*)new_image_pointer, (const void*)&ArHdr, arch_size); //Copy ar header to stripped ELF
222
223 if( type == 0) {
224 result = ELi_LoadObject( ElfHandle, (void*)(image_pointer+arch_size),
225 (void*)(new_image_pointer + arch_size));
226 // (ElfHandle->buf_current + arch_size));
227 }else{
228 result = ELi_LoadObject2( ElfHandle, (void*)(image_pointer+arch_size),
229 (void*)(new_image_pointer + arch_size));
230 }
231
232 ELi_SetDecSize( (char*)(((ArchHdr*)new_image_pointer)->ar_size), ElfHandle->newelf_size); //Update arch header size
233 new_image_pointer += (ElfHandle->newelf_size + arch_size);
234 newarch_size += (ElfHandle->newelf_size + arch_size);
235
236 if( result < all_result) { /*Apply to all_result only when there are bad results*/
237 all_result = result;
238 }
239 /*Set default values*/
240 ElfHandle->ShdrEx = NULL;
241 ElfHandle->SymEx = NULL;
242 ElfHandle->process = EL_INITIALIZED; /*Set the flag*/
243 }else{
244 memcpy( (void*)new_image_pointer, (const void*)&ArHdr, arch_size); //Copy ar header to stripped ELF
245
246 /*Copy next (entry) of ar header to stripped ELF*/
247 ElfHandle->ELi_ReadStub( (void*)(new_image_pointer+arch_size), ElfHandle->FileStruct,
248 (u32)(obj_image),
249 (image_pointer+arch_size), AR_GetEntrySize( &ArHdr));
250
251 new_image_pointer += (AR_GetEntrySize( &ArHdr) + arch_size);
252 newarch_size += (AR_GetEntrySize( &ArHdr) + arch_size);
253 }
254 /*To next entry*/
255 obj_size = AR_GetEntrySize( &ArHdr);
256 if( obj_size %2) //Padded by '\n' when the object size is an odd number.
257 {
258 obj_size++;
259 }
260 image_pointer += arch_size + obj_size;
261 }
262 ElfHandle->newelf_size = newarch_size;
263 }else{/*--------------- For ELF files ---------------*/
264 if( strncmp( OBJMAG, ELFMAG, 4) == 0) {
265 elf_num++;
266 if( type == 0) {
267 all_result = ELi_LoadObject( ElfHandle, 0, buf);
268 }else{
269 all_result = ELi_LoadObject2( ElfHandle, 0, buf);
270 }
271 }
272 }
273 /*-------------------------------------------------------*/
274
275 if( elf_num) {
276 return all_result;
277 }else{
278 return EL_FAILED;
279 }
280 }
281
282 /*------------------------------------------------------
283 Relocate ELF object to buffer
284
285 ElfHandle: Header structure
286 obj_offset: Offset from RAM image address of object file
287 buf: Buffer for loading
288 -----------------------------------------------------*/
ELi_LoadObject(ELHandle * ElfHandle,void * obj_offset,void * buf)289 u16 ELi_LoadObject( ELHandle* ElfHandle, void* obj_offset, void* buf)
290 {
291 u16 i, j;
292 // u32 num_of_entry;
293 ELShdrEx* FwdShdrEx;
294 ELShdrEx* CurrentShdrEx;
295 ELShdrEx DmyShdrEx;
296 // char sym_str[128]; //For debugging print
297 // u32 offset; //For debugging print
298 u32 newelf_shoff = 0; //Write pointer to stripped ELF image
299 u32 buf_shdr;
300 u32 section_num = 0;
301 // u32 newelf_size;
302 u32 tmp_buf;
303 u32 *shdr_table; //Table for new/old number correspondence for section headers
304 // u32 *sym_table; //Table corresponding to the new/old numbers of symbol entries
305 u32 last_local_symbol_index = 0xFFFFFFFF;
306
307
308 /* Check initialization of ELHandle */
309 if( ElfHandle->process != EL_INITIALIZED) {
310 return EL_FAILED;
311 }
312 /* Buffer NULL check */
313 if( buf == NULL) {
314 return EL_FAILED;
315 }
316 /* Get ELF header */
317 ElfHandle->ELi_ReadStub( &(ElfHandle->CurrentEhdr), ElfHandle->FileStruct,
318 (u32)(ElfHandle->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr));
319
320 /* Section handle build */
321 ElfHandle->elf_offset = obj_offset;
322 ElfHandle->buf_current = (void*)((u32)buf + sizeof( Elf32_Ehdr));
323 ElfHandle->shentsize = ElfHandle->CurrentEhdr.e_shentsize;
324
325 /*Section header table build*/
326 shdr_table = (u32*)malloc( 4 * ElfHandle->CurrentEhdr.e_shnum);
327
328 /*---------- Create ELShdrEx and shdr_table Lists ----------*/
329 CurrentShdrEx = &DmyShdrEx;
330 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
331 CurrentShdrEx->next = (void*)(malloc( sizeof(ELShdrEx)));
332 CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
333 memset( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Clear zero
334
335 /*Set flag to distinguish whether this is debugging information*/
336 if( ELi_ShdrIsDebug( ElfHandle, i) == TRUE) { /*When it is debugging information*/
337 CurrentShdrEx->debug_flag = 1;
338 shdr_table[i] = 0xFFFFFFFF;
339 }else{ /*When not debugging information*/
340 /*Copy section header*/
341 ELi_GetShdr( ElfHandle, i, &(CurrentShdrEx->Shdr));
342 CurrentShdrEx->debug_flag = 0;
343 shdr_table[i] = section_num; /*Create section new/old table*/
344 // printf( "shdr_table[0x%x] = 0x%x\n", i, section_num);
345 section_num++;
346 /*Get section string*/
347 #if 0 // Do not dynamically allocate section string buffer
348 CurrentShdrEx->str = (char*)malloc( 128); //Get 128 character buffer
349 ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
350 CurrentShdrEx->Shdr.sh_name,
351 CurrentShdrEx->str, 128);
352 #else
353 {
354 u32 length;
355
356 length = ELi_GetStrLen( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx, CurrentShdrEx->Shdr.sh_name) + 1;
357
358 CurrentShdrEx->str = (char*)malloc(length);
359 if(CurrentShdrEx->str == 0)
360 {
361 return EL_FAILED;
362 }
363 ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
364 CurrentShdrEx->Shdr.sh_name,
365 CurrentShdrEx->str, length);
366 }
367 #endif
368 }
369 }
370 #if 0 /*Comment out because the addition of a special section was performed on the added-elf side*/
371 section_num++; //Add special section
372 ElfHandle->CurrentEhdr.e_shnum++; //Add special section
373 CurrentShdrEx->next = (void*)(malloc( sizeof(ELShdrEx)));
374 CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
375 memset( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Clear zero
376 // CurrentShdrEx->Shdr.sh_name
377 CurrentShdrEx->Shdr.sh_type = SPECIAL_SECTION_TYPE;
378 CurrentShdrEx->Shdr.sh_flags = 0;
379 CurrentShdrEx->Shdr.sh_addr = 0;
380 CurrentShdrEx->Shdr.sh_offset = 0;
381 CurrentShdrEx->Shdr.sh_size = (section_num - 1)*4; //(ElfHandle->CurrentEhdr.e_shnum)*4; (When old section number is in the index)
382 CurrentShdrEx->Shdr.sh_link = 0;
383 CurrentShdrEx->Shdr.sh_info = 0;
384 CurrentShdrEx->Shdr.sh_addralign = 4;
385 CurrentShdrEx->Shdr.sh_entsize = 4;
386 #if 0 // Do not dynamically allocate section string buffer
387 CurrentShdrEx->str = (char*)malloc( 128);
388 #else
389 CurrentShdrEx->str = (char*)malloc( strlen(SPECIAL_SECTION_NAME) + 1 );
390 if(CurrentShdrEx->str == 0)
391 {
392 return EL_FAILED;
393 }
394 #endif
395 strcpy( CurrentShdrEx->str, SPECIAL_SECTION_NAME);
396 #endif
397 CurrentShdrEx->next = NULL;
398 ElfHandle->ShdrEx = DmyShdrEx.next;
399 /*--------------------------------------------------------*/
400
401
402 /*---------- Check and copy all sections ----------*/
403 // printf( "\nLoad to RAM:\n");
404 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
405 //
406 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
407
408 if( CurrentShdrEx->debug_flag == 1) { //When it is debugging information
409 // printf( "skip debug-section %02x\n", i);
410 }else{ //When not debugging information
411 // .text section
412 if( /*(CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))&&*/
413 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
414 //Copy to memory
415 CurrentShdrEx->loaded_adr = (u32)
416 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
417 }
418 // .data, .data1 section (Initialized data)
419 /* else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
420 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
421 //Copy to memory
422 CurrentShdrEx->loaded_adr = (u32)
423 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
424 }*/
425 // bss section
426 else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
427 (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) {
428 //Do not copy
429 CurrentShdrEx->loaded_adr = ELi_ALIGN( (u32)(ElfHandle->buf_current), 4);
430 /* CurrentShdrEx->loaded_adr = (u32)
431 ELi_AllocSectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));*/
432 }
433 // .rodata, .rodata1 section
434 /* else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&&
435 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
436 //Copy to memory
437 CurrentShdrEx->loaded_adr = (u32)
438 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
439 }*/
440 #if 0 /*Comment out because the addition of a special section was performed on the added-elf side*/
441 else if( CurrentShdrEx->Shdr.sh_type == SPECIAL_SECTION_TYPE) {
442 //Series of processes equivalent to ELi_CopySectionToBuffer
443 u32 load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
444 u32 sh_size = CurrentShdrEx->Shdr.sh_size;
445 u32* reverse_shdr_table = (u32*)malloc( 4 * (section_num-1)); //-1 is to exclude a special section
446 /*Index converts to new section number table*/
447 for( j=0; j<(ElfHandle->CurrentEhdr.e_shnum - 1); j++) {
448 if( shdr_table[j] != 0xFFFFFFFF) {
449 reverse_shdr_table[shdr_table[j]] = j;
450 }
451 }
452 memcpy( (u32*)load_start, reverse_shdr_table, sh_size); //Copy new/old section correspondence table
453 free( reverse_shdr_table);
454 CurrentShdrEx->loaded_adr = load_start;
455 ElfHandle->buf_current = (void*)(load_start + sh_size);
456 }
457 #endif
458 //Copy .arm_vfe_header, .ARM.exidx, .ARM.attributes and the like
459 else if( CurrentShdrEx->Shdr.sh_type >= SHT_LOPROC) {
460 //Copy to memory
461 CurrentShdrEx->loaded_adr = (u32)
462 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
463 }
464 //Symbol table section
465 else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) {
466 ELi_BuildSymList( ElfHandle, i, &(CurrentShdrEx->sym_table)); //Create symbol list
467 {
468 ELSymEx* CurrentSymEx;
469 ELShdrEx* StrShEx; //Character string section
470 #if 0 // Do not dynamically allocate section string buffer
471 char symstr[128];
472 #else
473 char *symstr;
474 #endif
475 u32 symbol_num = 0;
476
477 /*--- Correct symbol entry data ---*/
478 CurrentSymEx = ElfHandle->SymEx;
479 while( CurrentSymEx != NULL) { //If you track SymEx, debug symbols are not included
480 /*Get character string section*/
481 StrShEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx,
482 CurrentShdrEx->Shdr.sh_link);
483 /*--- Build character string section content ---*/
484 #if 0 // Do not dynamically allocate section string buffer
485 ELi_GetStrAdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, //Get symbol string
486 CurrentSymEx->Sym.st_name,
487 symstr, 128);
488 #else
489 {
490 u32 length;
491
492 length = ELi_GetStrLen( ElfHandle, CurrentShdrEx->Shdr.sh_link, CurrentSymEx->Sym.st_name ) + 1;
493
494 symstr = (char*)malloc(length);
495 if(symstr == 0)
496 {
497 return EL_FAILED;
498 }
499 ELi_GetStrAdr( ElfHandle, CurrentShdrEx->Shdr.sh_link,
500 CurrentSymEx->Sym.st_name,
501 symstr, length);
502 }
503 #endif
504 StrShEx->str_table = realloc( StrShEx->str_table, //Add symbol string
505 (StrShEx->str_table_size) +
506 strlen( symstr) + 1);
507 strcpy( (u8*)((u32)StrShEx->str_table + StrShEx->str_table_size),
508 symstr);
509
510 CurrentSymEx->Sym.st_name = StrShEx->str_table_size; //Correct symbol entry data
511
512 StrShEx->str_table_size += ( strlen( symstr) + 1);
513 #if 0 // Do not dynamically allocate section string buffer
514 #else
515 free(symstr);
516 #endif
517 /*---------------------------------*/
518 //Find final STB_LOCAL symbol (becomes the value of sh_info for the SYMTAB section header)
519 if( ((ELF32_ST_BIND( (CurrentSymEx->Sym.st_info))) != STB_LOCAL)&&
520 (last_local_symbol_index == 0xFFFFFFFF)) {
521 last_local_symbol_index = symbol_num;
522 }
523 /*---------------------------------*/
524
525 symbol_num++;
526
527 /*---------------------------------*/
528 if( (CurrentSymEx->Sym.st_shndx != SHN_UNDEF) &&
529 (CurrentSymEx->Sym.st_shndx < SHN_LORESERVE)) {
530 CurrentSymEx->Sym.st_shndx = shdr_table[CurrentSymEx->Sym.st_shndx]; //Update section number for the symbol entry
531 }
532 /*---------------------------------*/
533 CurrentSymEx = CurrentSymEx->next;
534 }/*-------------------------------------*/
535
536 /*--- Update the symbol table section header ---*/
537 CurrentShdrEx->loaded_adr = (u32)(ELi_CopySymToBuffer( ElfHandle));
538 if( (CurrentShdrEx->Shdr.sh_link != SHN_UNDEF) &&
539 (CurrentShdrEx->Shdr.sh_link < SHN_LORESERVE)) {
540 CurrentShdrEx->Shdr.sh_link = shdr_table[CurrentShdrEx->Shdr.sh_link]; //Update string section number
541 }
542 CurrentShdrEx->Shdr.sh_size = symbol_num * sizeof( Elf32_Sym);
543 CurrentShdrEx->Shdr.sh_info = last_local_symbol_index; //Reference the ARM ELF materials
544 /*----------------------------------------------*/
545 }
546 ELi_FreeSymList( ElfHandle, (u32**)(CurrentShdrEx->sym_table)); //Deallocate the symbol list
547 }
548
549 /* printf( "section %02x relocated at %08x\n",
550 i, CurrentShdrEx->loaded_adr);*/
551 }
552 }
553
554 /*---------- Processing for REL, RELA, STRTAB sections ----------*/
555 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
556 //
557 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
558
559 if( CurrentShdrEx->debug_flag == 1) { //When it is debugging information
560 }else{ //When not debugging information
561 //REL section
562 if( CurrentShdrEx->Shdr.sh_type == SHT_REL) {
563 CurrentShdrEx->loaded_adr = (u32)
564 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
565 {
566 Elf32_Rel* CurrentRel;
567 ELShdrEx* SymShdrEx;
568 u32 new_sym_num;
569 /*Get the symbol section*/
570 SymShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx,
571 CurrentShdrEx->Shdr.sh_link);
572 /*Correct the Rel section of the copy source*/
573 for( j=0; j<(CurrentShdrEx->Shdr.sh_size/CurrentShdrEx->Shdr.sh_entsize); j++) {
574 CurrentRel = (Elf32_Rel*)(CurrentShdrEx->loaded_adr + (j * sizeof( Elf32_Rel)));
575 new_sym_num = SymShdrEx->sym_table[ELF32_R_SYM(CurrentRel->r_info)];
576 CurrentRel->r_info = ELF32_R_INFO( new_sym_num,
577 ELF32_R_TYPE(CurrentRel->r_info));
578 }
579 }
580 }
581 //RELA section
582 else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) {
583 CurrentShdrEx->loaded_adr = (u32)
584 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
585 {
586 Elf32_Rela* CurrentRela;
587 ELShdrEx* SymShdrEx;
588 u32 new_sym_num;
589 /*Get the symbol section*/
590 SymShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx,
591 CurrentShdrEx->Shdr.sh_link);
592 /*Correct the Rela section of the copy source*/
593 for( j=0; j<(CurrentShdrEx->Shdr.sh_size/CurrentShdrEx->Shdr.sh_entsize); j++) {
594 CurrentRela = (Elf32_Rela*)(CurrentShdrEx->loaded_adr + (j * sizeof( Elf32_Rela)));
595 // printf( "symnum: 0x%x\n", ELF32_R_SYM(CurrentRela->r_info));
596 // printf( "sym_table:0x%x", (u32)(SymShdrEx->sym_table));
597 new_sym_num = SymShdrEx->sym_table[ELF32_R_SYM(CurrentRela->r_info)];
598 CurrentRela->r_info = ELF32_R_INFO( new_sym_num,
599 ELF32_R_TYPE(CurrentRela->r_info));
600 }
601 }
602 }
603 //String table section
604 else if( CurrentShdrEx->Shdr.sh_type == SHT_STRTAB) {
605 if( i == ElfHandle->CurrentEhdr.e_shstrndx) { //Section name string table section
606 CurrentShdrEx->loaded_adr = (u32)
607 ELi_CopyShStrToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
608 }else{
609 CurrentShdrEx->loaded_adr = (u32)
610 ELi_CopySymStrToBuffer( ElfHandle, CurrentShdrEx);
611 // printf( "sym str section:0x%x, size:0x%x\n", i, CurrentShdrEx->str_table_size);
612 }
613 }
614 }
615 }
616 /*-------------------------------------------------------*/
617
618
619 /*Only the section content up to this point was copied to stripped ELF*/
620
621
622 /*---------- Copy section header to stripped elf ----------*/
623 buf_shdr = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
624 ElfHandle->buf_current = (void*)buf_shdr;
625 // printf( "buf_shdr = 0x%x\n", buf_shdr);
626 // printf( "buf = 0x%x\n", (u32)buf);
627
628 newelf_shoff = buf_shdr - ((u32)(buf));
629 // printf( "newelf_shoff = 0x%x\n", newelf_shoff);
630
631 section_num = 0;
632 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
633 //
634 tmp_buf = buf_shdr + ( section_num * sizeof( Elf32_Shdr));
635
636 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
637 if( CurrentShdrEx->debug_flag == 1) { //Convert to the NULL section for debugging information
638 // memset( (u8*)tmp_buf, '\0', sizeof( Elf32_Shdr));
639 }else{
640 /*Update offset*/
641 if( CurrentShdrEx->loaded_adr != 0) {
642 CurrentShdrEx->Shdr.sh_offset = (CurrentShdrEx->loaded_adr - (u32)buf);
643 }
644 /*Copy section header to stripped ELF image*/
645 if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) {
646 /*The symbol table sh_type indicates the index of the symbol entry*/
647 //For SYMTAB, because the sh_link is already converted at line 406, there is no need here.
648 //For SYMTAB, because the sh_info is already converted at line 428, there is no need here.
649 }else{
650 CurrentShdrEx->Shdr.sh_link = shdr_table[CurrentShdrEx->Shdr.sh_link]; //Update section number
651 CurrentShdrEx->Shdr.sh_info = shdr_table[CurrentShdrEx->Shdr.sh_info]; //Update section number
652 }
653 memcpy( (u8*)tmp_buf, &(CurrentShdrEx->Shdr),
654 sizeof( Elf32_Shdr));
655 section_num++; /*Update section count*/
656 }
657 }
658
659 // After copy ends
660 ElfHandle->process = EL_COPIED;
661 /*------------------------------------------------------------*/
662
663 ElfHandle->newelf_size = (buf_shdr - (u32)buf) + (section_num*sizeof( Elf32_Shdr));
664 // printf( "newelf_size = 0x%x\n", ElfHandle->newelf_size);
665
666 /*---------- Update ELF Header ----------*/
667 ElfHandle->CurrentEhdr.e_shnum = section_num; /*Apply the reduced section count to the ELF header*/
668 ElfHandle->CurrentEhdr.e_shstrndx = shdr_table[ElfHandle->CurrentEhdr.e_shstrndx];
669 //Update the section header offset
670 ElfHandle->CurrentEhdr.e_shoff = newelf_shoff;
671 memcpy( (u8*)buf, &(ElfHandle->CurrentEhdr), sizeof( Elf32_Ehdr)); /*Copy ELF header to the stripped ELF image*/
672 /*-----------------------------------*/
673
674
675 /*---------- Relocate ----------*/
676 /* if( unresolved_table_block_flag == 0) {
677 if( dbg_print_flag == 1) {
678 printf( "\nRelocate Symbols:\n");
679 }
680 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
681 //
682 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
683
684 if( CurrentShdrEx->debug_flag == 1) { //When it is debugging information
685 }else{ //When not debugging information
686
687 if( CurrentShdrEx->Shdr.sh_type == SHT_REL) {
688 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
689 (CurrentShdrEx->Shdr.sh_entsize);
690 if( dbg_print_flag == 1) {
691 printf( "num of REL = %x\n", num_of_entry);
692 printf( "Section Header Info.\n");
693 printf( "link : %x\n", CurrentShdrEx->Shdr.sh_link);
694 printf( "info : %x\n", CurrentShdrEx->Shdr.sh_info);
695 printf( " Offset Info Type Sym.Value Sym.Name\n");
696 }
697 offset = 0;
698 for( j=0; j<num_of_entry; j++) {
699 ELi_GetSent( ElfHandle, i, &(ElfHandle->Rel), offset, sizeof(Elf32_Rel));
700 ELi_GetShdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->SymShdr));
701 ELi_GetSent( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->Sym),
702 (u32)(ElfHandle->SymShdr.sh_entsize * ELF32_R_SYM( ElfHandle->Rel.r_info)), sizeof(Elf32_Sym));
703 ELi_GetStrAdr( ElfHandle, ElfHandle->SymShdr.sh_link, ElfHandle->Sym.st_name, sym_str, 128);
704
705 if( dbg_print_flag == 1) {
706 printf( "%08x ", ElfHandle->Rel.r_offset);
707 printf( "%08x ", ElfHandle->Rel.r_info);
708 printf( " ");
709 printf( "%08x ", ElfHandle->Sym.st_value);
710 printf( sym_str);
711 printf("\n");
712 }
713 // To next entry
714 offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
715 }
716 if( dbg_print_flag == 1) {
717 printf("\n");
718 }
719 //Relocate
720 ELi_RelocateSym( ElfHandle, i);
721 if( dbg_print_flag == 1) {
722 printf("\n");
723 }
724 }
725 else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) {
726
727 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
728 (CurrentShdrEx->Shdr.sh_entsize);
729 if( dbg_print_flag == 1) {
730 printf( "num of RELA = %x\n", num_of_entry);
731 printf( "Section Header Info.\n");
732 printf( "link : %x\n", CurrentShdrEx->Shdr.sh_link);
733 printf( "info : %x\n", CurrentShdrEx->Shdr.sh_info);
734 printf( " Offset Info Type Sym.Value Sym.Name\n");
735 }
736 offset = 0;
737 for( j=0; j<num_of_entry; j++) {
738 ELi_GetSent( ElfHandle, i, &(ElfHandle->Rela), offset, sizeof(Elf32_Rel));
739 ELi_GetShdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->SymShdr));
740 ELi_GetSent( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->Sym),
741 (u32)(ElfHandle->SymShdr.sh_entsize * ELF32_R_SYM( ElfHandle->Rela.r_info)), sizeof(Elf32_Sym));
742 ELi_GetStrAdr( ElfHandle, ElfHandle->SymShdr.sh_link, ElfHandle->Sym.st_name, sym_str, 128);
743
744 if( dbg_print_flag == 1) {
745 printf( "%08x ", ElfHandle->Rela.r_offset);
746 printf( "%08x ", ElfHandle->Rela.r_info);
747 printf( " ");
748 printf( "%08x ", ElfHandle->Sym.st_value);
749 printf( sym_str);
750 printf("\n");
751 }
752 // To next entry
753 offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
754 }
755 if( dbg_print_flag == 1) {
756 printf("\n");
757 }
758 //Relocate
759 ELi_RelocateSym( ElfHandle, i);
760 if( dbg_print_flag == 1) {
761 printf("\n");
762 }
763 }
764 }
765 }
766 }else{ //When not dll but a static module
767 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
768 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
769 if( CurrentShdrEx->debug_flag == 1) { //When it is debugging information
770 } else {
771 if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) {
772 ELi_DiscriminateGlobalSym( ElfHandle, i);
773 }
774 }
775 }
776 }*/
777
778 /*---------- Deallocate the ELShdrEx List ----------*/
779 CurrentShdrEx = ElfHandle->ShdrEx;
780 if( CurrentShdrEx) {
781 do{
782 FwdShdrEx = CurrentShdrEx;
783 CurrentShdrEx = CurrentShdrEx->next;
784 if( FwdShdrEx->debug_flag == 0) {
785 free( FwdShdrEx->str); //When not debugging section
786 }
787 free( FwdShdrEx);
788 }while( CurrentShdrEx != NULL);
789 ElfHandle->ShdrEx = NULL;
790 }
791 /*-----------------------------------------*/
792
793 /*Deallocate the section header table*/
794 free( shdr_table);
795
796
797
798 /*Flush cache before the DLL in RAM is called*/
799 // DC_FlushAll();
800 // DC_WaitWriteBufferEmpty();
801
802 return (ElfHandle->process);
803 }
804
805 /*------------------------------------------------------
806 Resolve unresolved symbols using the address table
807 -----------------------------------------------------*/
EL_ResolveAllLibrary(void)808 u16 EL_ResolveAllLibrary( void)
809 {
810 ELAdrEntry* AdrEnt;
811 ELUnresolvedEntry* RemoveUnrEnt;
812 ELUnresolvedEntry* UnrEnt;
813 // ELUnresolvedEntry* CurrentUnrEnt;
814 // ELUnresolvedEntry* FwdUnrEnt;
815 // u32 relocation_val;
816 // ELAdrEntry AddAdrEnt;
817 #if 0 // Do not dynamically allocate section string buffer
818 char sym_str[128];
819 #else
820 char *sym_str;
821 #endif
822 UnrEnt = ELUnrEntStart;
823 if( dbg_print_flag == 1) {
824 printf( "\nResolve all symbols:\n");
825 }
826 while( UnrEnt != NULL) {
827 if( UnrEnt->remove_flag == 0) {
828 AdrEnt = EL_GetAdrEntry( UnrEnt->sym_str); /*Search from address table*/
829 if( AdrEnt) { /*When found in address table*/
830 UnrEnt->S_ = (u32)(AdrEnt->adr);
831 UnrEnt->T_ = (u32)(AdrEnt->thumb_flag);
832 if( unresolved_table_block_flag == 0) {
833 if( dbg_print_flag == 1) {
834 // printf( "\n symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_);
835 }
836 UnrEnt->remove_flag = 1;
837 // ELi_RemoveUnresolvedEntry( UnrEnt); //Delete from unresolved list because this was resolved
838 }else{
839 if( dbg_print_flag == 1) {
840 printf( "\n static symbol found %s : %8x\n", UnrEnt->sym_str, (int)(UnrEnt->S_));
841 }
842 UnrEnt->AdrEnt = AdrEnt; //Set the found address entry
843 UnrEnt->remove_flag = 2; //Marking (special value used only with makelst)
844 #if 0 // Do not dynamically allocate section string buffer
845 #else
846 sym_str = (char*)malloc( strlen( UnrEnt->sym_str ) + 1 );
847 if(sym_str == 0)
848 {
849 return EL_FAILED;
850 }
851 #endif
852 strcpy( sym_str, UnrEnt->sym_str);
853 while( 1) {
854 RemoveUnrEnt = ELi_GetUnresolvedEntry( sym_str);
855 if( RemoveUnrEnt == NULL) {
856 break;
857 }else{
858 RemoveUnrEnt->remove_flag = 1;
859 }
860 }
861 #if 0 // Do not dynamically allocate section string buffer
862 #else
863 free(sym_str);
864 #endif
865 }
866 /* relocation_val = ELi_DoRelocate( UnrEnt); //Resolve symbol
867 if( !relocation_val) {
868 return EL_FAILED;
869 }*/
870
871 }else{ /*When not found in address table*/
872 if( unresolved_table_block_flag == 0) {
873 if( dbg_print_flag == 1) {
874 printf( "ERROR! cannot find symbol : %s\n", UnrEnt->sym_str);
875 }
876 }else{
877 if( dbg_print_flag == 1) {
878 printf( "ERROR! cannot find static symbol : %s\n", UnrEnt->sym_str);
879 }
880 }
881 /* AddAdrEnt.next = NULL;
882 AddAdrEnt.name = UnrEnt->sym_str;
883 AddAdrEnt.
884 EL_AddAdrEntry( */
885 // return EL_FAILED;
886 }
887 }
888 UnrEnt = (ELUnresolvedEntry*)(UnrEnt->next); /*To next unresolved entry*/
889 }
890
891 /*---------- Deallocate the ELUnresolvedEntry List ----------*/
892 /* CurrentUnrEnt = ELUnrEntStart;
893 if( CurrentUnrEnt) {
894 while( CurrentUnrEnt->next != NULL) {
895 FwdUnrEnt = CurrentUnrEnt;
896 CurrentUnrEnt = CurrentUnrEnt->next;
897 free( FwdUnrEnt->sym_str); // symbol name string
898 free( FwdUnrEnt); //Structure itself
899 }
900 ELUnrEntStart = NULL;
901 }*/
902 /*-------------------------------------------*/
903
904 /*Flush cache before the DLL in RAM is called*/
905 // DC_FlushAll();
906 // DC_WaitWriteBufferEmpty();
907
908 return EL_RELOCATED;
909 }
910
911
912
913
914
915 /*------------------------------------------------------
916 Delete entry from address table
917 -----------------------------------------------------*/
EL_RemoveAdrEntry(ELAdrEntry * AdrEnt)918 BOOL EL_RemoveAdrEntry( ELAdrEntry* AdrEnt)
919 {
920 ELAdrEntry DmyAdrEnt;
921 ELAdrEntry* CurrentAdrEnt;
922
923 DmyAdrEnt.next = ELAdrEntStart;
924 CurrentAdrEnt = &DmyAdrEnt;
925
926 while( CurrentAdrEnt->next != AdrEnt) {
927 if( CurrentAdrEnt->next == NULL) {
928 return FALSE;
929 }else{
930 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
931 }
932 }
933
934 CurrentAdrEnt->next = AdrEnt->next;
935 ELAdrEntStart = DmyAdrEnt.next;
936
937 return TRUE;
938 }
939
940 /*------------------------------------------------------
941 Add entry to address table
942 -----------------------------------------------------*/
EL_AddAdrEntry(ELAdrEntry * AdrEnt)943 void EL_AddAdrEntry( ELAdrEntry* AdrEnt)
944 {
945 ELAdrEntry DmyAdrEnt;
946 ELAdrEntry* CurrentAdrEnt;
947
948 if( !ELAdrEntStart) {
949 ELAdrEntStart = AdrEnt;
950 }else{
951 DmyAdrEnt.next = ELAdrEntStart;
952 CurrentAdrEnt = &DmyAdrEnt;
953
954 while( CurrentAdrEnt->next != NULL) {
955 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
956 }
957 CurrentAdrEnt->next = (void*)AdrEnt;
958 }
959 AdrEnt->next = NULL;
960 }
961
962 /*------------------------------------------------------
963 Search for entry corresponding to specified string in address table
964 -----------------------------------------------------*/
EL_GetAdrEntry(char * ent_name)965 ELAdrEntry* EL_GetAdrEntry( char* ent_name)
966 {
967 ELAdrEntry* CurrentAdrEnt;
968
969 CurrentAdrEnt = ELAdrEntStart;
970 if( CurrentAdrEnt == NULL) {
971 return NULL;
972 }
973 while( strcmp( CurrentAdrEnt->name, ent_name) != 0) {
974 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
975 if( CurrentAdrEnt == NULL) {
976 break;
977 }
978 }
979 return CurrentAdrEnt;
980 }
981
982 /*------------------------------------------------------
983 Return address corresponding to specified string in address table
984 -----------------------------------------------------*/
EL_GetGlobalAdr(char * ent_name)985 void* EL_GetGlobalAdr( char* ent_name)
986 {
987 u32 adr;
988 ELAdrEntry* CurrentAdrEnt;
989
990 CurrentAdrEnt = EL_GetAdrEntry( ent_name);
991
992 if( CurrentAdrEnt) {
993 if( CurrentAdrEnt->thumb_flag) {
994 adr = (u32)(CurrentAdrEnt->adr) + 1;
995 }else{
996 adr = (u32)(CurrentAdrEnt->adr);
997 }
998 }else{
999 adr = 0;
1000 }
1001
1002 return (void*)(adr);
1003 }
1004
1005 #if 0
1006 /*------------------------------------------------------
1007 Deallocate the address table (not allowed because it tried to delete up to the entry registered by the application)
1008 -----------------------------------------------------*/
1009 void* EL_FreeAdrTbl( void)
1010 {
1011 ELAdrEntry* FwdAdrEnt;
1012 ELAdrEntry* CurrentAdrEnt;
1013
1014 /*---------- Deallocate the ELAdrEntry List ----------*/
1015 CurrentAdrEnt = ELAdrEntStart;
1016 if( CurrentAdrEnt) {
1017 while( CurrentAdrEnt->next != NULL) {
1018 FwdAdrEnt = CurrentAdrEnt;
1019 CurrentAdrEnt = CurrentAdrEnt->next;
1020 free( FwdAdrEnt->name); //Symbol name string
1021 free( FwdAdrEnt); //Structure itself
1022 }
1023 ELAdrEntStart = NULL;
1024 }
1025 /*------------------------------------*/
1026 }
1027 #endif
1028
1029 /*------------------------------------------------------
1030 Stub that reads data from the ELF object
1031 -----------------------------------------------------*/
ELi_ReadFile(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1032 void ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1033 {
1034 // printf( "0x%x, 0x%x\n", file_offset, size);
1035 fseek( file_struct, file_offset, SEEK_SET);
1036 fread( buf, 1, size, file_struct);
1037
1038 /* FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET);
1039 FS_ReadFile( file_struct, buf, (s32)(size));*/
1040 }
1041
ELi_ReadMem(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1042 void ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1043 {
1044 /* MI_CpuCopy8( (void*)(file_base + file_offset),
1045 buf,
1046 size);*/
1047 memcpy( buf,
1048 (void*)(file_base + file_offset),
1049 size);
1050 }
1051