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