1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ELF Loader
3 File: elf_loader.c
4
5 Copyright 2006-2009 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 "el_config.h"
19
20 #ifdef SDK_TWL
21 #include <twl.h>
22 #else
23 #include <nitro.h>
24 #endif
25
26 #include "elf.h"
27 #include "arch.h"
28 #include "elf_loader.h"
29 #include "loader_subset.h"
30 #include <istdbglibpriv.h>
31
32
33 #ifndef SDK_TWL
34 OSHeapHandle EL_Heap;
35 #endif
36
37
38 #if 1
39
40 /*------------------------------------------------------
41 Function to notify IS-TWL_DEBUGGER
42 -----------------------------------------------------*/
43 void _ISTDbgLib_StartRegistRelocationInfo( ISTDOVERLAYPROC nProc );
44 BOOL _ISTDbgLib_RegistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA );
45 void _ISTDbgLib_EndRegistRelocationInfo( ISTDOVERLAYPROC nProc );
46 BOOL _ISTDbgLib_UnregistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll );
47
_ISTDbgLib_StartRegistRelocationInfo(ISTDOVERLAYPROC nProc)48 SDK_WEAK_SYMBOL void _ISTDbgLib_StartRegistRelocationInfo( ISTDOVERLAYPROC nProc )
49 {
50 (void)nProc;
51 return;
52 }
53
_ISTDbgLib_RegistRelocationInfo(ISTDOVERLAYPROC nProc,u32 nDll,u32 nELF,u32 nSection,u32 nLMA)54 SDK_WEAK_SYMBOL BOOL _ISTDbgLib_RegistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA )
55 {
56 (void)nProc;
57 (void)nDll;
58 (void)nELF;
59 (void)nSection;
60 (void)nLMA;
61 return TRUE;
62 }
63
_ISTDbgLib_EndRegistRelocationInfo(ISTDOVERLAYPROC nProc)64 SDK_WEAK_SYMBOL void _ISTDbgLib_EndRegistRelocationInfo( ISTDOVERLAYPROC nProc )
65 {
66 (void)nProc;
67 return;
68 }
69
_ISTDbgLib_UnregistRelocationInfo(ISTDOVERLAYPROC nProc,u32 nDll)70 SDK_WEAK_SYMBOL BOOL _ISTDbgLib_UnregistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll )
71 {
72 (void)nProc;
73 (void)nDll;
74 return TRUE;
75 }
76
77 /* stub */
78 static void ELi_START_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable );
79 static BOOL ELi_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA, BOOL enable );
80 static void ELi_END_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable );
81 static BOOL ELi_UNREGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, BOOL enable );
82
ELi_START_REGISTER_RELOCATION_INFO(ISTDOVERLAYPROC nProc,BOOL enable)83 static void ELi_START_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable )
84 {
85 if( enable) {
86 _ISTDbgLib_StartRegistRelocationInfo( nProc);
87 }
88 }
ELi_REGISTER_RELOCATION_INFO(ISTDOVERLAYPROC nProc,u32 nDll,u32 nELF,u32 nSection,u32 nLMA,BOOL enable)89 static BOOL ELi_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA, BOOL enable )
90 {
91 if( enable) {
92 return( _ISTDbgLib_RegistRelocationInfo( nProc, nDll, nELF, nSection, nLMA));
93 }
94 return( FALSE);
95 }
ELi_END_REGISTER_RELOCATION_INFO(ISTDOVERLAYPROC nProc,BOOL enable)96 static void ELi_END_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable )
97 {
98 if( enable) {
99 _ISTDbgLib_EndRegistRelocationInfo( nProc);
100 }
101 }
ELi_UNREGISTER_RELOCATION_INFO(ISTDOVERLAYPROC nProc,u32 nDll,BOOL enable)102 static BOOL ELi_UNREGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, BOOL enable )
103 {
104 if( enable) {
105 return( _ISTDbgLib_UnregistRelocationInfo( nProc, nDll));
106 }
107 return( FALSE);
108 }
109 #endif
110
111
112 /*------------------------------------------------------
113 External Functions
114 -----------------------------------------------------*/
115 extern ELDesc* i_eldesc_sim;
116
117
118 /*------------------------------------------------------
119 Global Variables
120 -----------------------------------------------------*/
121 static ELReadImage i_elReadImage;
122 ELAlloc i_elAlloc;
123 ELFree i_elFree;
124
125 static BOOL i_el_initialized = FALSE;
126 static OSMutex i_el_mutex;
127
128
129 /*------------------------------------------------------
130 Local Function Declarations
131 -----------------------------------------------------*/
132 static void ELi_FreeObject( ELObject** ELObjEntStart);
133 static void ELi_InitObject( ELObject* MYObject);
134 BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt);
135 static void elAddObjEntry( ELObject** StartEnt, ELObject* ObjEnt);
136
137 static BOOL ELi_ReInitDesc( ELDesc* elElfDesc);
138 static ELResult elLoadSegments( ELDesc* elElfDesc, ELObject* MYObject);
139 static ELResult elLoadSections( ELDesc* elElfDesc, ELObject* MYObject, u32 dll_fileid, u32 elf_num);
140
141 // Relocate ELF object or the archive in a buffer
142 static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, u32 buf_size, u32 dll_fileid);
143 // Core function that relocates ELF object to buffer
144 static ELResult ELi_LoadObject( ELDesc* elElfDesc, ELObject* MYObject, void* obj_offset, void* buf, u32 dll_fileid, u32 elf_num);
145 // Stub functions that read data from the ELF object
146 static BOOL ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size);
147 static BOOL ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size);
148 static BOOL ELi_ReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size);
149
150 // Delete entry from address table
151 //BOOL elRemoveAdrEntry( ELAdrEntry* AdrEnt);
152
153 // Add entry to address table
154 void elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt);
155
156 // Search for entry corresponding to specified string in address table
157 ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt);
158
159 // Deallocate all address tables
160 static void elFreeAdrTbl( ELAdrEntry** ELAdrEntStart);
161
162
163 /*---------------------------------------------------------
164 Find size of the ELF object
165
166 buf: Address of ELF image
167 --------------------------------------------------------*/
EL_GetElfSize(const void * buf)168 u32 EL_GetElfSize( const void* buf)
169 {
170 Elf32_Ehdr Ehdr;
171 u32 size;
172
173 if( ELF_LoadELFHeader( buf, &Ehdr) == NULL) {
174 return 0;
175 }
176 size = (u32)(Ehdr.e_shoff + (Ehdr.e_shentsize * Ehdr.e_shnum));
177 return size;
178 }
179
180
181 /*---------------------------------------------------------
182 Find the size of the linked library
183 --------------------------------------------------------*/
EL_GetLibSize(ELDlld my_dlld)184 u32 EL_GetLibSize( ELDlld my_dlld)
185 {
186 if( my_dlld == 0) {
187 return( 0);
188 }
189 return( ((ELObject*)my_dlld)->lib_size);
190 }
191
192
193 /*------------------------------------------------------
194 Initializes the dynamic link system.
195 -----------------------------------------------------*/
196 #if 0
197 //#ifndef SDK_TWL
198 void ELi_Init( void)
199 {
200 void* heap_start;
201
202 if( i_el_initialized) {
203 return;
204 }
205
206 i_el_initialized = TRUE;
207
208 /*--- Memory allocation related settings ---*/
209 OS_InitArena();
210 heap_start = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
211 OS_SetMainArenaLo( heap_start );
212 EL_Heap = OS_CreateHeap( OS_ARENA_MAIN, heap_start, (void*)((u32)(OS_GetMainArenaHi())+1));
213 OS_SetCurrentHeap( OS_ARENA_MAIN, EL_Heap);
214 /*--------------------------------------*/
215
216 OS_InitMutex( &i_el_mutex);
217 }
218 #else
ELi_Init(ELAlloc alloc,ELFree free)219 void ELi_Init( ELAlloc alloc, ELFree free)
220 {
221 i_elAlloc = alloc;
222 i_elFree = free;
223
224 if( i_el_initialized) {
225 return;
226 }
227
228 i_el_initialized = TRUE;
229
230 OS_InitMutex( &i_el_mutex);
231 }
232
ELi_Malloc(ELDesc * elElfDesc,ELObject * MYObject,size_t size)233 void* ELi_Malloc( ELDesc* elElfDesc, ELObject* MYObject, size_t size)
234 {
235 void* ptr;
236
237 ptr = OSAPI_MALLOC( size);
238 if( ptr == NULL) {
239 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_NO_MORE_RESOURCE);
240 return( NULL);
241 }
242 return( ptr);
243 }
244 #endif
245
246 /*------------------------------------------------------
247 Initialize the ELDesc structure
248 -----------------------------------------------------*/
ELi_InitDesc(ELDesc * elElfDesc)249 BOOL ELi_InitDesc( ELDesc* elElfDesc)
250 {
251 if( elElfDesc == NULL) { /*NULL check*/
252 return FALSE;
253 }
254
255 /*Set default values*/
256 elElfDesc->ShdrEx = NULL;
257 elElfDesc->SymEx = NULL;
258 elElfDesc->SymExTbl = NULL;
259 elElfDesc->SymExTarget = 0xFFFFFFFF;
260
261 elElfDesc->process = (u32)EL_PROC_INITIALIZED; /*Set the flag*/
262 elElfDesc->result = (u32)EL_RESULT_SUCCESS;
263
264 /**/
265 elElfDesc->ELObjectStart = NULL;
266 elElfDesc->ELStaticObj = NULL;
267
268 return TRUE;
269 }
270
271 /*------------------------------------------------------
272 Reinitialize the ELDesc structure if the object has finished reading
273 -----------------------------------------------------*/
ELi_ReInitDesc(ELDesc * elElfDesc)274 static BOOL ELi_ReInitDesc( ELDesc* elElfDesc)
275 {
276 if( elElfDesc == NULL) { /*NULL check*/
277 return FALSE;
278 }
279
280 /*Set default values*/
281 elElfDesc->ShdrEx = NULL;
282 elElfDesc->SymEx = NULL;
283 elElfDesc->SymExTbl = NULL;
284 elElfDesc->SymExTarget = 0xFFFFFFFF;
285
286 elElfDesc->process = (u32)EL_PROC_INITIALIZED; /*Set the flag*/
287 elElfDesc->result = (u32)EL_RESULT_SUCCESS;
288
289 return TRUE;
290 }
291
292 /*------------------------------------------------------
293 Relocate ELF object or the archive in a buffer
294
295 elElfDesc: Header structure
296 ObjFile: Object file or archive file structure
297 buf: Buffer for loading
298 -----------------------------------------------------*/
EL_LoadLibraryfromFile(ELDesc * elElfDesc,const char * FilePath,void * buf,u32 buf_size)299 ELDlld EL_LoadLibraryfromFile( ELDesc* elElfDesc, const char* FilePath, void* buf, u32 buf_size)
300 {
301 ELDlld dlld;
302 u32 len;
303 FSFile file[1];
304 FSFileID file_id[1];
305
306 if( elElfDesc == NULL) {
307 return( 0);
308 }
309
310 OS_LockMutex( &i_el_mutex);
311
312 FS_InitFile(file);
313
314 if( !FS_OpenFileEx(file, FilePath, FS_FILEMODE_R) )
315 {
316 ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF);
317 OS_UnlockMutex( &i_el_mutex);
318 return 0;
319 }
320
321 if( !FS_ConvertPathToFileID( file_id, FilePath ) )
322 {
323 (void)FS_CloseFile(file);
324 OS_UnlockMutex( &i_el_mutex);
325 return 0;
326 }
327
328 /*Set read function*/
329 elElfDesc->i_elReadStub = ELi_ReadFile;
330 elElfDesc->FileStruct = (int*)file;
331
332 len = FS_GetFileLength( file );
333
334 dlld = ELi_LoadLibrary( elElfDesc, NULL, len, buf, buf_size, file_id[0].file_id);
335
336 if( dlld != 0) {
337 ((ELObject*)dlld)->file_id = file_id[0].file_id;
338 }
339
340 if( !FS_CloseFile(file)) {
341 ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF);
342 dlld = 0;
343 }
344
345 OS_UnlockMutex( &i_el_mutex);
346 return( dlld);
347 }
348
349 /*------------------------------------------------------
350 Relocate ELF object or the archive in a buffer
351
352 elElfDesc: Header structure
353 readfunc: User function that reads OBJ or archive files
354 buf: Buffer for loading
355 -----------------------------------------------------*/
EL_LoadLibrary(ELDesc * elElfDesc,ELReadImage readfunc,u32 len,void * buf,u32 buf_size)356 ELDlld EL_LoadLibrary( ELDesc* elElfDesc, ELReadImage readfunc, u32 len, void* buf, u32 buf_size)
357 {
358 ELDlld dlld;
359
360 if( elElfDesc == NULL) {
361 return( 0);
362 }
363
364 OS_LockMutex( &i_el_mutex);
365
366 i_elReadImage = readfunc;
367 elElfDesc->i_elReadStub = ELi_ReadUsr;
368
369 dlld = ELi_LoadLibrary( elElfDesc, NULL, len, buf, buf_size, 0xFFFFFFFF);
370
371 if( dlld != 0) {
372 ((ELObject*)dlld)->file_id = 0xFFFFFFFF;
373 }
374
375 OS_UnlockMutex( &i_el_mutex);
376 return( dlld);
377 }
378
379 /*------------------------------------------------------
380 Relocate ELF object or the archive in a buffer
381
382 elElfDesc: Header structure
383 obj_image: RAM image address for OBJ file or archive file
384 buf: Buffer for loading
385 -----------------------------------------------------*/
EL_LoadLibraryfromMem(ELDesc * elElfDesc,void * obj_image,u32 obj_len,void * buf,u32 buf_size)386 ELDlld EL_LoadLibraryfromMem( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, u32 buf_size)
387 {
388 ELDlld dlld;
389
390 if( elElfDesc == NULL) {
391 return( 0);
392 }
393
394 OS_LockMutex( &i_el_mutex);
395
396 /*Set read function*/
397 elElfDesc->i_elReadStub = ELi_ReadMem;
398 elElfDesc->FileStruct = NULL;
399
400 dlld = ELi_LoadLibrary( elElfDesc, obj_image, obj_len, buf, buf_size, 0xFFFFFFFF);
401
402 if( dlld != 0) {
403 ((ELObject*)dlld)->file_id = 0xFFFFFFFF;
404 }
405
406 OS_UnlockMutex( &i_el_mutex);
407 return( dlld);
408 }
409
410 /*------------------------------------------------------
411 Relocate ELF object or the archive in a buffer
412
413 elElfDesc: Header structure
414 obj_image: RAM image address for OBJ file or archive file
415 buf: Buffer for loading
416 -----------------------------------------------------*/
ELi_LoadLibrary(ELDesc * elElfDesc,void * obj_image,u32 obj_len,void * buf,u32 buf_size,u32 dll_fileid)417 static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, u32 buf_size, u32 dll_fileid)
418 {
419 ELResult result;
420 u32 image_pointer;
421 u32 arch_size;
422 u32 elf_num = 0; /*Number of ELF objects*/
423 u32 obj_size;
424 ArchHdr ArHdr;
425 char OBJMAG[8];
426 char ELFMAG[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3};
427 ELObject* MYObject;
428
429 /*-------*/
430 if( elElfDesc->i_elReadStub == NULL) {
431 ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF);
432 return( 0);
433 }
434 /*-------*/
435
436 /* Allocate individual object management structure */
437 MYObject = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject));
438 if(MYObject == NULL)
439 return 0;
440 ELi_InitObject( MYObject);
441 elAddObjEntry( &(elElfDesc->ELObjectStart), MYObject);
442
443 elElfDesc->ar_head = obj_image;
444 image_pointer = 0;
445 MYObject->lib_start = buf;
446 MYObject->buf_current = buf;
447 /* Set the boundary address for checking buffers */
448 if( buf_size > (0xFFFFFFFF - (u32)buf)) {
449 MYObject->buf_limit_addr = 0xFFFFFFFF;
450 }else{
451 MYObject->buf_limit_addr = ((u32)buf + buf_size);
452 }
453
454 if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)obj_image, 0, 8) == FALSE) { /*Get the OBJ string*/
455 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
456 return( 0);
457 }
458 /*--------------- For archive files ---------------*/
459 if( OSAPI_STRNCMP( OBJMAG, ARMAG, 8) == 0) {
460 arch_size = sizeof( ArchHdr);
461 image_pointer += 8; /*To first entry*/
462
463 while( image_pointer < obj_len) {
464 if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4)
465 == FALSE) { /*Get the OBJ string*/
466 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
467 break;
468 }
469 if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) {
470 /*Reset initial values*/
471 (void)ELi_ReInitDesc( elElfDesc);
472 result = ELi_LoadObject( elElfDesc, MYObject, (void*)(image_pointer+arch_size), MYObject->buf_current, dll_fileid, elf_num);
473 if( result != EL_RESULT_SUCCESS) {
474 break;
475 }
476 elf_num++;
477 }else{
478 }
479 /*To next entry*/
480 if( elElfDesc->i_elReadStub( &ArHdr, elElfDesc->FileStruct, (u32)(obj_image), image_pointer, arch_size)
481 == FALSE) {
482 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
483 return( 0);
484 }
485 obj_size = AR_GetEntrySize( &ArHdr);
486 if( obj_size % 2) //Padded by '\n' when the object size is an odd number.
487 {
488 obj_size++;
489 }
490 image_pointer += arch_size + obj_size;
491 }
492 }else{/*--------------- For ELF files ---------------*/
493 if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) {
494 /*Reset initial values*/
495 (void)ELi_ReInitDesc( elElfDesc);
496 result = ELi_LoadObject( elElfDesc, MYObject, 0, MYObject->buf_current, dll_fileid, elf_num);
497 if( result != EL_RESULT_SUCCESS) {
498 }else{
499 elf_num++;
500 }
501 }else{
502 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF);
503 }
504 }
505 /*-------------------------------------------------------*/
506
507 if( elf_num) {
508 if( OS_IsRunOnDebugger() == FALSE) {
509 (void)ELi_FreeVenTbl( elElfDesc, MYObject); /*Release the veneer link list when not debugging*/
510 }
511 MYObject->stat = elf_num;
512 //When (MEMO)Segment was loaded, buf_current was not advanced, so it was not applied to lib_size
513 MYObject->lib_size = ((u32)(MYObject->buf_current)) - ((u32)(MYObject->lib_start));
514 PRINTDEBUG( "library size : 0x%x\n", MYObject->lib_size);
515 return( (ELDlld)MYObject);
516 }else{
517 /* Object could not be processed so structure was destroyed */
518 (void)elRemoveObjEntry( &(elElfDesc->ELObjectStart), MYObject);
519 return 0; //NULL
520 }
521 }
522
523 /*------------------------------------------------------
524 Relocate ELF object to buffer
525
526 elElfDesc: Header structure
527 MYObject: Individual object management structure
528 obj_offset: Offset from RAM image address of object file
529 buf: Buffer to load (TODO: Buffer overflow countermeasure)
530 -----------------------------------------------------*/
ELi_LoadObject(ELDesc * elElfDesc,ELObject * MYObject,void * obj_offset,void * buf,u32 dll_fileid,u32 elf_num)531 static ELResult ELi_LoadObject( ELDesc* elElfDesc, ELObject* MYObject, void* obj_offset, void* buf, u32 dll_fileid, u32 elf_num)
532 {
533 ELResult ret_val;
534
535 /* Check initialization of ELDesc */
536 if( elElfDesc->process != (u32)EL_PROC_INITIALIZED) {
537 return( EL_RESULT_FAILURE);
538 }
539 /* Get ELF header */
540 if( elElfDesc->i_elReadStub( &(elElfDesc->CurrentEhdr), elElfDesc->FileStruct,
541 (u32)(elElfDesc->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr))
542 == FALSE) {
543 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
544 return( EL_RESULT_CANNOT_ACCESS_ELF);
545 }
546
547 /* Build ELDesc structure */
548 elElfDesc->elf_offset = obj_offset;
549 elElfDesc->shentsize = elElfDesc->CurrentEhdr.e_shentsize;
550 elElfDesc->entry_adr = elElfDesc->CurrentEhdr.e_entry;
551
552 /* Process for each ELF file type */
553 switch( elElfDesc->CurrentEhdr.e_type) {
554
555 case ET_NONE:
556 PRINTDEBUG( "ERROR : Elf type \"ET_NONE\"\n");
557 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF);
558 ret_val = EL_RESULT_UNSUPPORTED_ELF;
559 break;
560
561 case ET_REL: /* X to execute; O to relocate */
562 PRINTDEBUG( "Elf type \"ET_REL\"\n");
563 if( buf == NULL) { /* Buffer NULL check */
564 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_NO_MORE_RESOURCE);
565 return EL_RESULT_NO_MORE_RESOURCE;
566 }
567 ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num);
568 break;
569
570 case ET_EXEC: /* O to execute; X to relocate */
571 PRINTDEBUG( "Elf type \"ET_EXEC\"\n");
572 ret_val = elLoadSegments( elElfDesc, MYObject);
573 break;
574
575 case ET_DYN: /* O to execute; O to relocate (TODO: untested)*/
576 PRINTDEBUG( "Elf type \"ET_DYN\"\n");
577 if( buf == NULL) { //Handle as ET_EXEC when the load address is not specified
578 ret_val = elLoadSegments( elElfDesc, MYObject);
579 }else{ //Handle as ET_REL when the load address is not specified
580 ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num);
581 }
582 break;
583
584 case ET_CORE:
585 PRINTDEBUG( "ERROR : Elf type \"ET_CORE\"\n");
586 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF);
587 ret_val = EL_RESULT_UNSUPPORTED_ELF;
588 break;
589
590 default:
591 PRINTDEBUG( "ERROR : Invalid Elf type 0x%x\n",
592 elElfDesc->CurrentEhdr.e_type);
593 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF);
594 ret_val = EL_RESULT_INVALID_ELF;
595 break;
596 }
597
598 return( ret_val);
599 }
600
601
602 /*------------------------------------------------------
603 Check and copy all segments
604
605 elElfDesc: Header structure
606 -----------------------------------------------------*/
elLoadSegments(ELDesc * elElfDesc,ELObject * MYObject)607 static ELResult elLoadSegments( ELDesc* elElfDesc, ELObject* MYObject)
608 {
609 u16 i;
610 //u32 load_start;
611 Elf32_Phdr CurrentPhdr;
612
613 for( i=0; i<(elElfDesc->CurrentEhdr.e_phnum); i++) {
614 /*Copy program header*/
615 ELi_GetPhdr( elElfDesc, i, &CurrentPhdr);
616
617 if( CurrentPhdr.p_type == PT_LOAD) {
618 /*If loadable segment, load to memory*/
619 if( ELi_CopySegmentToBuffer( elElfDesc, MYObject, &CurrentPhdr) == NULL) {
620 return( EL_RESULT_CANNOT_ACCESS_ELF);
621 }
622 }else{
623 PRINTDEBUG( "WARNING : skip segment (type = 0x%x)\n",
624 CurrentPhdr.p_type);
625 }
626 }
627 ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED);
628 return( EL_RESULT_SUCCESS);
629 }
630
631
632 /*------------------------------------------------------
633 Check and copy all sections
634
635 elElfDesc: Header structure
636 -----------------------------------------------------*/
elLoadSections(ELDesc * elElfDesc,ELObject * MYObject,u32 dll_fileid,u32 elf_num)637 static ELResult elLoadSections( ELDesc* elElfDesc, ELObject* MYObject, u32 dll_fileid, u32 elf_num)
638 {
639 u16 i;
640 ELShdrEx* FwdShdrEx;
641 ELShdrEx* CurrentShdrEx;
642 ELShdrEx* InfoShdrEx; //For example, consider CurrentShdrEx as .text for rel.text
643 ELShdrEx DmyShdrEx;
644 #if (DEBUG_PRINT_ON == 1)
645 u16 j;
646 u32 num_of_entry;
647 char sym_str[128]; //For debug print
648 u32 offset; //For debug print
649 #endif
650
651 /*---------- Create ELShdrEx List ----------*/
652 CurrentShdrEx = &DmyShdrEx;
653 for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
654 CurrentShdrEx->next = ELi_Malloc( elElfDesc, MYObject, sizeof(ELShdrEx));
655 if(CurrentShdrEx->next == NULL) {
656 return( EL_RESULT_NO_MORE_RESOURCE);
657 }
658 CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
659 OSAPI_CPUFILL8( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Clear zero
660
661 /*Set flag to distinguish whether this is debugging information*/
662 if( ELi_ShdrIsDebug( elElfDesc, i) == TRUE) { /*When it is debugging information*/
663 CurrentShdrEx->debug_flag = 1;
664 }else{ /*When not debugging information*/
665 /*Copy section header*/
666 ELi_GetShdr( elElfDesc, i, &(CurrentShdrEx->Shdr));
667 CurrentShdrEx->debug_flag = 0;
668 }
669 }
670 CurrentShdrEx->next = NULL;
671 elElfDesc->ShdrEx = DmyShdrEx.next;
672 /*--------------------------------------------*/
673
674 ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
675
676 /*---------- Check and copy all sections ----------*/
677 PRINTDEBUG( "\nLoad to RAM:\n");
678 for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
679 /**/
680 CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i);
681 // PRINTDEBUG( "section:%d sh_flag=0x%x\n", i, CurrentShdrEx->Shdr.sh_flags);
682 // PRINTDEBUG( "section:%d sh_type=0x%x\n", i, CurrentShdrEx->Shdr.sh_type);
683
684 if( CurrentShdrEx->debug_flag == 1) { /*When it is debugging information*/
685 PRINTDEBUG( "skip debug-section %02x\n", i);
686 }else{ /*When not debugging information*/
687 BOOL bLocate = FALSE;
688
689 /* .text section */
690 if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))&&
691 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
692 //Copy to memory
693 CurrentShdrEx->loaded_adr = (u32)
694 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
695 bLocate = TRUE;
696 }
697 /* .data, .data1 section (Initialized data) */
698 else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
699 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
700 //Copy to memory
701 CurrentShdrEx->loaded_adr = (u32)
702 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
703 bLocate = TRUE;
704 }
705 /* bss section */
706 else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
707 (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) {
708 //Do not copy
709 CurrentShdrEx->loaded_adr = (u32)
710 ELi_AllocSectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
711 bLocate = TRUE;
712 }
713 /* .rodata, .rodata1 section */
714 else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&&
715 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
716 //Copy to memory
717 CurrentShdrEx->loaded_adr = (u32)
718 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
719 bLocate = TRUE;
720 }
721
722 if (bLocate) {
723 if( CurrentShdrEx->loaded_adr == NULL) { //When failed in ELi_CopySectionToBuffer
724 ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
725 return( EL_RESULT_CANNOT_ACCESS_ELF);
726 }
727 (void)ELi_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, dll_fileid, elf_num, i, CurrentShdrEx->loaded_adr, (elElfDesc != i_eldesc_sim));
728 }
729
730 PRINTDEBUG( "section %02x relocated at %08x\n",
731 i, CurrentShdrEx->loaded_adr);
732 }
733 }
734 /* After copy ends */
735 ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED);
736 /*----------------------------------------------------*/
737
738 ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
739
740 /*---------- Publication of global symbols and relocating of local symbols ----------*/
741 PRINTDEBUG( "\nRelocate Symbols:\n");
742 for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
743 /**/
744 CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i);
745
746 if( CurrentShdrEx->debug_flag == 1) { /*When it is debugging information*/
747 }else{ /*When not debugging information*/
748
749 if( CurrentShdrEx->Shdr.sh_type == SHT_REL) {
750 /*Relocate*/
751 InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx,
752 CurrentShdrEx->Shdr.sh_info);
753 if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded
754 if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE)
755 return( (ELResult)(elElfDesc->result)); //EL_RESULT_NO_MORE_RESOURCE or EL_RESULT_UNSUPPORTED_ELF
756 }
757 #if (DEBUG_PRINT_ON == 1)
758 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
759 (CurrentShdrEx->Shdr.sh_entsize);
760
761 PRINTDEBUG( "num of REL = %x\n", num_of_entry);
762 PRINTDEBUG( "Section Header Info.\n");
763 PRINTDEBUG( "link : %x\n", CurrentShdrEx->Shdr.sh_link);
764 PRINTDEBUG( "info : %x\n", CurrentShdrEx->Shdr.sh_info);
765 PRINTDEBUG( " Offset Info Type Sym.Value Sym.Name\n");
766 offset = 0;
767 for( j=0; j<num_of_entry; j++) {
768 ELi_GetSent( elElfDesc, i, &(elElfDesc->Rel), offset, sizeof(Elf32_Rel));
769 ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr));
770 ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym),
771 (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rel.r_info)), sizeof(Elf32_Sym));
772 ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128);
773
774 PRINTDEBUG( "%08x ", elElfDesc->Rel.r_offset);
775 PRINTDEBUG( "%08x ", elElfDesc->Rel.r_info);
776 PRINTDEBUG( " ");
777 PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value);
778 PRINTDEBUG( sym_str);
779 PRINTDEBUG( "\n");
780 /*To next entry*/
781 offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
782 }
783 #endif
784 }
785 else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) {
786 /*Relocate*/
787 InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx,
788 CurrentShdrEx->Shdr.sh_info);
789 if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded
790 if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE)
791 return( EL_RESULT_NO_MORE_RESOURCE);
792 }
793
794 #if (DEBUG_PRINT_ON == 1)
795 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
796 (CurrentShdrEx->Shdr.sh_entsize);
797 PRINTDEBUG( "num of RELA = %x\n", num_of_entry);
798 PRINTDEBUG( "Section Header Info.\n");
799 PRINTDEBUG( "link : %x\n", CurrentShdrEx->Shdr.sh_link);
800 PRINTDEBUG( "info : %x\n", CurrentShdrEx->Shdr.sh_info);
801 PRINTDEBUG( " Offset Info Type Sym.Value Sym.Name\n");
802 offset = 0;
803 for( j=0; j<num_of_entry; j++) {
804 ELi_GetSent( elElfDesc, i, &(elElfDesc->Rela), offset, sizeof(Elf32_Rel));
805 ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr));
806 ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym),
807 (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rela.r_info)), sizeof(Elf32_Sym));
808 ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128);
809
810 PRINTDEBUG( "%08x ", elElfDesc->Rela.r_offset);
811 PRINTDEBUG( "%08x ", elElfDesc->Rela.r_info);
812 PRINTDEBUG( " ");
813 PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value);
814 PRINTDEBUG( sym_str);
815 PRINTDEBUG( "\n");
816 /*To next entry*/
817 offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
818 }
819 #endif
820 }
821 else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) {
822 /*Register global symbol in address table*/
823 if(ELi_GoPublicGlobalSym( elElfDesc, MYObject, i) == FALSE)
824 return( EL_RESULT_NO_MORE_RESOURCE);
825 }
826 }
827 }
828 /*Create in ELi_RelocateSym and ELi_GoPublicGlobalSym and release the used symbol list*/
829 ELi_FreeSymList( elElfDesc);
830
831 /*---------- Deallocate the ELShdrEx List ----------*/
832 CurrentShdrEx = elElfDesc->ShdrEx;
833 if( CurrentShdrEx) {
834 do {
835 FwdShdrEx = CurrentShdrEx;
836 CurrentShdrEx = CurrentShdrEx->next;
837 OSAPI_FREE( FwdShdrEx);
838 }while( CurrentShdrEx != NULL);
839 elElfDesc->ShdrEx = NULL;
840 }
841 /*-----------------------------------------*/
842
843 /*Flush cache before the DLL in RAM is called*/
844 #if (TARGET_ARM_V5 == 1)
845 OSAPI_FLUSHCACHEALL();
846 OSAPI_WAITCACHEBUF();
847 #endif
848
849 return( EL_RESULT_SUCCESS);
850 }
851
852 /*------------------------------------------------------
853 Resolve unresolved symbols using the address table
854 -----------------------------------------------------*/
ELi_ResolveAllLibrary(ELDesc * elElfDesc)855 ELProcess ELi_ResolveAllLibrary( ELDesc* elElfDesc)
856 {
857 ELAdrEntry* AdrEnt;
858 ELImportEntry* UnrEnt;
859 ELImportEntry* NextEnt;
860 // ELImportEntry* CurrentUnrEnt;
861 // ELImportEntry* FwdUnrEnt;
862 ELObject* ObjEnt;
863 ELObject* ExpObjEnt;
864 BOOL ret_val;
865
866 if( elElfDesc == NULL) {
867 return( EL_PROC_NOTHING);
868 }
869 ObjEnt = elElfDesc->ELObjectStart;
870 if( (ObjEnt == NULL)||((ObjEnt == elElfDesc->ELStaticObj)&&(ObjEnt->next == NULL))) {
871 return( EL_PROC_NOTHING); /* If there is no DLL */
872 }
873 while( ObjEnt != NULL) {
874 UnrEnt = (ELImportEntry*)ObjEnt->UnresolvedImportAdrEnt;
875 PRINTDEBUG( "\nResolve all symbols:\n");
876 while( UnrEnt != NULL) {
877 NextEnt = UnrEnt->next;
878 AdrEnt = elGetAdrEntry( elElfDesc, UnrEnt->sym_str, &ExpObjEnt); /*Search from address table*/
879 if( AdrEnt) { /*When found in address table*/
880 UnrEnt->S_ = (u32)(AdrEnt->adr);
881 UnrEnt->T_ = (u32)(AdrEnt->thumb_flag);
882 PRINTDEBUG( "\n symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_);
883 ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt); /*Resolve symbol*/
884 if( ret_val == FALSE) {
885 return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED. Is osPanic better? TODO: continuation
886 }else{
887 PRINTDEBUG( "%s ... ObjEnt:0x%x, ExpObjEnt:0x%x\n", UnrEnt->sym_str, ObjEnt, ExpObjEnt);
888 UnrEnt->Dlld = (struct ELObject*)ExpObjEnt; /*Register ObjEnt referenced in resolution*/
889 /* Change link from Unresolved to Resolved */
890 (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt);
891 ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt);
892 }
893 }else{ /*When not found in address table*/
894 if( elElfDesc != i_eldesc_sim) {
895 PRINTDEBUG( "\n ERROR! cannot find symbol : %s\n\n", UnrEnt->sym_str);
896 return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED. Is osPanic better? TODO: Continue
897 }
898 /*----- For simulation, assume it was forcefully resolved -----*/
899 UnrEnt->S_ = (u32)0;
900 UnrEnt->T_ = (u32)0;
901 ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt);
902 UnrEnt->Dlld = (struct ELObject*)NULL; /*Register ObjEnt referenced in resolution*/
903 /* Change link from Unresolved to Resolved */
904 (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt);
905 ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt);
906 /*--------------------------------------------------------*/
907 }
908 UnrEnt = NextEnt; /*To next unresolved entry*/
909 }
910 ELi_SetProcCode( NULL, ObjEnt, EL_PROC_RELOCATED);
911 ObjEnt->lib_size = ((u32)(ObjEnt->buf_current)) - ((u32)(ObjEnt->lib_start)); //There is the possibility that veneer was added, so update the size
912 ObjEnt = ObjEnt->next;
913 }
914 ELi_SetProcCode( elElfDesc, NULL, EL_PROC_RELOCATED);
915
916 /*TODO: When fixed, only the UnrEnt entry that could not be resolved here should be deleted*/
917 #if 0
918 /*---------- Deallocate the ELImportEntry List ----------*/
919 ELi_FreeImportTbl( &ELUnrEntStart);
920 /*-------------------------------------------*/
921 #endif
922 /*Deallocate the veneer linked list*/
923 // (void)ELi_FreeVenTbl();
924
925 /*Flush cache before the DLL in RAM is called*/
926 #if (TARGET_ARM_V5 == 1)
927 OSAPI_FLUSHCACHEALL();
928 OSAPI_WAITCACHEBUF();
929 #endif
930
931 return EL_PROC_RELOCATED;
932 }
933
934
935 /*------------------------------------------------------
936 Unlink the object
937 -----------------------------------------------------*/
ELi_Unlink(ELDesc * elElfDesc,ELDlld my_dlld)938 BOOL ELi_Unlink( ELDesc* elElfDesc, ELDlld my_dlld)
939 {
940 ELObject* MYObject;
941 ELObject* ObjEnt;
942 ELImportEntry* ResEnt;
943 ELImportEntry* NextEnt;
944 u32 file_id;
945
946 if( elElfDesc == NULL) {
947 return( FALSE);
948 }
949
950 if( my_dlld == 0) {
951 ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_INVALID_PARAMETER);
952 return( FALSE);
953 }
954
955 /* Object to unlink */
956 MYObject = (ELObject*)my_dlld;
957
958 /* Get the file ID of the object to unlink */
959 file_id = MYObject->file_id;
960
961 #if 0
962 /* Hide all export information */
963 if( MYObject->ExportAdrEnt) {
964 MYObject->HiddenAdrEnt = MYObject->ExportAdrEnt;
965 MYObject->ExportAdrEnt = NULL;
966 }
967 #else
968 /* Clear all export information */
969 elFreeAdrTbl( &(MYObject->ExportAdrEnt));
970 #endif
971
972 /* Reference other objects and make the resolved portions unresolved */
973 ObjEnt = elElfDesc->ELObjectStart;
974 while( ObjEnt != NULL) {
975 ResEnt = ObjEnt->ResolvedImportAdrEnt;
976 while( ResEnt != NULL) {
977 NextEnt = ResEnt->next;
978 PRINTDEBUG( "Compare ObjEnt:0x%x, ExpObjEnt:0x%x\n", ResEnt->Dlld, MYObject);
979 if( ResEnt->Dlld == (struct ELObject*)MYObject) {
980 PRINTDEBUG( "Unlink from ObjEnt:0x%x, ExpObjEnt:0x%x\n", ObjEnt, MYObject);
981 /* Link from Resolved to Unresolved */
982 (void)ELi_ExtractImportEntry( &(ObjEnt->ResolvedImportAdrEnt), ResEnt);
983 ELi_AddImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), ResEnt);
984 ResEnt->Dlld = NULL;
985 }
986 ResEnt = NextEnt;
987 }
988 ObjEnt = ObjEnt->next;
989 }
990
991 /*Do not destroy import information or self*/
992
993
994 /*Destroy the veneer table*/
995 (void)ELi_FreeVenTbl( elElfDesc, MYObject); /*Deallocate the veneer linked list*/
996
997 ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_NOTHING);
998
999 ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
1000 (void)ELi_UNREGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, file_id, (elElfDesc != i_eldesc_sim));
1001 ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
1002
1003 return( TRUE);
1004 }
1005
1006
1007 /*------------------------------------------------------
1008 Deallocate all object lists
1009 -----------------------------------------------------*/
ELi_FreeObject(ELObject ** ELObjEntStart)1010 static void ELi_FreeObject( ELObject** ELObjEntStart)
1011 {
1012 ELObject* FwdObjEnt;
1013 ELObject* CurrentObjEnt;
1014
1015 /*---------- Deallocate the ELObject List ----------*/
1016 CurrentObjEnt = (*ELObjEntStart);
1017 if( CurrentObjEnt) {
1018 do {
1019 FwdObjEnt = CurrentObjEnt;
1020 CurrentObjEnt = CurrentObjEnt->next;
1021 /**/
1022 elFreeAdrTbl( &(FwdObjEnt->ExportAdrEnt));
1023 elFreeAdrTbl( &(FwdObjEnt->HiddenAdrEnt));
1024 ELi_FreeImportTbl( &(FwdObjEnt->ResolvedImportAdrEnt));
1025 ELi_FreeImportTbl( &(FwdObjEnt->UnresolvedImportAdrEnt));
1026 OSAPI_FREE( FwdObjEnt);
1027 }while( CurrentObjEnt != NULL);
1028 (*ELObjEntStart) = NULL;
1029 }
1030 /*----------------------------------*/
1031 }
1032
1033
1034 /*------------------------------------------------------
1035 Check whether there are unresolved external references remaining in the object
1036 -----------------------------------------------------*/
EL_IsResolved(ELDlld my_dlld)1037 BOOL EL_IsResolved( ELDlld my_dlld)
1038 {
1039 ELObject* MYObject;
1040
1041 if( my_dlld == 0) {
1042 return( FALSE);
1043 }
1044
1045 MYObject = (ELObject*)my_dlld;
1046 /*TODO: Check whether MYObject is linked to the list*/
1047 if( (MYObject->stat != 0)&&(MYObject->UnresolvedImportAdrEnt == NULL)) {
1048 return( TRUE);
1049 }else{
1050 return( FALSE);
1051 }
1052 }
1053
1054
1055 /*------------------------------------------------------
1056 Initializes the object management structure.
1057 -----------------------------------------------------*/
ELi_InitObject(ELObject * MYObject)1058 static void ELi_InitObject( ELObject* MYObject)
1059 {
1060 MYObject->next = NULL;
1061 MYObject->lib_size = 0;
1062 MYObject->ExportAdrEnt = NULL;
1063 MYObject->HiddenAdrEnt = NULL;
1064 MYObject->ResolvedImportAdrEnt = NULL;
1065 MYObject->UnresolvedImportAdrEnt = NULL;
1066 MYObject->ELVenEntStart = NULL;
1067 MYObject->ELV4tVenEntStart = NULL;
1068 MYObject->stat = 0;
1069
1070 MYObject->process = (u32)EL_PROC_INITIALIZED;
1071 MYObject->result = (u32)EL_RESULT_SUCCESS;
1072 }
1073
1074
1075 /*------------------------------------------------------
1076 Delete entry from the object table
1077 -----------------------------------------------------*/
elRemoveObjEntry(ELObject ** StartEnt,ELObject * ObjEnt)1078 BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt)
1079 {
1080 ELObject DmyObjEnt;
1081 ELObject* CurObjEnt;
1082
1083 DmyObjEnt.next = (*StartEnt);
1084 CurObjEnt = &DmyObjEnt;
1085
1086 while( CurObjEnt->next != ObjEnt) {
1087 if( CurObjEnt->next == NULL) {
1088 return FALSE;
1089 }else{
1090 CurObjEnt = (ELObject*)CurObjEnt->next;
1091 }
1092 }
1093
1094 /*Relink link list*/
1095 CurObjEnt->next = ObjEnt->next;
1096 (*StartEnt) = DmyObjEnt.next;
1097
1098 /*Deallocate*/
1099 elFreeAdrTbl( &(ObjEnt->ExportAdrEnt));
1100 elFreeAdrTbl( &(ObjEnt->HiddenAdrEnt));
1101 ELi_FreeImportTbl( &(ObjEnt->ResolvedImportAdrEnt));
1102 ELi_FreeImportTbl( &(ObjEnt->UnresolvedImportAdrEnt));
1103 ELi_InitObject( ObjEnt); //stat = 0;
1104 OSAPI_FREE( ObjEnt);
1105
1106 return TRUE;
1107 }
1108
1109 /*------------------------------------------------------
1110 Add entry to object table
1111 -----------------------------------------------------*/
elAddObjEntry(ELObject ** StartEnt,ELObject * ObjEnt)1112 static void elAddObjEntry( ELObject** StartEnt, ELObject* ObjEnt)
1113 {
1114 ELObject DmyObjEnt;
1115 ELObject* CurObjEnt;
1116
1117 if( (*StartEnt) == NULL) {
1118 (*StartEnt) = ObjEnt;
1119 }else{
1120 DmyObjEnt.next = (*StartEnt);
1121 CurObjEnt = &DmyObjEnt;
1122
1123 while( CurObjEnt->next != NULL) {
1124 CurObjEnt = (ELObject*)CurObjEnt->next;
1125 }
1126 CurObjEnt->next = (void*)ObjEnt;
1127 }
1128 ObjEnt->next = NULL;
1129 }
1130
1131
1132 /*------------------------------------------------------
1133 Delete entry from address table
1134 -----------------------------------------------------*/
1135 #if 0
1136 BOOL elRemoveAdrEntry( ELAdrEntry* AdrEnt)
1137 {
1138 ELAdrEntry DmyAdrEnt;
1139 ELAdrEntry* CurrentAdrEnt;
1140
1141 DmyAdrEnt.next = ELAdrEntStart;
1142 CurrentAdrEnt = &DmyAdrEnt;
1143
1144 while( CurrentAdrEnt->next != AdrEnt) {
1145 if( CurrentAdrEnt->next == NULL) {
1146 return FALSE;
1147 }else{
1148 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1149 }
1150 }
1151
1152 /*Relink link list*/
1153 CurrentAdrEnt->next = AdrEnt->next;
1154 ELAdrEntStart = DmyAdrEnt.next;
1155
1156 /*Deallocate*/
1157 OSAPI_FREE( AdrEnt);
1158
1159 return TRUE;
1160 }
1161 #endif
1162
1163 /*------------------------------------------------------
1164 Add entry to address table
1165 -----------------------------------------------------*/
elAddAdrEntry(ELAdrEntry ** ELAdrEntStart,ELAdrEntry * AdrEnt)1166 void elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt)
1167 {
1168 ELAdrEntry DmyAdrEnt;
1169 ELAdrEntry* CurrentAdrEnt;
1170
1171 if( (*ELAdrEntStart) == NULL) {
1172 (*ELAdrEntStart) = AdrEnt;
1173 }else{
1174 DmyAdrEnt.next = (*ELAdrEntStart);
1175 CurrentAdrEnt = &DmyAdrEnt;
1176
1177 while( CurrentAdrEnt->next != NULL) {
1178 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1179 }
1180 CurrentAdrEnt->next = (void*)AdrEnt;
1181 }
1182 AdrEnt->next = NULL;
1183 }
1184
1185 /*------------------------------------------------------
1186 Add entry from application to address table
1187 -----------------------------------------------------*/
ELi_Export(ELDesc * elElfDesc,ELAdrEntry * AdrEnt)1188 BOOL ELi_Export( ELDesc* elElfDesc, ELAdrEntry* AdrEnt)
1189 {
1190 ELAdrEntry DmyAdrEnt;
1191 ELAdrEntry* CurrentAdrEnt;
1192
1193 if( elElfDesc == NULL) {
1194 return( FALSE);
1195 }
1196 if( elElfDesc->ELStaticObj == NULL) {
1197 elElfDesc->ELStaticObj = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject));
1198 if(elElfDesc->ELStaticObj == NULL) {
1199 return( FALSE);
1200 }
1201 ELi_InitObject( elElfDesc->ELStaticObj);
1202 elAddObjEntry( &(elElfDesc->ELObjectStart), elElfDesc->ELStaticObj);
1203 }
1204
1205 if( !(elElfDesc->ELStaticObj->ExportAdrEnt)) {
1206 elElfDesc->ELStaticObj->ExportAdrEnt = (ELAdrEntry*)AdrEnt;
1207 }else{
1208 DmyAdrEnt.next = (ELAdrEntry*)elElfDesc->ELStaticObj->ExportAdrEnt;
1209 CurrentAdrEnt = &DmyAdrEnt;
1210
1211 while( CurrentAdrEnt->next != NULL) {
1212 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1213 }
1214 CurrentAdrEnt->next = (void*)AdrEnt;
1215 }
1216 AdrEnt->next = NULL;
1217 return( TRUE);
1218 }
1219
1220 /*------------------------------------------------------
1221 Add entry of static side to address table
1222 -----------------------------------------------------*/
1223 #ifndef SDK_TWL
EL_AddStaticSym(void)1224 SDK_WEAK_SYMBOL void EL_AddStaticSym( void)
1225 //__declspec(weak) void EL_AddStaticSym( void)
1226 #else
1227 SDK_WEAK_SYMBOL void EL_AddStaticSym( void)
1228 #endif
1229 {
1230 PRINTDEBUG( "please link file which is generated by \"makelst\".\n");
1231 while( 1) {};
1232 }
1233
1234 /*------------------------------------------------------
1235 Return entry corresponding to specified string from entire address table and set the object that exports the entry as ExpObEnt
1236
1237 -----------------------------------------------------*/
elGetAdrEntry(ELDesc * elElfDesc,const char * ent_name,ELObject ** ExpObjEnt)1238 ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt)
1239 {
1240 ELObject* ObjEnt;
1241 ELAdrEntry* CurrentAdrEnt;
1242
1243 ObjEnt = elElfDesc->ELObjectStart;
1244 while( ObjEnt != NULL) {
1245 CurrentAdrEnt = ObjEnt->ExportAdrEnt;
1246 while( CurrentAdrEnt != NULL) {
1247 if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) {
1248 (*ExpObjEnt) = ObjEnt; //Specify OBJ that is exporting
1249 goto get_end;
1250 }
1251 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1252 }
1253 ObjEnt = ObjEnt->next;
1254 }
1255 (*ExpObjEnt) = NULL; //Nobody is exporting
1256 get_end:
1257 return CurrentAdrEnt;
1258 }
1259
1260 /*------------------------------------------------------
1261 Return address corresponding to specified string in address table
1262 -----------------------------------------------------*/
ELi_GetGlobalAdr(ELDesc * elElfDesc,ELDlld my_dlld,const char * ent_name)1263 void* ELi_GetGlobalAdr( ELDesc* elElfDesc, ELDlld my_dlld, const char* ent_name)
1264 {
1265 u32 adr;
1266 ELAdrEntry* CurrentAdrEnt;
1267 ELObject* DmyObjEnt;
1268
1269 if( elElfDesc == NULL) {
1270 return( 0);
1271 }
1272
1273 if( my_dlld == 0) { /*Search the entire table*/
1274 CurrentAdrEnt = elGetAdrEntry( elElfDesc, ent_name, &DmyObjEnt);
1275 }else{ /*Search specific objects*/
1276 CurrentAdrEnt = ((ELObject*)my_dlld)->ExportAdrEnt;
1277 while( CurrentAdrEnt != NULL) {
1278 if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) {
1279 break;
1280 }
1281 CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1282 }
1283 }
1284
1285 if( CurrentAdrEnt) {
1286 if( CurrentAdrEnt->thumb_flag) { //TODO: only for func_flag
1287 adr = (u32)(CurrentAdrEnt->adr) + 1;
1288 }else{
1289 adr = (u32)(CurrentAdrEnt->adr);
1290 }
1291 }else{
1292 adr = 0;
1293 }
1294
1295 return (void*)(adr);
1296 }
1297
1298
1299 /*------------------------------------------------------
1300 Deallocate all address tables
1301 -----------------------------------------------------*/
elFreeAdrTbl(ELAdrEntry ** ELAdrEntStart)1302 static void elFreeAdrTbl( ELAdrEntry** ELAdrEntStart)
1303 {
1304 ELAdrEntry* FwdAdrEnt;
1305 ELAdrEntry* CurrentAdrEnt;
1306
1307 /*---------- Deallocate the ELAdrEntry List ----------*/
1308 CurrentAdrEnt = (*ELAdrEntStart);
1309 if( CurrentAdrEnt) {
1310 do {
1311 FwdAdrEnt = CurrentAdrEnt;
1312 CurrentAdrEnt = CurrentAdrEnt->next;
1313 OSAPI_FREE( FwdAdrEnt->name); //Symbol name string
1314 OSAPI_FREE( FwdAdrEnt); //Structure itself
1315 }while( CurrentAdrEnt != NULL);
1316 (*ELAdrEntStart) = NULL;
1317 }
1318 /*------------------------------------*/
1319 }
1320
1321
1322 /*------------------------------------------------------
1323 Stub that reads data from the ELF object
1324 -----------------------------------------------------*/
ELi_ReadFile(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1325 static BOOL ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1326 {
1327 #pragma unused( file_base)
1328 if( FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET) == FALSE) {
1329 return( FALSE);
1330 }
1331 if( FS_ReadFile( file_struct, buf, (s32)(size)) == (s32)size) {
1332 return( TRUE);
1333 }else{
1334 return( FALSE);
1335 }
1336 }
1337
ELi_ReadMem(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1338 static BOOL ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1339 {
1340 #pragma unused(file_struct)
1341 OSAPI_CPUCOPY8( (void*)(file_base + file_offset),
1342 buf,
1343 size);
1344 return( TRUE);
1345 }
1346
ELi_ReadUsr(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1347 static BOOL ELi_ReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1348 {
1349 #pragma unused(file_struct)
1350 #pragma unused(file_base)
1351 if( i_elReadImage( file_offset, buf, size) == 0) {
1352 return( TRUE);
1353 }
1354 return( FALSE);
1355 }
1356
1357
1358 /*------------------------------------------------------
1359 Set of error codes/process codes
1360 Set ELResult when initial value is SUCCESS and an error occurs
1361 Set ELProcess when the initial value is INITIALIZED and in conjunction with progress
1362 -----------------------------------------------------*/
ELi_SetResultCode(ELDesc * elElfDesc,ELObject * MYObject,ELResult result)1363 void ELi_SetResultCode( ELDesc* elElfDesc, ELObject* MYObject, ELResult result)
1364 {
1365 if( elElfDesc != NULL) {
1366 elElfDesc->result = (u32)result;
1367 }
1368 if( MYObject != NULL) {
1369 MYObject->result = (u32)result;
1370 }
1371 }
1372
ELi_SetProcCode(ELDesc * elElfDesc,ELObject * MYObject,ELProcess process)1373 void ELi_SetProcCode( ELDesc* elElfDesc, ELObject* MYObject, ELProcess process)
1374 {
1375 if( elElfDesc != NULL) {
1376 elElfDesc->process = (u32)process;
1377 }
1378 if( MYObject != NULL) {
1379 MYObject->process = (u32)process;
1380 }
1381 }
1382
1383