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