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