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