1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - ELF Loader
3   File:     loader_subset.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 #ifdef SDK_TWL
20 #include <twl.h>
21 #else
22 #include <nitro.h>
23 #endif
24 
25 #include "loader_subset.h"
26 #include <istdbglibpriv.h>
27 
28 
29 /*------------------------------------------------------
30   External Variables
31  -----------------------------------------------------*/
32 //#ifndef SDK_TWL
33 //#else
34 extern ELAlloc   i_elAlloc;
35 extern ELFree    i_elFree;
36 //#endif
37 extern ELDesc* i_eldesc_sim;
38 
39 
40 /*------------------------------------------------------
41   External Functions
42  -----------------------------------------------------*/
43 extern BOOL        elRemoveAdrEntry( ELAdrEntry* AdrEnt);
44 extern void        elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt);
45 extern ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt);
46 
47 
48 /*------------------------------------------------------
49   Static functions
50  -----------------------------------------------------*/
51 static u32 el_veneer[3] = { //ARM code
52     0xE59FC000,    //(LDR r12,[PC])
53     0xE12FFF1C,    //(BX  r12)
54     0x00000000,    //(data)
55 };
56 
57 static u16 el_veneer_t[10] = { //Thumb code for v4t
58     0xB580,  //(PUSH {R7,LR})
59     0x46FE,  //(NOP)
60     0x46FE,  //(MOV LR, PC)
61     0x2707,  //(MOV R7, 7)
62     0x44BE,  //(ADD LR,R7)
63     0x4F01,  //(LDR R7,[PC+4])
64     0x4738,  //(BX R7) ---> ARM routine
65     0xBD80,  //(POP {R7,PC} <--- LR (Thumb branch with no conditions for v4t)
66     0x0000,  //(data) ARM routine address
67     0x0000,  //(data)
68 };
69 
70 static BOOL     ELi_BuildSymList( ELDesc* elElfDesc, u32 symsh_index);
71 static ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index);
72 static ELSymEx* ELi_GetSymExfromTbl( ELSymEx** SymExTbl, u32 index);
73 static void     ELi_InitImport( ELImportEntry* ImportInfo);
74 
75 //Extract entry from import information table (Do not delete ImpEnt!)
76 BOOL ELi_ExtractImportEntry( ELImportEntry** StartEnt, ELImportEntry* ImpEnt);
77 void ELi_AddImportEntry( ELImportEntry** ELUnrEntStart, ELImportEntry* UnrEnt);
78 
79 static void      ELi_AddVeneerEntry( ELVeneer** start, ELVeneer* VenEnt);
80 static BOOL      ELi_RemoveVenEntry( ELVeneer** start, ELVeneer* VenEnt);
81 static ELVeneer* ELi_GetVenEntry( ELVeneer** start, u32 data);
82 static BOOL      ELi_IsFar( u32 P, u32 S, s32 threshold);
83 
84 
85 /*------------------------------------------------------
86   Align the addresses
87  -----------------------------------------------------*/
88 #define ALIGN( addr, align_size ) (((addr)  & ~((align_size) - 1)) + (align_size))
89 
90 static u32 ELi_ALIGN( u32 addr, u32 align_size);
ELi_ALIGN(u32 addr,u32 align_size)91 u32 ELi_ALIGN( u32 addr, u32 align_size)
92 {
93     u32 aligned_addr;
94 
95     if( (addr % align_size) == 0) {
96         aligned_addr = addr;
97     }else{
98         aligned_addr = (((addr) & ~((align_size) - 1)) + (align_size));
99     }
100 
101     return aligned_addr;
102 }
103 
104 
105 /*------------------------------------------------------
106   Function to notify the IS-TWL_DEBUGGER
107  -----------------------------------------------------*/
_ISTDbgLib_RegistVeneerInfo(ISTDOVERLAYPROC nProc,ISTDVENEERTYPE vType,u32 nVeneerAddress,u32 nJumpAddress)108 SDK_WEAK_SYMBOL BOOL _ISTDbgLib_RegistVeneerInfo( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress, u32 nJumpAddress)
109 {
110 #pragma unused( nProc)
111 #pragma unused( vType)
112 #pragma unused( nVeneerAddress)
113 #pragma unused( nJumpAddress)
114     return( TRUE);
115 }
116 
_ISTDbgLib_UnregistVeneerInfo(ISTDOVERLAYPROC nProc,ISTDVENEERTYPE vType,u32 nVeneerAddress)117 SDK_WEAK_SYMBOL BOOL _ISTDbgLib_UnregistVeneerInfo( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress)
118 {
119 #pragma unused( nProc, vType, nVeneerAddress)
120     return( TRUE);
121 }
122 
123 static BOOL ELi_REGISTER_VENEER_INFO( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress, u32 nJumpAddress, BOOL enable);
124 static BOOL ELi_UNREGISTER_VENEER_INFO( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress, BOOL enable);
125 
ELi_REGISTER_VENEER_INFO(ISTDOVERLAYPROC nProc,ISTDVENEERTYPE vType,u32 nVeneerAddress,u32 nJumpAddress,BOOL enable)126 static BOOL ELi_REGISTER_VENEER_INFO( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress, u32 nJumpAddress, BOOL enable)
127 {
128     if( enable) {
129         return( _ISTDbgLib_RegistVeneerInfo( nProc, vType, nVeneerAddress, nJumpAddress));
130     }
131     return( FALSE);
132 }
133 
ELi_UNREGISTER_VENEER_INFO(ISTDOVERLAYPROC nProc,ISTDVENEERTYPE vType,u32 nVeneerAddress,BOOL enable)134 static BOOL ELi_UNREGISTER_VENEER_INFO( ISTDOVERLAYPROC nProc, ISTDVENEERTYPE vType, u32 nVeneerAddress, BOOL enable)
135 {
136     if( enable) {
137         return( _ISTDbgLib_UnregistVeneerInfo( nProc, vType, nVeneerAddress));
138     }
139     return( FALSE);
140 }
141 
142 
143 /*------------------------------------------------------
144   Copy the veneer to the buffer
145     start: Call source
146     data: Jump destination
147     threshold: Reuse if there is already veneer in this range
148  -----------------------------------------------------*/
ELi_CopyVeneerToBuffer(ELDesc * elElfDesc,ELObject * MYObject,u32 start,u32 data,s32 threshold)149 void* ELi_CopyVeneerToBuffer( ELDesc* elElfDesc, ELObject* MYObject, u32 start, u32 data, s32 threshold)
150 {
151 #pragma unused(elElfDesc)
152     u32*        el_veneer_dest;
153     u32         load_start;
154     Elf32_Addr  sh_size;
155     ELVeneer*   elVenEnt;
156 
157     if( (elElfDesc == i_eldesc_sim)&&(data == 0)) {
158     }else{
159         /*--- If there already is veneer, use that ---*/
160         elVenEnt = ELi_GetVenEntry( &(MYObject->ELVenEntStart), data);
161         if( elVenEnt != NULL) {
162             if( ELi_IsFar( start, elVenEnt->adr, threshold) == FALSE) {
163                 PRINTDEBUG( "Veneer Hit!\n");
164                 return( (void*)elVenEnt->adr);
165             }else{
166                 /*The veneer is too far and cannot be used, so delete from the link list*/
167                 (void)ELi_RemoveVenEntry( &(MYObject->ELVenEntStart), elVenEnt);
168             }
169         }
170         /*--------------------------------------*/
171     }
172 
173     /*Align*/
174     load_start = ELi_ALIGN( ((u32)(MYObject->buf_current)), 4);
175     /*Size settings*/
176     sh_size = 12;//el_veneer
177 
178     if( elElfDesc != i_eldesc_sim) {
179         /* If not simulation, actually copy */
180         OSAPI_CPUCOPY8( el_veneer, (u32*)load_start, sh_size);
181         el_veneer_dest = (u32*)load_start;
182         el_veneer_dest[2] = data;
183     }
184 
185     /*Move the buffer pointer*/
186     MYObject->buf_current = (void*)(load_start + sh_size);
187 
188     /*--- Add to veneer list ---*/
189     elVenEnt = ELi_Malloc( elElfDesc, MYObject, sizeof( ELVeneer));
190     if(elVenEnt == NULL)
191         return 0;
192     elVenEnt->adr = load_start;
193     elVenEnt->data = data;
194     ELi_AddVeneerEntry( &(MYObject->ELVenEntStart), elVenEnt);
195     (void)ELi_REGISTER_VENEER_INFO( ISTDRELOCATIONPROC_AUTO, ISTDVENEERTYPE_AUTO, elVenEnt->adr, elVenEnt->data, (elElfDesc != i_eldesc_sim));
196     /*--------------------------*/
197 
198     /*Return the loaded header address*/
199     return (void*)load_start;
200 }
201 
202 
203 /*------------------------------------------------------
204   Copy the veneer to the buffer
205     start: Call source
206     data: Jump destination
207     threshold: Reuse if there is already veneer in this range
208  -----------------------------------------------------*/
ELi_CopyV4tVeneerToBuffer(ELDesc * elElfDesc,ELObject * MYObject,u32 start,u32 data,s32 threshold)209 void* ELi_CopyV4tVeneerToBuffer( ELDesc* elElfDesc, ELObject* MYObject, u32 start, u32 data, s32 threshold)
210 {
211 #pragma unused(elElfDesc)
212     u32*        el_veneer_dest;
213     u32         load_start;
214     Elf32_Addr  sh_size;
215     ELVeneer*   elVenEnt;
216 
217     if( (elElfDesc == i_eldesc_sim)&&(data == 0)) {
218         /*--- If there already is veneer, use that ---*/
219         elVenEnt = ELi_GetVenEntry( &(MYObject->ELV4tVenEntStart), data);
220         if( elVenEnt != NULL) {
221             if( ELi_IsFar( start, elVenEnt->adr, threshold) == FALSE) {
222                 PRINTDEBUG( "Veneer Hit!\n");
223                 return( (void*)elVenEnt->adr);
224             }else{
225                 /*The veneer is too far and cannot be used, so delete from the link list*/
226                 (void)ELi_RemoveVenEntry( &(MYObject->ELV4tVenEntStart), elVenEnt);
227             }
228         }
229         /*--------------------------------------*/
230     }
231 
232     /*Align*/
233     load_start = ELi_ALIGN( ((u32)(MYObject->buf_current)), 4);
234     /*Size settings*/
235     sh_size = 20;//el_veneer_t
236 
237     if( elElfDesc != i_eldesc_sim) {
238         /* If not simulation, actually copy */
239         OSAPI_CPUCOPY8( el_veneer_t, (u32*)load_start, sh_size);
240         el_veneer_dest = (u32*)load_start;
241         el_veneer_dest[4] = data;
242     }
243 
244     /*Move the buffer pointer*/
245     MYObject->buf_current = (void*)(load_start + sh_size);
246 
247     /*--- Add to veneer list ---*/
248     elVenEnt = ELi_Malloc( elElfDesc, MYObject, sizeof( ELVeneer));
249     if(elVenEnt == NULL)
250         return 0;
251     elVenEnt->adr = load_start;
252     elVenEnt->data = data;
253     ELi_AddVeneerEntry( &(MYObject->ELV4tVenEntStart), elVenEnt);
254     (void)ELi_REGISTER_VENEER_INFO( ISTDRELOCATIONPROC_AUTO, ISTDVENEERTYPE_AUTO, elVenEnt->adr, elVenEnt->data, (elElfDesc != i_eldesc_sim));
255     /*--------------------------*/
256 
257     /*Return the loaded header address*/
258     return (void*)load_start;
259 }
260 
261 
262 /*------------------------------------------------------
263   Copy the segment to the buffer
264  -----------------------------------------------------*/
ELi_CopySegmentToBuffer(ELDesc * elElfDesc,ELObject * MYObject,Elf32_Phdr * Phdr)265 void* ELi_CopySegmentToBuffer( ELDesc* elElfDesc, ELObject* MYObject, Elf32_Phdr* Phdr)
266 {
267     u32 load_start;
268 
269     load_start = ELi_ALIGN( Phdr->p_vaddr, Phdr->p_align);
270 
271     if( elElfDesc != i_eldesc_sim) {
272         /* If not simulation, actually copy */
273         if( elElfDesc->i_elReadStub( (void*)load_start,
274                                     elElfDesc->FileStruct,
275                                     (u32)(elElfDesc->ar_head),
276                                     (u32)(elElfDesc->elf_offset)+(u32)(Phdr->p_offset),
277                                     Phdr->p_filesz) == FALSE)
278         {
279             ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
280             return( NULL);
281         }
282     }
283 
284     return( (void*)load_start);
285 }
286 
287 /*------------------------------------------------------
288   Copy the section to the buffer
289  -----------------------------------------------------*/
ELi_CopySectionToBuffer(ELDesc * elElfDesc,ELObject * MYObject,Elf32_Shdr * Shdr)290 void* ELi_CopySectionToBuffer( ELDesc* elElfDesc, ELObject* MYObject, Elf32_Shdr* Shdr)
291 {
292     u32         load_start;
293     Elf32_Addr  sh_size;
294 
295     /*Align*/
296     load_start = ELi_ALIGN( ((u32)(MYObject->buf_current)), (Shdr->sh_addralign));
297     /*Size settings*/
298     sh_size = Shdr->sh_size;
299 
300     if( elElfDesc != i_eldesc_sim) {
301         /* If not simulation, actually copy */
302         if( elElfDesc->i_elReadStub( (void*)load_start,
303                                     elElfDesc->FileStruct,
304                                     (u32)(elElfDesc->ar_head),
305                                     (u32)(elElfDesc->elf_offset)+(u32)(Shdr->sh_offset),
306                                     sh_size) == FALSE)
307         {
308             ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF);
309             return( NULL);
310         }
311     }
312     /*Move the buffer pointer*/
313     MYObject->buf_current = (void*)(load_start + sh_size);
314 
315     /*Return the loaded header address*/
316     return (void*)load_start;
317 }
318 
319 
320 /*------------------------------------------------------
321   Allocate a section in the buffer (do not copy) and zero-fill that region.
322 
323  -----------------------------------------------------*/
ELi_AllocSectionToBuffer(ELDesc * elElfDesc,ELObject * MYObject,Elf32_Shdr * Shdr)324 void* ELi_AllocSectionToBuffer( ELDesc* elElfDesc, ELObject* MYObject, Elf32_Shdr* Shdr)
325 {
326 #pragma unused(elElfDesc)
327     u32         load_start;
328     Elf32_Addr  sh_size;
329 
330     /*Align*/
331     load_start = ELi_ALIGN( ((u32)(MYObject->buf_current)), (Shdr->sh_addralign));
332     /*Size settings*/
333     sh_size = Shdr->sh_size;
334 
335     /*Move the buffer pointer*/
336     MYObject->buf_current = (void*)(load_start + sh_size);
337 
338     /*Embed with 0 (because .bss section is expected)*/
339     OSAPI_CPUFILL8( (void*)load_start, 0, sh_size);
340 
341     /*Return the allocated header address*/
342     return (void*)load_start;
343 }
344 
345 
346 /*------------------------------------------------------
347   Get program header of the specified index in buffer
348  -----------------------------------------------------*/
ELi_GetPhdr(ELDesc * elElfDesc,u32 index,Elf32_Phdr * Phdr)349 void ELi_GetPhdr( ELDesc* elElfDesc, u32 index, Elf32_Phdr* Phdr)
350 {
351     u32 offset;
352 
353     offset = (elElfDesc->CurrentEhdr.e_phoff) +
354              ((u32)(elElfDesc->CurrentEhdr.e_phentsize) * index);
355 
356     (void)elElfDesc->i_elReadStub( Phdr,
357                              elElfDesc->FileStruct,
358                              (u32)(elElfDesc->ar_head),
359                              (u32)(elElfDesc->elf_offset) + offset,
360                              sizeof( Elf32_Shdr));
361 }
362 
363 /*------------------------------------------------------
364   Get section header for the specified index to the buffer
365  -----------------------------------------------------*/
ELi_GetShdr(ELDesc * elElfDesc,u32 index,Elf32_Shdr * Shdr)366 void ELi_GetShdr( ELDesc* elElfDesc, u32 index, Elf32_Shdr* Shdr)
367 {
368     u32 offset;
369 
370     offset = (elElfDesc->CurrentEhdr.e_shoff) + ((u32)(elElfDesc->shentsize) * index);
371 
372     (void)elElfDesc->i_elReadStub( Shdr,
373                              elElfDesc->FileStruct,
374                              (u32)(elElfDesc->ar_head),
375                              (u32)(elElfDesc->elf_offset) + offset,
376                              sizeof( Elf32_Shdr));
377 }
378 
379 /*------------------------------------------------------
380   Get section entry for the specified index to the buffer
381  -----------------------------------------------------*/
ELi_GetSent(ELDesc * elElfDesc,u32 index,void * entry_buf,u32 offset,u32 size)382 void ELi_GetSent( ELDesc* elElfDesc, u32 index, void* entry_buf, u32 offset, u32 size)
383 {
384     Elf32_Shdr  Shdr;
385 
386     ELi_GetShdr( elElfDesc, index, &Shdr);
387 
388     (void)elElfDesc->i_elReadStub( entry_buf,
389                              elElfDesc->FileStruct,
390                              (u32)(elElfDesc->ar_head),
391                              (u32)(elElfDesc->elf_offset) + (u32)(Shdr.sh_offset) + offset,
392                              size);
393 }
394 
395 
396 /*------------------------------------------------------
397   Get specified index entry for the specified section header to the buffer.
398     (Only section with a fixed entry size, such as Rel, Rela, Sym, and the like.)
399     Shdr: Specified section header
400     index: Entry number (from 0)
401  -----------------------------------------------------*/
ELi_GetEntry(ELDesc * elElfDesc,Elf32_Shdr * Shdr,u32 index,void * entry_buf)402 void ELi_GetEntry( ELDesc* elElfDesc, Elf32_Shdr* Shdr, u32 index, void* entry_buf)
403 {
404     u32 offset;
405 
406     offset = (u32)(Shdr->sh_offset) + ((Shdr->sh_entsize) * index);
407 
408     (void)elElfDesc->i_elReadStub( entry_buf,
409                              elElfDesc->FileStruct,
410                              (u32)(elElfDesc->ar_head),
411                              (u32)(elElfDesc->elf_offset) + offset,
412                              Shdr->sh_entsize);
413 }
414 
415 /*------------------------------------------------------
416   Get specified index string for the STR section header
417 
418     Shdr: Specified section header
419     index: Entry index (from 0)
420  -----------------------------------------------------*/
ELi_GetStrAdr(ELDesc * elElfDesc,u32 strsh_index,u32 ent_index,char * str,u32 len)421 void ELi_GetStrAdr( ELDesc* elElfDesc, u32 strsh_index, u32 ent_index, char* str, u32 len)
422 {
423     /*Header address of the string entry*/
424     ELi_GetSent( elElfDesc, strsh_index, str, ent_index, len);
425 }
426 
427 /*------------------------------------------------------
428   Redefine symbol.
429 
430     <Rel section header>
431     RelShdr->sh_link: Symbol section number
432     RelShdr->sh_info: Target section number (ex.: Representing .text of rel.text)
433 
434     <Rel entry>
435     Rel->r_offset: Offset address in target section.
436     ELF32_R_SYM( Rel->r_info): Symbol entry number.
437     ELF32_R_TYPE( Rel->r_info): Relocate type.
438 
439     <Symbol section header>
440     SymShdr->sh_link: String table section number of symbol
441 
442     <Sym entry>
443     Sym->st_name: String entry number of symbol
444     Sym->st_value: Offset address in section to which the symbol belongs
445     Sym->st_size: Size in section to which the symbol belongs
446     Sym->st_shndx: Section number to which the symbol belongs
447     ELF32_ST_BIND (Sym->st_info): Bind (Local or Global)
448     ELF32_ST_TYPE( Sym->st_info): Type (Target associated with the symbol)
449  -----------------------------------------------------*/
ELi_RelocateSym(ELDesc * elElfDesc,ELObject * MYObject,u32 relsh_index)450 BOOL ELi_RelocateSym( ELDesc* elElfDesc, ELObject* MYObject, u32 relsh_index)
451 {
452     u32                 i;
453     u32                 num_of_rel;     //Number of symbols that should be redefined
454     Elf32_Shdr          RelOrRelaShdr;  //REL or RELA section header
455     Elf32_Rela          CurrentRela;    //REL or RELA entry copy destination
456     Elf32_Shdr*         SymShdr;
457     ELSymEx*            CurrentSymEx;
458     ELShdrEx*           TargetShdrEx;
459     ELShdrEx*           CurrentShdrEx;
460     u32                 relocation_adr;
461     char                sym_str[128];
462     u32                 copy_size;
463     ELAdrEntry*         CurrentAdrEntry;
464     u32                 sym_loaded_adr = 0;
465     u32                 thumb_func_flag = 0;
466     ELImportEntry       UnresolvedInfo;
467     ELImportEntry*      UnrEnt;
468     ELObject*           ExpObjEnt;
469     u32                 unresolved_num = 0;
470 
471     /*Get REL or RELA section header*/
472     ELi_GetShdr( elElfDesc, relsh_index, &RelOrRelaShdr);
473 
474     /*Target section EX header*/
475     TargetShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, RelOrRelaShdr.sh_info);
476 
477     num_of_rel = (RelOrRelaShdr.sh_size) / (RelOrRelaShdr.sh_entsize);    //Number of symbols that should be redefined
478 
479     /*Create the symbol list*/
480     if(ELi_BuildSymList( elElfDesc, RelOrRelaShdr.sh_link) == FALSE)
481         return FALSE;
482     /*elElfDesc->SymShdr is set when ELi_BuildSymList is called*/
483     SymShdr = &(elElfDesc->SymShdr);
484     PRINTDEBUG( "SymShdr->link:%02x, SymShdr->info:%02x\n", SymShdr->sh_link, SymShdr->sh_info);
485 
486 
487     /*--- Redefine symbols that must be redefined ---*/
488     for( i=0; i<num_of_rel; i++) {
489 
490         /*- Get Rel or Rela Entry -*/
491         ELi_GetEntry( elElfDesc, &RelOrRelaShdr, i, &CurrentRela);
492 
493         if( RelOrRelaShdr.sh_type == SHT_REL) {
494             CurrentRela.r_addend = 0;
495         }
496         /*-----------------------------*/
497 
498         /*Get symbol ExEntry (ELi_GetSymExfromTbl is acceptable)*/
499         CurrentSymEx = (ELSymEx*)(elElfDesc->SymExTbl[ELF32_R_SYM( CurrentRela.r_info)]);
500 
501 //        if( CurrentSymEx->debug_flag == 1) {              // *When it is debugging information *
502         if( CurrentSymEx == NULL) {
503         }else{                                            /*When not debugging information*/
504             /**/
505             ELi_InitImport( &UnresolvedInfo);
506             /*Rewritten address (Called P in the specifications)*/
507             relocation_adr = (TargetShdrEx->loaded_adr) + (CurrentRela.r_offset);
508             UnresolvedInfo.r_type = ELF32_R_TYPE( CurrentRela.r_info);
509             UnresolvedInfo.A_ = (CurrentRela.r_addend);
510             UnresolvedInfo.P_ = (relocation_adr);
511             UnresolvedInfo.sh_type = (RelOrRelaShdr.sh_type);
512 
513             /*Locate the symbol address*/
514             if( CurrentSymEx->Sym.st_shndx == SHN_UNDEF) {
515                 /*Search from address table*/
516                 ELi_GetStrAdr( elElfDesc, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128);
517                 CurrentAdrEntry = elGetAdrEntry( elElfDesc, sym_str, &ExpObjEnt);
518 
519                 /*Confirm symbol string*/
520                 copy_size = (u32)OSAPI_STRLEN( sym_str) + 1;
521                 UnresolvedInfo.sym_str = ELi_Malloc( elElfDesc, MYObject, copy_size);
522                 if(UnresolvedInfo.sym_str == NULL)
523                     return FALSE;
524                 OSAPI_CPUCOPY8( sym_str, UnresolvedInfo.sym_str, copy_size);
525 
526                 if( CurrentAdrEntry) {    /*When found from the address table*/
527                     sym_loaded_adr = (u32)(CurrentAdrEntry->adr);
528                     /*THUMB function flag (called T in the specifications) to differentiate THUMB or ARM*/
529                     thumb_func_flag = CurrentAdrEntry->thumb_flag;
530                     PRINTDEBUG( "\n symbol found %s : %8x\n", sym_str, sym_loaded_adr);
531                 }else{                    /*Do not resolve when not found from address table*/
532                     /*Add and register to unresolved table*/
533                     copy_size = sizeof( ELImportEntry);
534                     UnrEnt = ELi_Malloc( elElfDesc, MYObject, copy_size);
535                     if(UnrEnt == NULL)
536                         return FALSE;
537                     OSAPI_CPUCOPY8( &UnresolvedInfo, UnrEnt, copy_size);
538                     ELi_AddImportEntry( &(MYObject->UnresolvedImportAdrEnt), UnrEnt);
539 
540                     unresolved_num++;    /*Count number of unresolved symbols*/
541                     PRINTDEBUG( "\n WARNING! cannot find symbol : %s\n", sym_str);
542                 }
543             }else{ /* When resolved by yourself */
544                 /*Get Ex header of section where symbol belongs*/
545                 CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, CurrentSymEx->Sym.st_shndx);
546                 sym_loaded_adr = CurrentShdrEx->loaded_adr;
547                 sym_loaded_adr += CurrentSymEx->Sym.st_value;    //sym_loaded_adr is called S in the specifications
548                 /*THUMB function flag (called T in the specifications) to differentiate THUMB or ARM*/
549                 thumb_func_flag = CurrentSymEx->thumb_flag;
550                 ExpObjEnt = MYObject;
551             }
552 
553             if( ExpObjEnt) {        /* Resolve when someone exported themselves */
554                 /*Set to same variable name as in the specifications*/
555                 UnresolvedInfo.S_ = (sym_loaded_adr);
556                 UnresolvedInfo.T_ = (thumb_func_flag);
557 
558                 /*Add and register to unresolved table (only when referencing a separate object)*/
559                 if( ExpObjEnt != MYObject) {
560                     copy_size = sizeof( ELImportEntry);
561                     UnrEnt = ELi_Malloc( elElfDesc, MYObject, copy_size);
562                     if(UnrEnt == NULL)
563                         return FALSE;
564                     OSAPI_CPUCOPY8( &UnresolvedInfo, UnrEnt, copy_size);
565                     UnrEnt->Dlld = (struct ELObject*)ExpObjEnt;    /* Record objects used in resolution  */
566                     ELi_AddImportEntry( &(MYObject->ResolvedImportAdrEnt), UnrEnt);
567                 }
568 
569                 /*--------------- Resolve symbol (Execute Relocation) ---------------*/
570                 /*CurrentSymEx->relocation_val =*/
571                 if( ELi_DoRelocate( elElfDesc, MYObject, &UnresolvedInfo) == FALSE) {
572                     return( FALSE);
573                 }
574                 /*------------------------------------------------------------*/
575             }
576         }
577     }
578     /*-----------------------------------*/
579 
580 
581     /*Deallocate the symbol list*/
582 //    ELi_FreeSymList( elElfDesc);
583 
584 
585     /* After completing relocation */
586     if( unresolved_num == 0) {
587         ELi_SetProcCode( elElfDesc, NULL, EL_PROC_RELOCATED);
588     }
589     return TRUE;
590 }
591 
592 
593 /*------------------------------------------------------
594   Put global symbols in address table
595 
596     <Symbol section header>
597     SymShdr->sh_link: String table section number of symbol
598 
599     <Sym entry>
600     Sym->st_name: String entry number of symbol
601     Sym->st_value: Offset address in section to which the symbol belongs
602     Sym->st_size: Size in section to which the symbol belongs
603     Sym->st_shndx: Section number to which the symbol belongs
604     ELF32_ST_BIND (Sym->st_info): Bind (Local or Global)
605     ELF32_ST_TYPE( Sym->st_info): Type (Target associated with the symbol)
606  -----------------------------------------------------*/
ELi_GoPublicGlobalSym(ELDesc * elElfDesc,ELObject * MYObject,u32 symtblsh_index)607 BOOL ELi_GoPublicGlobalSym( ELDesc* elElfDesc, ELObject* MYObject, u32 symtblsh_index)
608 {
609     Elf32_Shdr   SymShdr;
610     ELSymEx*     CurrentSymEx;
611     ELShdrEx*    CurrentShdrEx;
612     ELAdrEntry*  ExportAdrEntry;
613     ELObject*    DmyObjEnt;
614     char         sym_str[128];
615     u32          copy_size;
616 
617     /*Get SYMTAB section header*/
618     ELi_GetShdr( elElfDesc, symtblsh_index, &SymShdr);
619 
620     /*Create the symbol list*/
621     if(ELi_BuildSymList( elElfDesc, symtblsh_index) == FALSE)
622         return FALSE;
623 
624     /*--- Made GLOBAL symbol in library public to address table ---*/
625     CurrentSymEx = elElfDesc->SymEx; //If traceable not from Tbl but from here, debug information is not included
626     while( CurrentSymEx != NULL) {
627 //        CurrentSymEx = ELi_GetSymExfromList( elElfDesc->SymExTbl, i);
628 //        if( CurrentSymEx != NULL) {
629         /*When global and the related section exist in the library*/
630         if( (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) &&
631             (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) {
632 
633             ExportAdrEntry = ELi_Malloc( elElfDesc, MYObject, sizeof(ELAdrEntry));    /*Memory allocation*/
634             if(ExportAdrEntry == NULL)
635                 return FALSE;
636             ExportAdrEntry->next = NULL;
637 
638             ELi_GetStrAdr( elElfDesc, SymShdr.sh_link, CurrentSymEx->Sym.st_name, sym_str, 128);
639             copy_size = (u32)OSAPI_STRLEN( sym_str) + 1;
640             ExportAdrEntry->name = ELi_Malloc( elElfDesc, MYObject, copy_size);
641             if(ExportAdrEntry->name == NULL)
642                 return FALSE;
643             OSAPI_CPUCOPY8( sym_str, ExportAdrEntry->name, copy_size);
644 
645             CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, CurrentSymEx->Sym.st_shndx);
646             //There are cases where Sym.st_value is adjusted to enable determination of ARM/Thumb with odd/even numbers, so delete the adjustment to derive the net value.
647             ExportAdrEntry->adr = (void*)(CurrentShdrEx->loaded_adr + ((CurrentSymEx->Sym.st_value)&0xFFFFFFFE));
648             ExportAdrEntry->func_flag = (u16)(ELF32_ST_TYPE( CurrentSymEx->Sym.st_info));
649             ExportAdrEntry->thumb_flag = CurrentSymEx->thumb_flag;
650 
651             if( elGetAdrEntry( elElfDesc, ExportAdrEntry->name, &DmyObjEnt) == NULL) {    //If not in
652                 elAddAdrEntry( &(MYObject->ExportAdrEnt), ExportAdrEntry);    /*registration*/
653             }
654         }
655         CurrentSymEx = CurrentSymEx->next;
656 //        }
657     }
658     /*----------------------------------------------------------------*/
659 
660     /*Deallocate the symbol list*/
661 //    ELi_FreeSymList( elElfDesc);
662     return TRUE;
663 }
664 
665 
666 /*------------------------------------------------------
667   Create the symbol list
668 
669  -----------------------------------------------------*/
ELi_BuildSymList(ELDesc * elElfDesc,u32 symsh_index)670 static BOOL ELi_BuildSymList( ELDesc* elElfDesc, u32 symsh_index)
671 {
672     u32         i;
673     u32         num_of_sym;        //Overall symbol count
674     u16         debug_flag;
675     Elf32_Sym   TestSym;
676     ELSymEx*    CurrentSymEx;
677     ELShdrEx*   CurrentShdrEx;
678     Elf32_Shdr* SymShdr;
679     ELSymEx     DmySymEx;
680 
681     if( elElfDesc->SymExTarget == symsh_index) {
682         PRINTDEBUG( "%s skip.\n", __FUNCTION__);
683         return TRUE;                              //List already created
684     }else{
685         ELi_FreeSymList( elElfDesc); /*Deallocate the symbol list*/
686     }
687 
688     PRINTDEBUG( "%s build\n", __FUNCTION__);
689 
690     /*Get SYMTAB section header*/
691     ELi_GetShdr( elElfDesc, symsh_index, &(elElfDesc->SymShdr));
692     SymShdr = &(elElfDesc->SymShdr);
693 
694     num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize);    //Overall symbol count
695     elElfDesc->SymExTbl = ELi_Malloc( elElfDesc, NULL, num_of_sym * 4);
696     if(elElfDesc->SymExTbl == NULL)
697         return FALSE;
698     /*---------- Create ELSymEx List  ----------*/
699     CurrentSymEx = &DmySymEx;
700     for( i=0; i<num_of_sym; i++) {
701 
702         /*Copy symbol entry*/
703         ELi_GetEntry( elElfDesc, (Elf32_Shdr*)SymShdr, i, &TestSym);
704         /*-- Set debug information flag --*/
705         CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, TestSym.st_shndx);
706         if( CurrentShdrEx) {
707             debug_flag = CurrentShdrEx->debug_flag;
708         }else{
709             debug_flag = 0;
710         }/*-------------------------------*/
711 
712         if( debug_flag == 1) {
713             elElfDesc->SymExTbl[i] = NULL;
714         }else{
715             CurrentSymEx->next = ELi_Malloc( elElfDesc, NULL, sizeof(ELSymEx));
716             if(CurrentSymEx->next == NULL)
717                 return FALSE;
718             CurrentSymEx = (ELSymEx*)(CurrentSymEx->next);
719 
720             OSAPI_CPUCOPY8( &TestSym, &(CurrentSymEx->Sym), sizeof(TestSym));
721 
722             elElfDesc->SymExTbl[i] = CurrentSymEx;
723 
724             PRINTDEBUG( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx);
725         }
726     }
727 
728     CurrentSymEx->next = NULL;
729     elElfDesc->SymEx = DmySymEx.next;
730     /*-------------------------------------------*/
731 
732 
733     /*-------- Determine ARM or Thumb (Because if SymEx is not ready, ELi_CodeIsThumb does not work) --------*/
734     CurrentSymEx = elElfDesc->SymEx;
735     while( CurrentSymEx != NULL) { //If traceable from here, there is no debug information
736         /*-- Set the ELSymEx Thumb flag (Only the function symbol is required) -----*/
737         if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) {
738             CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( elElfDesc,
739                                                               CurrentSymEx->Sym.st_shndx,
740                                                               CurrentSymEx->Sym.st_value));
741         }else{
742             CurrentSymEx->thumb_flag = 0;
743         }/*--------------------------------------------------------*/
744 
745         CurrentSymEx = CurrentSymEx->next;
746     }
747     /*-------------------------------------------------------------------------------------*/
748 
749 
750     elElfDesc->SymExTarget = symsh_index;
751     return TRUE;
752 }
753 
754 
755 /*------------------------------------------------------
756   Deallocate the symbol list
757 
758  -----------------------------------------------------*/
ELi_FreeSymList(ELDesc * elElfDesc)759 void ELi_FreeSymList( ELDesc* elElfDesc)
760 {
761     ELSymEx*  CurrentSymEx;
762     ELSymEx*  FwdSymEx;
763 
764     /*--- First free SymExTbl ---*/
765     if( elElfDesc->SymExTbl != NULL) {
766         OSAPI_FREE( elElfDesc->SymExTbl);
767         elElfDesc->SymExTbl = NULL;
768     }
769 
770     /*---------- Free the ELSymEx List  ----------*/
771     CurrentSymEx = elElfDesc->SymEx;
772     if( CurrentSymEx) {
773         do {
774             FwdSymEx = CurrentSymEx;
775             CurrentSymEx = CurrentSymEx->next;
776             OSAPI_FREE( FwdSymEx);
777         }while( CurrentSymEx != NULL);
778         elElfDesc->SymEx = NULL;
779     }
780     /*-----------------------------------------*/
781 
782     elElfDesc->SymExTarget = 0xFFFFFFFF;
783 }
784 
785 
786 /*------------------------------------------------------
787   Resolve symbol based on unresolved information
788 
789     It is necessary to know all of the r_type, S_, A_, P_, and T_
790  -----------------------------------------------------*/
791 #define _S_    (UnresolvedInfo->S_)
792 #define _A_    (UnresolvedInfo->A_)
793 #define _P_    (UnresolvedInfo->P_)
794 #define _T_    (UnresolvedInfo->T_)
ELi_DoRelocate(ELDesc * elElfDesc,ELObject * MYObject,ELImportEntry * UnresolvedInfo)795 BOOL    ELi_DoRelocate( ELDesc* elElfDesc, ELObject* MYObject, ELImportEntry* UnresolvedInfo)
796 {
797     s32    signed_val;
798     u32    relocation_val = 0;
799     u32    relocation_adr;
800     BOOL   ret_val;
801     BOOL   veneer_flag = TRUE;
802 
803     ret_val = TRUE;
804     relocation_adr = _P_;
805 
806     switch( (UnresolvedInfo->r_type)) {
807       case R_ARM_PC24:
808       case R_ARM_PLT32:
809       case R_ARM_CALL:
810       case R_ARM_JUMP24:
811         if( UnresolvedInfo->sh_type == SHT_REL) {
812             _A_ = (s32)(((*(vu32*)relocation_adr)|0xFF800000) << 2);    //Generally, this should be -8
813         }
814         /*----------------- veneer -----------------*/
815         if( (elElfDesc == i_eldesc_sim)&&(_S_ == 0)) {
816             veneer_flag = TRUE; //If resolution not possible with simulation, veneer is presumed
817         }else{
818             veneer_flag = ELi_IsFar( _P_, _S_|_T_, 0x2000000); //Within +-32 Bytes?
819         }
820 #if (TARGET_ARM_V5 == 1)
821         if( veneer_flag == TRUE) {
822 #else //(TARGET_ARM_V4 == 1)
823         //Use veneer when there is a long branch with ARM->Thumb and ARM->ARM
824         if( (_T_) || (veneer_flag == TRUE)) {
825 #endif
826             //_A_ is an adjustment value for PC relative branch, so when an absolute branch, there is no relationship.
827             _S_ = (u32)ELi_CopyVeneerToBuffer( elElfDesc,
828                                                MYObject,
829                                                _P_,
830                                                (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)),
831                                                0x2000000);
832             if(_S_ == 0)
833                 return FALSE;
834             _T_ = 0; //Because veneer is ARM code
835         }/*-----------------------------------------*/
836         if( elElfDesc == i_eldesc_sim) {  //Do not actually redefine the symbol at simulation
837             break;
838         }
839         signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_);
840         if( _T_) {        /*Jump from ARM to Thumb with BLX instruction (If less than v5, BL �� it is necessary to combine with BX using veneer)*/
841             relocation_val = (0xFA000000) | ((signed_val>>2) & 0x00FFFFFF) | (((signed_val>>1) & 0x1)<<24);
842         }else{            /*Jump from ARM to ARM using the BL instruction*/
843             signed_val >>= 2;
844             relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF);
845         }
846         *(vu32*)relocation_adr = relocation_val;
847         break;
848       case R_ARM_ABS32:
849         if( elElfDesc == i_eldesc_sim) { //Do not actually redefine the symbol at simulation
850             break;
851         }
852         relocation_val = (( _S_ + _A_) | _T_);
853         *(vu32*)relocation_adr = relocation_val;
854         break;
855       case R_ARM_REL32:
856       case R_ARM_PREL31:
857         if( elElfDesc == i_eldesc_sim) { //Do not actually redefine the symbol at simulation
858             break;
859         }
860         relocation_val = (( _S_ + _A_) | _T_) - _P_;
861         *(vu32*)relocation_adr = relocation_val;
862         break;
863       case R_ARM_LDR_PC_G0:
864         /*----------------- veneer -----------------*/
865         if( (elElfDesc == i_eldesc_sim)&&(_S_ == 0)) {
866             veneer_flag = TRUE; //If resolution not possible with simulation, veneer is presumed
867         }else{
868             veneer_flag = ELi_IsFar( _P_, _S_|_T_, 0x2000000); //Within +-32 Bytes?
869         }
870 #if (TARGET_ARM_V5 == 1)
871         if( veneer_flag == TRUE) {
872 #else //(TARGET_ARM_V4 == 1)
873         //Use veneer when there is a long branch with ARM->Thumb and ARM->ARM
874         if( (_T_) || (veneer_flag == TRUE)) {
875 #endif
876             //_A_ is an adjustment value for PC relative branch, so when an absolute branch, there is no relationship.
877             _S_ = (u32)ELi_CopyVeneerToBuffer( elElfDesc,
878                                                MYObject,
879                                                _P_,
880                                                (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)),
881                                                0x2000000);
882             if(_S_ == 0)
883                 return FALSE;
884             _T_ = 0; //Because veneer is ARM code
885         }/*-----------------------------------------*/
886         if( elElfDesc == i_eldesc_sim) {  //Do not actually redefine the symbol at simulation
887             break;
888         }
889         signed_val = ( (s32)(_S_) + _A_) - (s32)(_P_);
890         signed_val >>= 2;
891         relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF);
892         *(vu32*)relocation_adr = relocation_val;
893         break;
894       case R_ARM_ABS16:
895       case R_ARM_ABS12:
896       case R_ARM_THM_ABS5:
897       case R_ARM_ABS8:
898         if( elElfDesc == i_eldesc_sim) { //Do not actually redefine the symbol at simulation
899             break;
900         }
901         relocation_val = _S_ + _A_;
902         *(vu32*)relocation_adr = relocation_val;
903         break;
904       case R_ARM_THM_PC22:/*Different Name: R_ARM_THM_CALL*/
905         if( UnresolvedInfo->sh_type == SHT_REL) {
906             _A_ = (s32)(((*(vu16*)relocation_adr & 0x07FF)<<11) + ((*((vu16*)(relocation_adr)+1)) & 0x07FF));
907             _A_ = (s32)((_A_ | 0xFFC00000) << 1);    //Generally, this should be -4 (Because the PC is the current instruction address +4)
908         }
909         /*----------------- veneer -----------------*/
910         if( (elElfDesc == i_eldesc_sim)&&(_S_ == 0)) {
911             veneer_flag = TRUE; //If resolution not possible with simulation, veneer is presumed
912         }else{
913             veneer_flag = ELi_IsFar( _P_, _S_|_T_, 0x400000); //Within +-4 Bytes?
914         }
915 #if (TARGET_ARM_V5 == 1)
916         if( veneer_flag == TRUE) {
917             //_A_ is an adjustment value for PC relative branch, so when an absolute branch, there is no relationship.
918             _S_ = (u32)ELi_CopyVeneerToBuffer( elElfDesc,
919                                                MYObject,
920                                                _P_,
921                                                (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)),
922                                                0x400000);
923             if(_S_ == 0)
924                 return FALSE;
925             _T_ = 0; //Because veneer is ARM code
926         }/*-----------------------------------------*/
927 #else //(TARGET_ARM_V4 == 1)
928         /*----------------- v4t veneer -----------------*/
929         //Use v4T when there is a long branch with Thumb->ARM and Thumb->Thumb
930         if( (_T_ == 0) || (veneer_flag == TRUE)) {
931             _S_ = (u32)ELi_CopyV4tVeneerToBuffer( elElfDesc,
932                                                   MYObject,
933                                                   _P_,
934                                                   (u32)(( (s32)(_S_)) | (s32)(_T_)),
935                                                   0x400000);
936             if(_S_ == 0)
937                 return FALSE;
938             _T_ = 1; //Because v4t veneer is Thumb code
939         }
940         /*---------------------------------------------*/
941 #endif
942         if( elElfDesc == i_eldesc_sim) { //Do not actually redefine the symbol at simulation
943             break;
944         }
945         signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_);
946         signed_val >>= 1;
947         if( _T_) {    /*Jump from Thumb to Thumb using the BL instruction*/
948             relocation_val = (u32)(*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF) +
949                                    ((((*((vu16*)(relocation_adr)+1)) & 0xF800) | (signed_val & 0x07FF)) << 16);
950         }else{        /*Jump from Thumb to ARM with BLX instruction (If less than v5, it is necessary to combine with BX with BL �� veneer)*/
951             if( (signed_val & 0x1)) {    //Come here when _P_ is not 4-byte aligned
952                 signed_val += 1;
953             }
954             relocation_val = (u32)(*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF) +
955                                    ((((*((vu16*)(relocation_adr)+1)) & 0xE800) | (signed_val & 0x07FF)) << 16);
956         }
957         *(vu16*)relocation_adr = (vu16)relocation_val;
958         *((vu16*)relocation_adr+1) = (vu16)((u32)(relocation_val) >> 16);
959         break;
960       case R_ARM_NONE:
961         /*R_ARM_NONE retains target symbols and is not dead-stripped to the linker
962           */
963         break;
964       case R_ARM_THM_JUMP24:
965       default:
966         ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF);
967         ret_val = FALSE;
968         PRINTDEBUG( "ERROR! : unsupported relocation type (0x%x)!\n", (UnresolvedInfo->r_type));
969         PRINTDEBUG( "S = 0x%x\n", _S_);
970         PRINTDEBUG( "A = 0x%x\n", _A_);
971         PRINTDEBUG( "P = 0x%x\n", _P_);
972         PRINTDEBUG( "T = 0x%x\n", _T_);
973         break;
974     }
975 
976     return ret_val;//relocation_val;
977 }
978 #undef _S_
979 #undef _A_
980 #undef _P_
981 #undef _T_
982 
983 /*------------------------------------------------------
984   Read ELSymEx of the index specified from the list.
985  -----------------------------------------------------*/
986 static ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index)
987 {
988     u32         i;
989     ELSymEx*    SymEx;
990 
991     SymEx = SymExStart;
992     for( i=0; i<index; i++) {
993         SymEx = (ELSymEx*)(SymEx->next);
994         if( SymEx == NULL) {
995             break;
996         }
997     }
998     return SymEx;
999 }
1000 
1001 /*------------------------------------------------------
1002   Read ELSymEx of the index specified from the table.
1003  -----------------------------------------------------*/
1004 static ELSymEx* ELi_GetSymExfromTbl( ELSymEx** SymExTbl, u32 index)
1005 {
1006     return( (ELSymEx*)(SymExTbl[index]));
1007 }
1008 
1009 /*------------------------------------------------------
1010   Read ELShdrx of the index specified from the list.
1011  -----------------------------------------------------*/
1012 ELShdrEx* ELi_GetShdrExfromList( ELShdrEx* ShdrExStart, u32 index)
1013 {
1014     u32         i;
1015     ELShdrEx*   ShdrEx;
1016 
1017     ShdrEx = ShdrExStart;
1018     for( i=0; i<index; i++) {
1019         ShdrEx = (ELShdrEx*)(ShdrEx->next);
1020         if( ShdrEx == NULL) {
1021             break;
1022         }
1023     }
1024     return ShdrEx;
1025 }
1026 
1027 
1028 
1029 /*------------------------------------------------------
1030   Determine whether the section for the specified index is debug information
1031 
1032 <Definition of debugging information>
1033 - Sections whose section name begins with .debug.
1034 
1035 - Section, such as .rel.debug - section, where the sh_info indicates the debug information section number
1036 
1037  -----------------------------------------------------*/
1038 BOOL ELi_ShdrIsDebug( ELDesc* elElfDesc, u32 index)
1039 {
1040     Elf32_Shdr  TmpShdr;
1041     char        shstr[6];
1042 
1043     /*-- Get six characters of string for section name --*/
1044     ELi_GetShdr( elElfDesc, index, &TmpShdr);
1045     ELi_GetStrAdr( elElfDesc, elElfDesc->CurrentEhdr.e_shstrndx,
1046                    TmpShdr.sh_name, shstr, 6);
1047     /*-------------------------------------*/
1048 
1049     if( OSAPI_STRNCMP( shstr, ".debug", 6) == 0) {    /*When debugging section*/
1050         return TRUE;
1051     }else{                        /*When relocated section relates to the debugging section*/
1052         if( (TmpShdr.sh_type == SHT_REL) || (TmpShdr.sh_type == SHT_RELA)) {
1053             if( ELi_ShdrIsDebug( elElfDesc, TmpShdr.sh_info) == TRUE) {
1054                 return TRUE;
1055             }
1056         }
1057     }
1058 
1059     return FALSE;
1060 }
1061 
1062 
1063 
1064 /*------------------------------------------------------
1065   Check the elElfDesc SymEx table, and determine whether the code in the specified offset of the specified index is ARM or THUMB
1066 
1067   (iConfigure elElfDesc->SymShdr and elElfDesc->SymEx in advance.)
1068 
1069     sh_index: Section index to be checked
1070     offset: Offset in section to check
1071  -----------------------------------------------------*/
1072 u32 ELi_CodeIsThumb( ELDesc* elElfDesc, u16 sh_index, u32 offset)
1073 {
1074     u32            i;
1075     u32            thumb_flag;
1076     Elf32_Shdr*    SymShdr;
1077     char           str_adr[3];
1078     ELSymEx*       CurrentSymEx;
1079 
1080     /*Get symbol section header and SymEx list*/
1081     SymShdr = &(elElfDesc->SymShdr);
1082     CurrentSymEx = elElfDesc->SymEx;
1083 
1084     i = 0;
1085     thumb_flag = 0;
1086     while( CurrentSymEx != NULL) {
1087 
1088         if( CurrentSymEx->Sym.st_shndx == sh_index) {
1089             ELi_GetStrAdr( elElfDesc, SymShdr->sh_link, CurrentSymEx->Sym.st_name, str_adr, 3);
1090             if( OSAPI_STRNCMP( str_adr, "$a\0", OSAPI_STRLEN("$a\0")) == 0) {
1091                 thumb_flag = 0;
1092             }else if( OSAPI_STRNCMP( str_adr, "$t\0", OSAPI_STRLEN("$t\0")) == 0) {
1093                 thumb_flag = 1;
1094             }
1095             if( CurrentSymEx->Sym.st_value > offset) {
1096                 break;
1097             }
1098         }
1099 
1100         CurrentSymEx = CurrentSymEx->next;
1101         i++;
1102     }
1103 
1104     return thumb_flag;
1105 }
1106 
1107 
1108 /*---------------------------------------------------------
1109  Initialize the import information entry
1110  --------------------------------------------------------*/
1111 static void ELi_InitImport( ELImportEntry* ImportInfo)
1112 {
1113     ImportInfo->sym_str = NULL;
1114     ImportInfo->r_type = 0;
1115     ImportInfo->S_ = 0;
1116     ImportInfo->A_ = 0;
1117     ImportInfo->P_ = 0;
1118     ImportInfo->T_ = 0;
1119     ImportInfo->Dlld = NULL;
1120 }
1121 
1122 /*------------------------------------------------------
1123   Extract entry from import information table (Do not delete ImpEnt!)
1124  -----------------------------------------------------*/
1125 BOOL ELi_ExtractImportEntry( ELImportEntry** StartEnt, ELImportEntry* ImpEnt)
1126 {
1127     ELImportEntry  DmyImpEnt;
1128     ELImportEntry* CurImpEnt;
1129 
1130     DmyImpEnt.next = (*StartEnt);
1131     CurImpEnt      = &DmyImpEnt;
1132 
1133     while( CurImpEnt->next != ImpEnt) {
1134         if( CurImpEnt->next == NULL) {
1135             return FALSE;
1136         }else{
1137             CurImpEnt = (ELImportEntry*)CurImpEnt->next;
1138         }
1139     }
1140 
1141     /*Relink link list*/
1142     CurImpEnt->next = ImpEnt->next;
1143     (*StartEnt) = DmyImpEnt.next;
1144 
1145     /*Free*/
1146 //    OSAPI_FREE( ImpEnt);
1147 
1148     return TRUE;
1149 }
1150 
1151 /*---------------------------------------------------------
1152  Add entry to the import information table
1153  --------------------------------------------------------*/
1154 void ELi_AddImportEntry( ELImportEntry** ELUnrEntStart, ELImportEntry* UnrEnt)
1155 {
1156     ELImportEntry    DmyUnrEnt;
1157     ELImportEntry*   CurrentUnrEnt;
1158 
1159     if( !(*ELUnrEntStart)) {
1160         (*ELUnrEntStart) = UnrEnt;
1161     }else{
1162         DmyUnrEnt.next = (*ELUnrEntStart);
1163         CurrentUnrEnt = &DmyUnrEnt;
1164 
1165         while( CurrentUnrEnt->next != NULL) {
1166             CurrentUnrEnt = CurrentUnrEnt->next;
1167         }
1168         CurrentUnrEnt->next = (void*)UnrEnt;
1169     }
1170     UnrEnt->next = NULL;
1171 }
1172 
1173 /*------------------------------------------------------
1174   Release all import information tables
1175  -----------------------------------------------------*/
1176 void ELi_FreeImportTbl( ELImportEntry** ELImpEntStart)
1177 {
1178     ELImportEntry*    FwdImpEnt;
1179     ELImportEntry*    CurrentImpEnt;
1180 
1181     /*---------- Free the ELImportEntry List  ----------*/
1182     CurrentImpEnt = (*ELImpEntStart);
1183     if( CurrentImpEnt) {
1184         do {
1185             FwdImpEnt = CurrentImpEnt;
1186             CurrentImpEnt = CurrentImpEnt->next;
1187             OSAPI_FREE( FwdImpEnt->sym_str);        //Symbol name character-string
1188             OSAPI_FREE( FwdImpEnt);              //Structure itself
1189         }while( CurrentImpEnt != NULL);
1190         (*ELImpEntStart) = NULL;
1191     }
1192     /*------------------------------------*/
1193 }
1194 
1195 
1196 /*---------------------------------------------------------
1197  Add entry to veneer table
1198  --------------------------------------------------------*/
1199 static void ELi_AddVeneerEntry( ELVeneer** start, ELVeneer* VenEnt)
1200 {
1201     ELVeneer    DmyVenEnt;
1202     ELVeneer*   CurrentVenEnt;
1203 
1204     if( !(*start)) {
1205         (*start) = VenEnt;
1206     }else{
1207         DmyVenEnt.next = (*start);
1208         CurrentVenEnt = &DmyVenEnt;
1209 
1210         while( CurrentVenEnt->next != NULL) {
1211             CurrentVenEnt = CurrentVenEnt->next;
1212         }
1213         CurrentVenEnt->next = (void*)VenEnt;
1214     }
1215     VenEnt->next = NULL;
1216 }
1217 
1218 /*------------------------------------------------------
1219   Delete entry from the veneer table
1220  -----------------------------------------------------*/
1221 static BOOL ELi_RemoveVenEntry( ELVeneer** start, ELVeneer* VenEnt)
1222 {
1223     ELVeneer  DmyVenEnt;
1224     ELVeneer* CurrentVenEnt;
1225 
1226     DmyVenEnt.next = (*start);
1227     CurrentVenEnt = &DmyVenEnt;
1228 
1229     while( CurrentVenEnt->next != VenEnt) {
1230         if( CurrentVenEnt->next == NULL) {
1231             return FALSE;
1232         }else{
1233             CurrentVenEnt = (ELVeneer*)CurrentVenEnt->next;
1234         }
1235     }
1236 
1237     /*Relink link list*/
1238     CurrentVenEnt->next = VenEnt->next;
1239     (*start) = DmyVenEnt.next;
1240 
1241     /*Free*/
1242     OSAPI_FREE( VenEnt);
1243 
1244      return TRUE;
1245 }
1246 
1247 /*------------------------------------------------------
1248   Search for entry corresponding to specified data in the veneer table
1249  -----------------------------------------------------*/
1250 static ELVeneer* ELi_GetVenEntry( ELVeneer** start, u32 data)
1251 {
1252     ELVeneer* CurrentVenEnt;
1253 
1254     CurrentVenEnt = (*start);
1255     if( CurrentVenEnt == NULL) {
1256         return NULL;
1257     }
1258     while( CurrentVenEnt->data != data) {
1259         CurrentVenEnt = (ELVeneer*)CurrentVenEnt->next;
1260         if( CurrentVenEnt == NULL) {
1261             break;
1262         }
1263     }
1264     return CurrentVenEnt;
1265 }
1266 
1267 /*------------------------------------------------------
1268   Deallocate the veneer table
1269  -----------------------------------------------------*/
1270 void* ELi_FreeVenTbl( ELDesc* elElfDesc, ELObject* MYObject)
1271 {
1272     ELVeneer*    FwdVenEnt;
1273     ELVeneer*    CurrentVenEnt;
1274 
1275     /*---------- Free the ELVenEntry List  ----------*/
1276     CurrentVenEnt = MYObject->ELVenEntStart;
1277     while( CurrentVenEnt != NULL) {
1278         FwdVenEnt = CurrentVenEnt;
1279         CurrentVenEnt = CurrentVenEnt->next;
1280         (void)ELi_UNREGISTER_VENEER_INFO( ISTDRELOCATIONPROC_AUTO, ISTDVENEERTYPE_AUTO, FwdVenEnt->adr, (elElfDesc != i_eldesc_sim));
1281         OSAPI_FREE( FwdVenEnt);              //Structure itself
1282     }
1283     MYObject->ELVenEntStart = NULL;
1284     /*------------------------------------*/
1285 
1286     /*---------- Free the ELVenEntry List  ----------*/
1287     CurrentVenEnt = MYObject->ELV4tVenEntStart;
1288     while( CurrentVenEnt != NULL) {
1289         FwdVenEnt = CurrentVenEnt;
1290         CurrentVenEnt = CurrentVenEnt->next;
1291         (void)ELi_UNREGISTER_VENEER_INFO( ISTDRELOCATIONPROC_AUTO, ISTDVENEERTYPE_AUTO, FwdVenEnt->adr, (elElfDesc != i_eldesc_sim));
1292         OSAPI_FREE( FwdVenEnt);              //Structure itself
1293     }
1294     MYObject->ELV4tVenEntStart = NULL;
1295     /*------------------------------------*/
1296 
1297     return NULL;
1298 }
1299 
1300 /*------------------------------------------------------
1301   Check whether the difference of two address values fits in (+threshold) to (-threshold)
1302 
1303  -----------------------------------------------------*/
1304 static BOOL ELi_IsFar( u32 P, u32 S, s32 threshold)
1305 {
1306     s32 diff;
1307 
1308     diff = (s32)S - (s32)(P);
1309     if( (diff < threshold)&&( diff > -threshold)) {
1310         return( FALSE); //Near
1311     }else{
1312         return( TRUE);  //Far
1313     }
1314 }
1315