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-12-15#$
14   $Rev: 9650 $
15   $Author: kitase_hirotake $
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 the 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 that archive in a buffer
142 static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, 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 function that reads 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 // Release 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   Initialize 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     /*--- Set memory allocation relationship  ---*/
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 defaut 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 defaut 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 that 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)299 ELDlld EL_LoadLibraryfromFile( ELDesc* elElfDesc, const char* FilePath, void* buf)
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, 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 that archive in a buffer
351 
352     elElfDesc: Header structure
353     readfunc: User function the reads object or archive files
354     buf: Buffer for loading
355  -----------------------------------------------------*/
EL_LoadLibrary(ELDesc * elElfDesc,ELReadImage readfunc,u32 len,void * buf)356 ELDlld EL_LoadLibrary( ELDesc* elElfDesc, ELReadImage readfunc, u32 len, void* buf)
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, 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 that archive in a buffer
381 
382     elElfDesc: Header structure
383     obj_image: Image address on RAM of object file or archive file
384     buf: Buffer for loading
385  -----------------------------------------------------*/
EL_LoadLibraryfromMem(ELDesc * elElfDesc,void * obj_image,u32 obj_len,void * buf)386 ELDlld EL_LoadLibraryfromMem( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf)
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, 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 that archive in a buffer
412 
413     elElfDesc: Header structure
414     obj_image: Image address on RAM of object file or archive file
415     buf: Buffer for loading
416  -----------------------------------------------------*/
ELi_LoadLibrary(ELDesc * elElfDesc,void * obj_image,u32 obj_len,void * buf,u32 dll_fileid)417 static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, 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     ArchHdr    ArHdr;
424     char       OBJMAG[8];
425     char       ELFMAG[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3};
426     ELObject*  MYObject;
427 
428     /*-------*/
429     if( elElfDesc->i_elReadStub == NULL) {
430         ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF);
431         return( 0);
432     }
433     /*-------*/
434 
435     /* Allocate individual object management structure */
436     MYObject = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject));
437     if(MYObject == NULL)
438         return 0;
439     ELi_InitObject( MYObject);
440     elAddObjEntry( &(elElfDesc->ELObjectStart), MYObject);
441 
442     elElfDesc->ar_head = obj_image;
443     image_pointer = 0;
444     MYObject->lib_start = buf;
445     MYObject->buf_current = buf;
446 
447     if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)obj_image, 0, 8) == FALSE) { /*Get the OBJ character string*/
448         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
449         return( 0);
450     }
451     /*--------------- For archive files  ---------------*/
452     if( OSAPI_STRNCMP( OBJMAG, ARMAG, 8) == 0) {
453         arch_size = sizeof( ArchHdr);
454         image_pointer += 8;                /*To first entry*/
455 
456         while( image_pointer < obj_len) {
457             if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4)
458                 == FALSE) {    /*Get the OBJ character string*/
459                 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
460                 break;
461             }
462             if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) {
463                 /*Reset initial values*/
464                 (void)ELi_ReInitDesc( elElfDesc);
465                 result = ELi_LoadObject( elElfDesc, MYObject, (void*)(image_pointer+arch_size), MYObject->buf_current, dll_fileid, elf_num);
466                 if( result != EL_RESULT_SUCCESS) {
467                     break;
468                 }
469                 elf_num++;
470             }else{
471             }
472             /*To next entry*/
473             if( elElfDesc->i_elReadStub( &ArHdr, elElfDesc->FileStruct, (u32)(obj_image), image_pointer, arch_size)
474                 == FALSE) {
475                 ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
476                 return( 0);
477             }
478             image_pointer += arch_size + AR_GetEntrySize( &ArHdr);
479         }
480     }else{/*--------------- For ELF files  ---------------*/
481         if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) {
482             /*Reset initial values*/
483             (void)ELi_ReInitDesc( elElfDesc);
484             result = ELi_LoadObject( elElfDesc, MYObject, 0, MYObject->buf_current, dll_fileid, elf_num);
485             if( result != EL_RESULT_SUCCESS) {
486             }else{
487                 elf_num++;
488             }
489         }else{
490             ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF);
491         }
492     }
493     /*-------------------------------------------------------*/
494 
495     if( elf_num) {
496         if( OS_IsRunOnDebugger() == FALSE) {
497             (void)ELi_FreeVenTbl( elElfDesc, MYObject);    /*Release the veneer link list when not debugging*/
498         }
499         MYObject->stat = elf_num;
500         //When (MEMO)Segment was loaded, buf_current was not advanced, so it was not applied to lib_size
501         MYObject->lib_size = ((u32)(MYObject->buf_current)) - ((u32)(MYObject->lib_start));
502         PRINTDEBUG( "library size : 0x%x\n", MYObject->lib_size);
503         return( (ELDlld)MYObject);
504     }else{
505         /* Object could not be processed so structure was destroyed */
506         (void)elRemoveObjEntry( &(elElfDesc->ELObjectStart), MYObject);
507         return 0; //NULL
508     }
509 }
510 
511 /*------------------------------------------------------
512   Relocate ELF object to buffer
513 
514     elElfDesc: Header structure
515     MYObject: Individual object management structure
516     obj_offset: Offset from image address on object file RAM
517     buf: Buffer to load (TODO: Buffer overflow countermeasure)
518  -----------------------------------------------------*/
ELi_LoadObject(ELDesc * elElfDesc,ELObject * MYObject,void * obj_offset,void * buf,u32 dll_fileid,u32 elf_num)519 static ELResult ELi_LoadObject( ELDesc* elElfDesc, ELObject* MYObject, void* obj_offset, void* buf, u32 dll_fileid, u32 elf_num)
520 {
521     ELResult ret_val;
522 
523     /* Check initialization of ELDesc */
524     if( elElfDesc->process != (u32)EL_PROC_INITIALIZED) {
525         return( EL_RESULT_FAILURE);
526     }
527     /* Get ELF header */
528     if( elElfDesc->i_elReadStub( &(elElfDesc->CurrentEhdr), elElfDesc->FileStruct,
529                                 (u32)(elElfDesc->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr))
530         == FALSE) {
531         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
532         return( EL_RESULT_CANNOT_ACCESS_ELF);
533     }
534 
535     /* Build ELDesc structure */
536     elElfDesc->elf_offset = obj_offset;
537     elElfDesc->shentsize = elElfDesc->CurrentEhdr.e_shentsize;
538     elElfDesc->entry_adr = elElfDesc->CurrentEhdr.e_entry;
539 
540     /* Process for each ELF file type */
541     switch( elElfDesc->CurrentEhdr.e_type) {
542 
543       case ET_NONE:
544         PRINTDEBUG( "ERROR : Elf type \"ET_NONE\"\n");
545         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF);
546         ret_val = EL_RESULT_UNSUPPORTED_ELF;
547         break;
548 
549       case ET_REL:  /* X to execute; O to relocate */
550         PRINTDEBUG( "Elf type \"ET_REL\"\n");
551         if( buf == NULL) {        /* Buffer NULL check */
552             ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_NO_MORE_RESOURCE);
553             return EL_RESULT_NO_MORE_RESOURCE;
554         }
555         ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num);
556         break;
557 
558       case ET_EXEC: /* O to execute; X to relocate */
559         PRINTDEBUG( "Elf type \"ET_EXEC\"\n");
560         ret_val = elLoadSegments( elElfDesc, MYObject);
561         break;
562 
563       case ET_DYN:  /* O to execute; O to relocate (TODO: untested)*/
564         PRINTDEBUG( "Elf type \"ET_DYN\"\n");
565         if( buf == NULL) { //Handle as ET_EXEC when the load address is not specified
566             ret_val = elLoadSegments( elElfDesc, MYObject);
567         }else{             //Handle as ET_REL when the load address is not specified
568             ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num);
569         }
570         break;
571 
572       case ET_CORE:
573         PRINTDEBUG( "ERROR : Elf type \"ET_CORE\"\n");
574         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF);
575         ret_val = EL_RESULT_UNSUPPORTED_ELF;
576         break;
577 
578       default:
579         PRINTDEBUG( "ERROR : Invalid Elf type 0x%x\n",
580                     elElfDesc->CurrentEhdr.e_type);
581         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF);
582         ret_val = EL_RESULT_INVALID_ELF;
583         break;
584     }
585 
586     return( ret_val);
587 }
588 
589 
590 /*------------------------------------------------------
591   Check and copy all segments
592 
593     elElfDesc: Header structure
594  -----------------------------------------------------*/
elLoadSegments(ELDesc * elElfDesc,ELObject * MYObject)595 static ELResult elLoadSegments( ELDesc* elElfDesc, ELObject* MYObject)
596 {
597     u16        i;
598     //u32        load_start;
599     Elf32_Phdr CurrentPhdr;
600 
601     for( i=0; i<(elElfDesc->CurrentEhdr.e_phnum); i++) {
602         /*Copy program header*/
603         ELi_GetPhdr( elElfDesc, i, &CurrentPhdr);
604 
605         if( CurrentPhdr.p_type == PT_LOAD) {
606             /*If loadable segment, load to memory*/
607             if( ELi_CopySegmentToBuffer( elElfDesc, MYObject, &CurrentPhdr) == NULL) {
608                 return( EL_RESULT_CANNOT_ACCESS_ELF);
609             }
610         }else{
611             PRINTDEBUG( "WARNING : skip segment (type = 0x%x)\n",
612                         CurrentPhdr.p_type);
613         }
614     }
615     ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED);
616     return( EL_RESULT_SUCCESS);
617 }
618 
619 
620 /*------------------------------------------------------
621   Check and copy all sections
622 
623     elElfDesc: Header structure
624  -----------------------------------------------------*/
elLoadSections(ELDesc * elElfDesc,ELObject * MYObject,u32 dll_fileid,u32 elf_num)625 static ELResult elLoadSections( ELDesc* elElfDesc, ELObject* MYObject, u32 dll_fileid, u32 elf_num)
626 {
627     u16         i;
628     ELShdrEx*   FwdShdrEx;
629     ELShdrEx*   CurrentShdrEx;
630     ELShdrEx*   InfoShdrEx;      //For example, consider CurrentShdrEx as .text for rel.text
631     ELShdrEx    DmyShdrEx;
632 #if (DEBUG_PRINT_ON == 1)
633     u16         j;
634     u32         num_of_entry;
635     char        sym_str[128];    //For debug print
636     u32         offset;          //For debug print
637 #endif
638 
639     /*---------- Create ELShdrEx List  ----------*/
640     CurrentShdrEx = &DmyShdrEx;
641     for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
642         CurrentShdrEx->next = ELi_Malloc( elElfDesc, MYObject, sizeof(ELShdrEx));
643         if(CurrentShdrEx->next == NULL) {
644             return( EL_RESULT_NO_MORE_RESOURCE);
645         }
646         CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
647         OSAPI_CPUFILL8( CurrentShdrEx, 0, sizeof(ELShdrEx));    //Zero-clear
648 
649         /*Set flag to distinguish whether this is debugging information*/
650         if( ELi_ShdrIsDebug( elElfDesc, i) == TRUE) {    /*When it is debugging information*/
651             CurrentShdrEx->debug_flag = 1;
652         }else{                                           /*When not debugging information*/
653             /*Copy section header*/
654             ELi_GetShdr( elElfDesc, i, &(CurrentShdrEx->Shdr));
655             CurrentShdrEx->debug_flag = 0;
656         }
657     }
658     CurrentShdrEx->next = NULL;
659     elElfDesc->ShdrEx = DmyShdrEx.next;
660     /*--------------------------------------------*/
661 
662     ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
663 
664     /*---------- Check and copy all sections  ----------*/
665     PRINTDEBUG( "\nLoad to RAM:\n");
666     for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
667         /**/
668         CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i);
669 //        PRINTDEBUG( "section:%d sh_flag=0x%x\n", i, CurrentShdrEx->Shdr.sh_flags);
670 //        PRINTDEBUG( "section:%d sh_type=0x%x\n", i, CurrentShdrEx->Shdr.sh_type);
671 
672         if( CurrentShdrEx->debug_flag == 1) {              /*When it is debugging information*/
673             PRINTDEBUG( "skip debug-section %02x\n", i);
674         }else{                                             /*When not debugging information*/
675             BOOL bLocate = FALSE;
676 
677             /* .text section */
678             if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))&&
679                 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
680                 //Copy to memory
681                 CurrentShdrEx->loaded_adr = (u32)
682                                 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
683                 bLocate = TRUE;
684             }
685             /* .data, .data1 section (Initialized data) */
686             else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
687                 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
688                 //Copy to memory
689                 CurrentShdrEx->loaded_adr = (u32)
690                                 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
691                 bLocate = TRUE;
692             }
693             /* bss section */
694             else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&&
695                 (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) {
696                 //Do not copy
697                 CurrentShdrEx->loaded_adr = (u32)
698                                 ELi_AllocSectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
699                 bLocate = TRUE;
700             }
701             /* .rodata, .rodata1 section*/
702             else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&&
703                 (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) {
704                 //Copy to memory
705                 CurrentShdrEx->loaded_adr = (u32)
706                                 ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr));
707                 bLocate = TRUE;
708             }
709 
710             if (bLocate) {
711                 if( CurrentShdrEx->loaded_adr == NULL) { //When failed in ELi_CopySectionToBuffer
712                     ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
713                     return( EL_RESULT_CANNOT_ACCESS_ELF);
714                 }
715                 (void)ELi_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, dll_fileid, elf_num, i, CurrentShdrEx->loaded_adr, (elElfDesc != i_eldesc_sim));
716             }
717 
718             PRINTDEBUG( "section %02x relocated at %08x\n",
719                         i, CurrentShdrEx->loaded_adr);
720         }
721     }
722     /* After copy ends */
723     ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED);
724     /*----------------------------------------------------*/
725 
726     ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
727 
728     /*---------- Publication of global symbols and relocating of local symbols ----------*/
729     PRINTDEBUG( "\nRelocate Symbols:\n");
730     for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) {
731         /**/
732         CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i);
733 
734         if( CurrentShdrEx->debug_flag == 1) {                /*When it is debugging information*/
735         }else{                                               /*When not debugging information*/
736 
737             if( CurrentShdrEx->Shdr.sh_type == SHT_REL) {
738                 /*Relocate*/
739                 InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx,
740                                                     CurrentShdrEx->Shdr.sh_info);
741                 if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded
742                     if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE)
743                         return( (ELResult)(elElfDesc->result)); //EL_RESULT_NO_MORE_RESOURCE or EL_RESULT_UNSUPPORTED_ELF
744                 }
745 #if (DEBUG_PRINT_ON == 1)
746                 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
747                                 (CurrentShdrEx->Shdr.sh_entsize);
748 
749                 PRINTDEBUG( "num of REL = %x\n", num_of_entry);
750                 PRINTDEBUG( "Section Header Info.\n");
751                 PRINTDEBUG( "link   : %x\n", CurrentShdrEx->Shdr.sh_link);
752                 PRINTDEBUG( "info   : %x\n", CurrentShdrEx->Shdr.sh_info);
753                 PRINTDEBUG( " Offset     Info    Type            Sym.Value  Sym.Name\n");
754                 offset = 0;
755                 for( j=0; j<num_of_entry; j++) {
756                     ELi_GetSent( elElfDesc, i, &(elElfDesc->Rel), offset, sizeof(Elf32_Rel));
757                     ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr));
758                     ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym),
759                                  (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rel.r_info)), sizeof(Elf32_Sym));
760                     ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128);
761 
762                     PRINTDEBUG( "%08x  ", elElfDesc->Rel.r_offset);
763                     PRINTDEBUG( "%08x ", elElfDesc->Rel.r_info);
764                     PRINTDEBUG( "                  ");
765                     PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value);
766                     PRINTDEBUG( sym_str);
767                     PRINTDEBUG( "\n");
768                     /*To next entry*/
769                     offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
770                 }
771 #endif
772             }
773             else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) {
774                 /*Relocate*/
775                 InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx,
776                                                     CurrentShdrEx->Shdr.sh_info);
777                 if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded
778                     if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE)
779                         return( EL_RESULT_NO_MORE_RESOURCE);
780                 }
781 
782 #if (DEBUG_PRINT_ON == 1)
783                 num_of_entry = (CurrentShdrEx->Shdr.sh_size) /
784                                 (CurrentShdrEx->Shdr.sh_entsize);
785                 PRINTDEBUG( "num of RELA = %x\n", num_of_entry);
786                 PRINTDEBUG( "Section Header Info.\n");
787                 PRINTDEBUG( "link   : %x\n", CurrentShdrEx->Shdr.sh_link);
788                 PRINTDEBUG( "info   : %x\n", CurrentShdrEx->Shdr.sh_info);
789                 PRINTDEBUG( " Offset     Info    Type            Sym.Value  Sym.Name\n");
790                 offset = 0;
791                 for( j=0; j<num_of_entry; j++) {
792                     ELi_GetSent( elElfDesc, i, &(elElfDesc->Rela), offset, sizeof(Elf32_Rel));
793                     ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr));
794                     ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym),
795                                  (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rela.r_info)), sizeof(Elf32_Sym));
796                     ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128);
797 
798                     PRINTDEBUG( "%08x  ", elElfDesc->Rela.r_offset);
799                     PRINTDEBUG( "%08x ", elElfDesc->Rela.r_info);
800                     PRINTDEBUG( "                  ");
801                     PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value);
802                     PRINTDEBUG( sym_str);
803                     PRINTDEBUG( "\n");
804                     /*To next entry*/
805                     offset += (u32)(CurrentShdrEx->Shdr.sh_entsize);
806                 }
807 #endif
808             }
809             else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) {
810                 /*Register global symbol in address table*/
811                 if(ELi_GoPublicGlobalSym( elElfDesc, MYObject, i) == FALSE)
812                     return( EL_RESULT_NO_MORE_RESOURCE);
813             }
814         }
815     }
816     /*Create in ELi_RelocateSym and ELi_GoPublicGlobalSym & and release the used symbol list*/
817     ELi_FreeSymList( elElfDesc);
818 
819     /*---------- Free the ELShdrEx List  ----------*/
820     CurrentShdrEx = elElfDesc->ShdrEx;
821     if( CurrentShdrEx) {
822         do {
823             FwdShdrEx = CurrentShdrEx;
824             CurrentShdrEx = CurrentShdrEx->next;
825             OSAPI_FREE( FwdShdrEx);
826         }while( CurrentShdrEx != NULL);
827         elElfDesc->ShdrEx = NULL;
828     }
829     /*-----------------------------------------*/
830 
831     /*Flush cache before DLL is called on RAM*/
832 #if (TARGET_ARM_V5 == 1)
833     OSAPI_FLUSHCACHEALL();
834     OSAPI_WAITCACHEBUF();
835 #endif
836 
837     return( EL_RESULT_SUCCESS);
838 }
839 
840 /*------------------------------------------------------
841   Resolve unresolved symbols using the address table
842  -----------------------------------------------------*/
ELi_ResolveAllLibrary(ELDesc * elElfDesc)843 ELProcess ELi_ResolveAllLibrary( ELDesc* elElfDesc)
844 {
845     ELAdrEntry*       AdrEnt;
846     ELImportEntry*    UnrEnt;
847     ELImportEntry*    NextEnt;
848 //    ELImportEntry*    CurrentUnrEnt;
849 //    ELImportEntry*    FwdUnrEnt;
850     ELObject*         ObjEnt;
851     ELObject*         ExpObjEnt;
852     BOOL              ret_val;
853 
854     if( elElfDesc == NULL) {
855         return( EL_PROC_NOTHING);
856     }
857     ObjEnt = elElfDesc->ELObjectStart;
858     if( (ObjEnt == NULL)||((ObjEnt == elElfDesc->ELStaticObj)&&(ObjEnt->next == NULL))) {
859         return( EL_PROC_NOTHING); /* If there is no dll */
860     }
861     while( ObjEnt != NULL) {
862         UnrEnt = (ELImportEntry*)ObjEnt->UnresolvedImportAdrEnt;
863         PRINTDEBUG( "\nResolve all symbols:\n");
864         while( UnrEnt != NULL) {
865             NextEnt = UnrEnt->next;
866             AdrEnt = elGetAdrEntry( elElfDesc, UnrEnt->sym_str, &ExpObjEnt);        /*Search from address table*/
867             if( AdrEnt) {                                    /*When found in address table*/
868                 UnrEnt->S_ = (u32)(AdrEnt->adr);
869                 UnrEnt->T_ = (u32)(AdrEnt->thumb_flag);
870                 PRINTDEBUG( "\n symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_);
871                 ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt);           /*Resolve symbol*/
872                 if( ret_val == FALSE) {
873                     return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED Is osPanic better? TODO: continuation
874                 }else{
875                     PRINTDEBUG( "%s ... ObjEnt:0x%x, ExpObjEnt:0x%x\n", UnrEnt->sym_str, ObjEnt, ExpObjEnt);
876                     UnrEnt->Dlld = (struct ELObject*)ExpObjEnt;           /*Register ObjEnt referenced in resolution*/
877                     /* Change link from Unresolved to Resolved */
878                     (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt);
879                     ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt);
880                 }
881             }else{                                           /*When not found in address table*/
882                 if( elElfDesc != i_eldesc_sim) {
883                     PRINTDEBUG( "\n ERROR! cannot find symbol : %s\n\n", UnrEnt->sym_str);
884                     return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED Is osPanic better? TODO: Continue
885                 }
886                 /*----- For simulation, assume it was forcefully resolved -----*/
887                 UnrEnt->S_ = (u32)0;
888                 UnrEnt->T_ = (u32)0;
889                 ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt);
890                 UnrEnt->Dlld = (struct ELObject*)NULL;           /*Register ObjEnt referenced in resolution*/
891                 /* Change link from Unresolved to Resolved */
892                 (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt);
893                 ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt);
894                 /*--------------------------------------------------------*/
895             }
896             UnrEnt = NextEnt;                           /*To next unresolved entry*/
897         }
898         ELi_SetProcCode( NULL, ObjEnt, EL_PROC_RELOCATED);
899         ObjEnt->lib_size = ((u32)(ObjEnt->buf_current)) - ((u32)(ObjEnt->lib_start)); //There is the possibility that veneer was added, so update the size.
900         ObjEnt = ObjEnt->next;
901     }
902     ELi_SetProcCode( elElfDesc, NULL, EL_PROC_RELOCATED);
903 
904     /*TODO: When fixed, only the UnrEnt entry that could not be resolved here should be deleted*/
905 #if 0
906     /*---------- Free the ELImportEntry List  ----------*/
907     ELi_FreeImportTbl( &ELUnrEntStart);
908     /*-------------------------------------------*/
909 #endif
910     /*Release the veneer link request*/
911 //    (void)ELi_FreeVenTbl();
912 
913     /*Flush cache before DLL is called on RAM*/
914 #if (TARGET_ARM_V5 == 1)
915     OSAPI_FLUSHCACHEALL();
916     OSAPI_WAITCACHEBUF();
917 #endif
918 
919     return EL_PROC_RELOCATED;
920 }
921 
922 
923 /*------------------------------------------------------
924   Unlink the object
925  -----------------------------------------------------*/
ELi_Unlink(ELDesc * elElfDesc,ELDlld my_dlld)926 BOOL ELi_Unlink( ELDesc* elElfDesc, ELDlld my_dlld)
927 {
928     ELObject*      MYObject;
929     ELObject*      ObjEnt;
930     ELImportEntry* ResEnt;
931     ELImportEntry* NextEnt;
932     u32            file_id;
933 
934     if( elElfDesc == NULL) {
935         return( FALSE);
936     }
937 
938     if( my_dlld == 0) {
939         ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_INVALID_PARAMETER);
940         return( FALSE);
941     }
942 
943     /* Object to unlink */
944     MYObject = (ELObject*)my_dlld;
945 
946     /* Get the file ID of the object to unlink */
947     file_id = MYObject->file_id;
948 
949 #if 0
950     /* Hide all export information */
951     if( MYObject->ExportAdrEnt) {
952         MYObject->HiddenAdrEnt = MYObject->ExportAdrEnt;
953         MYObject->ExportAdrEnt = NULL;
954     }
955 #else
956     /* Clear all export information */
957     elFreeAdrTbl( &(MYObject->ExportAdrEnt));
958 #endif
959 
960     /* Reference other objects and make the resolved portions unresolved */
961     ObjEnt = elElfDesc->ELObjectStart;
962     while( ObjEnt != NULL) {
963         ResEnt = ObjEnt->ResolvedImportAdrEnt;
964         while( ResEnt != NULL) {
965             NextEnt = ResEnt->next;
966             PRINTDEBUG( "Compare ObjEnt:0x%x, ExpObjEnt:0x%x\n", ResEnt->Dlld, MYObject);
967             if( ResEnt->Dlld == (struct ELObject*)MYObject) {
968                 PRINTDEBUG( "Unlink from ObjEnt:0x%x, ExpObjEnt:0x%x\n", ObjEnt, MYObject);
969                 /* Link from Resolved to Unresolved */
970                 (void)ELi_ExtractImportEntry( &(ObjEnt->ResolvedImportAdrEnt), ResEnt);
971                 ELi_AddImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), ResEnt);
972                 ResEnt->Dlld = NULL;
973             }
974             ResEnt = NextEnt;
975         }
976         ObjEnt = ObjEnt->next;
977     }
978 
979     /*Do not destroy import information or self*/
980 
981 
982     /*Destroy the veneer table*/
983     (void)ELi_FreeVenTbl( elElfDesc, MYObject);    /*Release the veneer link request*/
984 
985     ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_NOTHING);
986 
987     ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
988     (void)ELi_UNREGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, file_id, (elElfDesc != i_eldesc_sim));
989     ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim));
990 
991     return( TRUE);
992 }
993 
994 
995 /*------------------------------------------------------
996   Deallocate all object lists
997  -----------------------------------------------------*/
ELi_FreeObject(ELObject ** ELObjEntStart)998 static void ELi_FreeObject( ELObject** ELObjEntStart)
999 {
1000     ELObject* FwdObjEnt;
1001     ELObject* CurrentObjEnt;
1002 
1003     /*---------- Free the ELObject List  ----------*/
1004     CurrentObjEnt = (*ELObjEntStart);
1005     if( CurrentObjEnt) {
1006         do {
1007             FwdObjEnt = CurrentObjEnt;
1008             CurrentObjEnt = CurrentObjEnt->next;
1009             /**/
1010             elFreeAdrTbl( &(FwdObjEnt->ExportAdrEnt));
1011             elFreeAdrTbl( &(FwdObjEnt->HiddenAdrEnt));
1012             ELi_FreeImportTbl( &(FwdObjEnt->ResolvedImportAdrEnt));
1013             ELi_FreeImportTbl( &(FwdObjEnt->UnresolvedImportAdrEnt));
1014             OSAPI_FREE( FwdObjEnt);
1015         }while( CurrentObjEnt != NULL);
1016         (*ELObjEntStart) = NULL;
1017     }
1018     /*----------------------------------*/
1019 }
1020 
1021 
1022 /*------------------------------------------------------
1023   Check whether there are unresolved external references remaining in the object
1024  -----------------------------------------------------*/
EL_IsResolved(ELDlld my_dlld)1025 BOOL EL_IsResolved( ELDlld my_dlld)
1026 {
1027     ELObject* MYObject;
1028 
1029     if( my_dlld == 0) {
1030         return( FALSE);
1031     }
1032 
1033     MYObject = (ELObject*)my_dlld;
1034     /*TODO: Check whether MYObject is linked to the list*/
1035     if( (MYObject->stat != 0)&&(MYObject->UnresolvedImportAdrEnt == NULL)) {
1036         return( TRUE);
1037     }else{
1038         return( FALSE);
1039     }
1040 }
1041 
1042 
1043 /*------------------------------------------------------
1044   Initializes the object management structure.
1045  -----------------------------------------------------*/
ELi_InitObject(ELObject * MYObject)1046 static void ELi_InitObject( ELObject* MYObject)
1047 {
1048     MYObject->next = NULL;
1049     MYObject->lib_size = 0;
1050     MYObject->ExportAdrEnt = NULL;
1051     MYObject->HiddenAdrEnt = NULL;
1052     MYObject->ResolvedImportAdrEnt = NULL;
1053     MYObject->UnresolvedImportAdrEnt = NULL;
1054     MYObject->ELVenEntStart = NULL;
1055     MYObject->ELV4tVenEntStart = NULL;
1056     MYObject->stat = 0;
1057 
1058     MYObject->process = (u32)EL_PROC_INITIALIZED;
1059     MYObject->result = (u32)EL_RESULT_SUCCESS;
1060 }
1061 
1062 
1063 /*------------------------------------------------------
1064   Delete entry from the object table
1065  -----------------------------------------------------*/
elRemoveObjEntry(ELObject ** StartEnt,ELObject * ObjEnt)1066 BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt)
1067 {
1068     ELObject  DmyObjEnt;
1069     ELObject* CurObjEnt;
1070 
1071     DmyObjEnt.next = (*StartEnt);
1072     CurObjEnt      = &DmyObjEnt;
1073 
1074     while( CurObjEnt->next != ObjEnt) {
1075         if( CurObjEnt->next == NULL) {
1076             return FALSE;
1077         }else{
1078             CurObjEnt = (ELObject*)CurObjEnt->next;
1079         }
1080     }
1081 
1082     /*Relink link list*/
1083     CurObjEnt->next = ObjEnt->next;
1084     (*StartEnt) = DmyObjEnt.next;
1085 
1086     /*Free*/
1087     elFreeAdrTbl( &(ObjEnt->ExportAdrEnt));
1088     elFreeAdrTbl( &(ObjEnt->HiddenAdrEnt));
1089     ELi_FreeImportTbl( &(ObjEnt->ResolvedImportAdrEnt));
1090     ELi_FreeImportTbl( &(ObjEnt->UnresolvedImportAdrEnt));
1091     ELi_InitObject( ObjEnt); //stat = 0;
1092     OSAPI_FREE( ObjEnt);
1093 
1094     return TRUE;
1095 }
1096 
1097 /*------------------------------------------------------
1098   Add entry to object table
1099  -----------------------------------------------------*/
elAddObjEntry(ELObject ** StartEnt,ELObject * ObjEnt)1100 static void elAddObjEntry( ELObject** StartEnt, ELObject* ObjEnt)
1101 {
1102     ELObject  DmyObjEnt;
1103     ELObject* CurObjEnt;
1104 
1105     if( (*StartEnt) == NULL) {
1106         (*StartEnt) = ObjEnt;
1107     }else{
1108         DmyObjEnt.next = (*StartEnt);
1109         CurObjEnt      = &DmyObjEnt;
1110 
1111         while( CurObjEnt->next != NULL) {
1112             CurObjEnt = (ELObject*)CurObjEnt->next;
1113         }
1114         CurObjEnt->next = (void*)ObjEnt;
1115     }
1116     ObjEnt->next = NULL;
1117 }
1118 
1119 
1120 /*------------------------------------------------------
1121   Delete entry from address table
1122  -----------------------------------------------------*/
1123 #if 0
1124 BOOL elRemoveAdrEntry( ELAdrEntry* AdrEnt)
1125 {
1126     ELAdrEntry  DmyAdrEnt;
1127     ELAdrEntry* CurrentAdrEnt;
1128 
1129     DmyAdrEnt.next = ELAdrEntStart;
1130     CurrentAdrEnt = &DmyAdrEnt;
1131 
1132     while( CurrentAdrEnt->next != AdrEnt) {
1133         if( CurrentAdrEnt->next == NULL) {
1134             return FALSE;
1135         }else{
1136             CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1137         }
1138     }
1139 
1140     /*Relink link list*/
1141     CurrentAdrEnt->next = AdrEnt->next;
1142     ELAdrEntStart = DmyAdrEnt.next;
1143 
1144     /*Free*/
1145     OSAPI_FREE( AdrEnt);
1146 
1147     return TRUE;
1148 }
1149 #endif
1150 
1151 /*------------------------------------------------------
1152   Add entry to address table
1153  -----------------------------------------------------*/
elAddAdrEntry(ELAdrEntry ** ELAdrEntStart,ELAdrEntry * AdrEnt)1154 void elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt)
1155 {
1156     ELAdrEntry  DmyAdrEnt;
1157     ELAdrEntry* CurrentAdrEnt;
1158 
1159     if( (*ELAdrEntStart) == NULL) {
1160         (*ELAdrEntStart) = AdrEnt;
1161     }else{
1162         DmyAdrEnt.next = (*ELAdrEntStart);
1163         CurrentAdrEnt = &DmyAdrEnt;
1164 
1165         while( CurrentAdrEnt->next != NULL) {
1166             CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1167         }
1168         CurrentAdrEnt->next = (void*)AdrEnt;
1169     }
1170     AdrEnt->next = NULL;
1171 }
1172 
1173 /*------------------------------------------------------
1174   Add entry from application to address table
1175  -----------------------------------------------------*/
ELi_Export(ELDesc * elElfDesc,ELAdrEntry * AdrEnt)1176 BOOL ELi_Export( ELDesc* elElfDesc, ELAdrEntry* AdrEnt)
1177 {
1178     ELAdrEntry  DmyAdrEnt;
1179     ELAdrEntry* CurrentAdrEnt;
1180 
1181     if( elElfDesc == NULL) {
1182         return( FALSE);
1183     }
1184     if( elElfDesc->ELStaticObj == NULL) {
1185         elElfDesc->ELStaticObj = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject));
1186         if(elElfDesc->ELStaticObj == NULL) {
1187             return( FALSE);
1188         }
1189         ELi_InitObject( elElfDesc->ELStaticObj);
1190         elAddObjEntry( &(elElfDesc->ELObjectStart), elElfDesc->ELStaticObj);
1191     }
1192 
1193     if( !(elElfDesc->ELStaticObj->ExportAdrEnt)) {
1194         elElfDesc->ELStaticObj->ExportAdrEnt = (ELAdrEntry*)AdrEnt;
1195     }else{
1196         DmyAdrEnt.next = (ELAdrEntry*)elElfDesc->ELStaticObj->ExportAdrEnt;
1197         CurrentAdrEnt = &DmyAdrEnt;
1198 
1199         while( CurrentAdrEnt->next != NULL) {
1200             CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1201         }
1202         CurrentAdrEnt->next = (void*)AdrEnt;
1203     }
1204     AdrEnt->next = NULL;
1205     return( TRUE);
1206 }
1207 
1208 /*------------------------------------------------------
1209   Add entry of static side to address table
1210  -----------------------------------------------------*/
1211 #ifndef SDK_TWL
EL_AddStaticSym(void)1212 SDK_WEAK_SYMBOL void EL_AddStaticSym( void)
1213 //__declspec(weak) void EL_AddStaticSym( void)
1214 #else
1215 SDK_WEAK_SYMBOL void EL_AddStaticSym( void)
1216 #endif
1217 {
1218     PRINTDEBUG( "please link file which is generated by \"makelst\".\n");
1219     while( 1) {};
1220 }
1221 
1222 /*------------------------------------------------------
1223   Return entry corresponding to specified character string from entire address table and set the object that is exporting that entry to the ExpObEnt
1224 
1225  -----------------------------------------------------*/
elGetAdrEntry(ELDesc * elElfDesc,const char * ent_name,ELObject ** ExpObjEnt)1226 ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt)
1227 {
1228     ELObject*   ObjEnt;
1229     ELAdrEntry* CurrentAdrEnt;
1230 
1231     ObjEnt = elElfDesc->ELObjectStart;
1232     while( ObjEnt != NULL) {
1233         CurrentAdrEnt = ObjEnt->ExportAdrEnt;
1234         while( CurrentAdrEnt != NULL) {
1235             if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) {
1236                 (*ExpObjEnt) = ObjEnt; //Specify object that is exporting
1237                 goto get_end;
1238             }
1239             CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1240         }
1241         ObjEnt = ObjEnt->next;
1242     }
1243     (*ExpObjEnt) = NULL; //Nobody is exporting
1244 get_end:
1245     return CurrentAdrEnt;
1246 }
1247 
1248 /*------------------------------------------------------
1249   Return address corresponding to specified string in address table
1250  -----------------------------------------------------*/
ELi_GetGlobalAdr(ELDesc * elElfDesc,ELDlld my_dlld,const char * ent_name)1251 void* ELi_GetGlobalAdr( ELDesc* elElfDesc, ELDlld my_dlld, const char* ent_name)
1252 {
1253     u32         adr;
1254     ELAdrEntry* CurrentAdrEnt;
1255     ELObject*   DmyObjEnt;
1256 
1257     if( elElfDesc == NULL) {
1258         return( 0);
1259     }
1260 
1261     if( my_dlld == 0) { /*Search from entirety*/
1262         CurrentAdrEnt = elGetAdrEntry( elElfDesc, ent_name, &DmyObjEnt);
1263     }else{              /*Search from specific objects*/
1264         CurrentAdrEnt = ((ELObject*)my_dlld)->ExportAdrEnt;
1265         while( CurrentAdrEnt != NULL) {
1266             if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) {
1267                 break;
1268             }
1269             CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next;
1270         }
1271     }
1272 
1273     if( CurrentAdrEnt) {
1274         if( CurrentAdrEnt->thumb_flag) { //TODO: only for func_flag
1275             adr = (u32)(CurrentAdrEnt->adr) + 1;
1276         }else{
1277             adr = (u32)(CurrentAdrEnt->adr);
1278         }
1279     }else{
1280         adr = 0;
1281     }
1282 
1283     return (void*)(adr);
1284 }
1285 
1286 
1287 /*------------------------------------------------------
1288   Release all address tables
1289  -----------------------------------------------------*/
elFreeAdrTbl(ELAdrEntry ** ELAdrEntStart)1290 static void elFreeAdrTbl( ELAdrEntry** ELAdrEntStart)
1291 {
1292     ELAdrEntry*    FwdAdrEnt;
1293     ELAdrEntry*    CurrentAdrEnt;
1294 
1295     /*---------- Free the ELAdrEntry List  ----------*/
1296     CurrentAdrEnt = (*ELAdrEntStart);
1297     if( CurrentAdrEnt) {
1298         do {
1299             FwdAdrEnt = CurrentAdrEnt;
1300             CurrentAdrEnt = CurrentAdrEnt->next;
1301             OSAPI_FREE( FwdAdrEnt->name);        //Symbol name character-string
1302             OSAPI_FREE( FwdAdrEnt);              //Structure itself
1303         }while( CurrentAdrEnt != NULL);
1304         (*ELAdrEntStart) = NULL;
1305     }
1306     /*------------------------------------*/
1307 }
1308 
1309 
1310 /*------------------------------------------------------
1311   Stub that reads data from the ELF object
1312  -----------------------------------------------------*/
ELi_ReadFile(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1313 static BOOL ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1314 {
1315 #pragma unused( file_base)
1316     if( FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET) == FALSE) {
1317         return( FALSE);
1318     }
1319     if( FS_ReadFile( file_struct, buf, (s32)(size)) == (s32)size) {
1320         return( TRUE);
1321     }else{
1322         return( FALSE);
1323     }
1324 }
1325 
ELi_ReadMem(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1326 static BOOL ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1327 {
1328 #pragma unused(file_struct)
1329     OSAPI_CPUCOPY8( (void*)(file_base + file_offset),
1330                     buf,
1331                     size);
1332     return( TRUE);
1333 }
1334 
ELi_ReadUsr(void * buf,void * file_struct,u32 file_base,u32 file_offset,u32 size)1335 static BOOL ELi_ReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size)
1336 {
1337 #pragma unused(file_struct)
1338 #pragma unused(file_base)
1339     if( i_elReadImage( file_offset, buf, size) == 0) {
1340         return( TRUE);
1341     }
1342     return( FALSE);
1343 }
1344 
1345 
1346 /*------------------------------------------------------
1347   Set of error codes/process codes
1348   Set ELResult when initial value is SUCCESS and an error occurs
1349   Set ELProcess when the initial value is INITIALIZED, and in conjunction with progress.
1350  -----------------------------------------------------*/
ELi_SetResultCode(ELDesc * elElfDesc,ELObject * MYObject,ELResult result)1351 void ELi_SetResultCode( ELDesc* elElfDesc, ELObject* MYObject, ELResult result)
1352 {
1353     if( elElfDesc != NULL) {
1354         elElfDesc->result = (u32)result;
1355     }
1356     if( MYObject != NULL) {
1357         MYObject->result = (u32)result;
1358     }
1359 }
1360 
ELi_SetProcCode(ELDesc * elElfDesc,ELObject * MYObject,ELProcess process)1361 void ELi_SetProcCode( ELDesc* elElfDesc, ELObject* MYObject, ELProcess process)
1362 {
1363     if( elElfDesc != NULL) {
1364         elElfDesc->process = (u32)process;
1365     }
1366     if( MYObject != NULL) {
1367         MYObject->process = (u32)process;
1368     }
1369 }
1370