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-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "loader_subset.h"
22
23
24 extern ELUnresolvedEntry* ELUnrEntStart;
25
26 extern u16 dbg_print_flag;
27 extern u32 unresolved_table_block_flag;
28
29
30 //Use the following statements to determine whether the processor is ARM7.
31 //#ifdef SDK_ARM7
32 //#endif /*SDK_ARM7*/
33
34
35 /*------------------------------------------------------
36 Align the addresses
37 -----------------------------------------------------*/
38 #define ALIGN( addr, align_size ) (((addr) & ~((align_size) - 1)) + (align_size))
39
40 static u32 ELi_ALIGN( u32 addr, u32 align_size);
ELi_ALIGN(u32 addr,u32 align_size)41 u32 ELi_ALIGN( u32 addr, u32 align_size)
42 {
43 u32 aligned_addr;
44
45 if( (addr % align_size) == 0) {
46 aligned_addr = addr;
47 }else{
48 aligned_addr = (((addr) & ~((align_size) - 1)) + (align_size));
49 }
50
51 return aligned_addr;
52 }
53
54
55 /*------------------------------------------------------
56 Copy the section to the buffer
57 -----------------------------------------------------*/
ELi_CopySectionToBuffer(ELHandle * ElfHandle,Elf32_Shdr * Shdr)58 void* ELi_CopySectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr)
59 {
60 u32 load_start;
61 Elf32_Addr sh_size;
62
63 /*Align*/
64 // load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign));
65 load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
66 /*Set size*/
67 sh_size = Shdr->sh_size;
68
69 /*copy*/
70 ElfHandle->ELi_ReadStub( (void*)load_start,
71 ElfHandle->FileStruct,
72 (u32)(ElfHandle->ar_head),
73 (u32)(ElfHandle->elf_offset)+(u32)(Shdr->sh_offset),
74 sh_size);
75
76 /*Move the buffer pointer*/
77 ElfHandle->buf_current = (void*)(load_start + sh_size);
78
79 /*Return the loaded header address*/
80 return (void*)load_start;
81 }
82
83
84 /*------------------------------------------------------
85 Allocate a section in the buffer (do not copy) and embed a 0 for that region.
86
87 -----------------------------------------------------*/
ELi_AllocSectionToBuffer(ELHandle * ElfHandle,Elf32_Shdr * Shdr)88 void* ELi_AllocSectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr)
89 {
90 u32 load_start;
91 Elf32_Addr sh_size;
92
93 /*Align*/
94 // load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign));
95 load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
96 /*Set size*/
97 sh_size = Shdr->sh_size;
98
99 /*Move the buffer pointer*/
100 ElfHandle->buf_current = (void*)(load_start + sh_size);
101
102 /*Embed with 0 (because .bss section is expected)*/
103 memset( (void*)load_start, 0, sh_size);
104
105 /*Return the allocated header address */
106 return (void*)load_start;
107 }
108
109
110 /*------------------------------------------------------
111 Get section header for the specified index to the buffer
112 -----------------------------------------------------*/
ELi_GetShdr(ELHandle * ElfHandle,u32 index,Elf32_Shdr * Shdr)113 void ELi_GetShdr( ELHandle* ElfHandle, u32 index, Elf32_Shdr* Shdr)
114 {
115 u32 offset;
116
117 offset = (ElfHandle->CurrentEhdr.e_shoff) + ((u32)(ElfHandle->shentsize) * index);
118
119 ElfHandle->ELi_ReadStub( Shdr,
120 ElfHandle->FileStruct,
121 (u32)(ElfHandle->ar_head),
122 (u32)(ElfHandle->elf_offset) + offset,
123 sizeof( Elf32_Shdr));
124 }
125
126 /*------------------------------------------------------
127 Get section entry for the specified index to the buffer
128 -----------------------------------------------------*/
ELi_GetSent(ELHandle * ElfHandle,u32 index,void * entry_buf,u32 offset,u32 size)129 void ELi_GetSent( ELHandle* ElfHandle, u32 index, void* entry_buf, u32 offset, u32 size)
130 {
131 Elf32_Shdr Shdr;
132 //u32 entry_adr;
133
134 ELi_GetShdr( ElfHandle, index, &Shdr);
135
136 ElfHandle->ELi_ReadStub( entry_buf,
137 ElfHandle->FileStruct,
138 (u32)(ElfHandle->ar_head),
139 (u32)(ElfHandle->elf_offset) + (u32)(Shdr.sh_offset) + offset,
140 size);
141 }
142
143
144 /*------------------------------------------------------
145 Get specified index entry gpt the specified section header to the buffer.
146 (Only section with a fixed entry size, such as Rel, Rela, Sym, and the like.)
147 Shdr: Specified section header
148 index: Entry number (from 0)
149 -----------------------------------------------------*/
ELi_GetEntry(ELHandle * ElfHandle,Elf32_Shdr * Shdr,u32 index,void * entry_buf)150 void ELi_GetEntry( ELHandle* ElfHandle, Elf32_Shdr* Shdr, u32 index, void* entry_buf)
151 {
152 u32 offset;
153
154 offset = (u32)(Shdr->sh_offset) + ((Shdr->sh_entsize) * index);
155
156 ElfHandle->ELi_ReadStub( entry_buf,
157 ElfHandle->FileStruct,
158 (u32)(ElfHandle->ar_head),
159 (u32)(ElfHandle->elf_offset) + offset,
160 Shdr->sh_entsize);
161 }
162
163 /*------------------------------------------------------
164 Get specified index character string of the STR section header
165
166 Shdr: Specified section header
167 index: Entry index (from 0)
168 -----------------------------------------------------*/
ELi_GetStrAdr(ELHandle * ElfHandle,u32 strsh_index,u32 ent_index,char * str,u32 len)169 void ELi_GetStrAdr( ELHandle* ElfHandle, u32 strsh_index, u32 ent_index, char* str, u32 len)
170 {
171 /*Header address of the string entry*/
172 ELi_GetSent( ElfHandle, strsh_index, str, ent_index, len);
173 }
174
175 /*------------------------------------------------------
176 Redefine symbol.
177
178 <Rel section header>
179 RelShdr->sh_link: Symbol section number
180 RelShdr->sh_info: Target section number (ex.: Representing .text of rel.text)
181
182 <Rel entry>
183 Rel->r_offset: Offset address in target section.
184 ELF32_R_SYM( Rel->r_info): Symbol entry number.
185 ELF32_R_TYPE( Rel->r_info): Relocate type.
186
187 <Sym section header>
188 SymShdr->sh_link: Character string table section number of symbol
189
190 <Sym entry>
191 Sym->st_name : Character string entry number of symbol
192 Sym->st_value : Offset address in section to which the symbol belongs
193 Sym->st_size : Size in section to which the symbol belongs
194 Sym->st_shndx: Section number to which the symbol belongs
195 ELF32_ST_BIND (Sym->st_info) : Bind (Local or Global)
196 ELF32_ST_TYPE( Sym->st_info) : Type (Target associated with the symbol)
197 -----------------------------------------------------*/
ELi_RelocateSym(ELHandle * ElfHandle,u32 relsh_index)198 void ELi_RelocateSym( ELHandle* ElfHandle, u32 relsh_index)
199 {
200 u32 i;
201 u32 num_of_sym; //Overall symbol count
202 u32 num_of_rel; //Number of symbols that should be redefined
203 Elf32_Shdr RelOrRelaShdr; //REL or RELA section header
204 Elf32_Rela CurrentRela; //REL or RELA entry copy destination
205 Elf32_Shdr* SymShdr;
206 ELSymEx* CurrentSymEx;
207 ELSymEx* FwdSymEx;
208 ELSymEx DmySymEx;
209 ELShdrEx* TargetShdrEx;
210 ELShdrEx* CurrentShdrEx;
211 u32 relocation_adr;
212 char sym_str[128];
213 u32 copy_size;
214 ELAdrEntry* CurrentAdrEntry;
215 u32 sym_loaded_adr;
216 ELAdrEntry* ExportAdrEntry;
217 u32 thumb_func_flag;
218 ELUnresolvedEntry UnresolvedInfo;
219 ELUnresolvedEntry* UnrEnt;
220 u32 unresolved_num = 0;
221
222 /*Get REL or RELA section header*/
223 ELi_GetShdr( ElfHandle, relsh_index, &RelOrRelaShdr);
224
225 /*REL section and SYM section have 1:1 correspondence.*/
226 ELi_GetShdr( ElfHandle, RelOrRelaShdr.sh_link, &(ElfHandle->SymShdr));
227 SymShdr = &(ElfHandle->SymShdr);
228 if( dbg_print_flag == 1) {
229 printf( "SymShdr->link:%02x, SymShdr->info:%02x\n",
230 (int)(SymShdr->sh_link), (int)(SymShdr->sh_info));
231 }
232
233 /*Target section EX header*/
234 TargetShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, RelOrRelaShdr.sh_info);
235
236 num_of_rel = (RelOrRelaShdr.sh_size) / (RelOrRelaShdr.sh_entsize); //Number of symbols that should be redefined
237 num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize); //Overall symbol count
238
239 /*---------- Create ELSymEx List ----------*/
240 CurrentSymEx = &DmySymEx;
241 for( i=0; i<num_of_sym; i++) {
242 CurrentSymEx->next = (void*)(malloc( sizeof(ELSymEx)));
243 CurrentSymEx = (ELSymEx*)(CurrentSymEx->next);
244
245 /*Copy symbol entry*/
246 ELi_GetEntry( ElfHandle, SymShdr, i, &(CurrentSymEx->Sym));
247
248 /*Set debug information flag*/
249 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx);
250 if( CurrentShdrEx) {
251 CurrentSymEx->debug_flag = CurrentShdrEx->debug_flag;
252 }else{
253 CurrentSymEx->debug_flag = 0;
254 }
255
256 // printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx);
257 }
258 CurrentSymEx->next = NULL;
259 ElfHandle->SymEx = DmySymEx.next;
260 /*-------------------------------------------*/
261
262 /*----- Set the ELSymEx Thumb flag (Only the function symbol is required) -----*/
263 CurrentSymEx = ElfHandle->SymEx;
264 for( i=0; i<num_of_sym; i++) {
265 if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) {
266 CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( ElfHandle, CurrentSymEx->Sym.st_shndx,
267 CurrentSymEx->Sym.st_value));
268 }else{
269 CurrentSymEx->thumb_flag = 0;
270 }
271 CurrentSymEx = CurrentSymEx->next;
272 }
273 /*---------------------------------------------------------------*/
274
275 /*--- Redefine symbols that must be redefined ---*/
276 for( i=0; i<num_of_rel; i++) {
277
278 /*- Get Rel or Rela Entry -*/
279 ELi_GetEntry( ElfHandle, &RelOrRelaShdr, i, &CurrentRela);
280
281 if( RelOrRelaShdr.sh_type == SHT_REL) {
282 CurrentRela.r_addend = 0;
283 }
284 /*-----------------------------*/
285
286 /*Get symbol Ex entry*/
287 CurrentSymEx = ELi_GetSymExfromList( ElfHandle->SymEx,
288 ELF32_R_SYM( CurrentRela.r_info));
289
290 if( CurrentSymEx->debug_flag == 1) { /*When it is debugging information*/
291 }else{ /*When not debugging information*/
292 /**/
293 ELi_UnresolvedInfoInit( &UnresolvedInfo);
294 /*Rewritten address (Called P in the specifications)*/
295 relocation_adr = (TargetShdrEx->loaded_adr) + (CurrentRela.r_offset);
296 UnresolvedInfo.r_type = ELF32_R_TYPE( CurrentRela.r_info);
297 UnresolvedInfo.A_ = (CurrentRela.r_addend);
298 UnresolvedInfo.P_ = (relocation_adr);
299 UnresolvedInfo.sh_type = (RelOrRelaShdr.sh_type);
300
301 /*Identify the symbol address*/
302 if( CurrentSymEx->Sym.st_shndx == SHN_UNDEF) {
303 /*Search from address table*/
304 ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128);
305 CurrentAdrEntry = EL_GetAdrEntry( sym_str);
306 if( CurrentAdrEntry) {
307 sym_loaded_adr = (u32)(CurrentAdrEntry->adr);
308 /*THUMB function flag (called T in the specifications) to differentiate THUMB or ARM*/
309 thumb_func_flag = CurrentAdrEntry->thumb_flag;
310 if( dbg_print_flag == 1) {
311 printf( "\n symbol found %s : %8x\n", sym_str, (int)(sym_loaded_adr));
312 }
313 }else{
314 /*Error when not found (Cannot resolve S_ and T_)*/
315 copy_size = (u32)strlen( sym_str) + 1;
316 UnresolvedInfo.sym_str = (char*)(malloc( copy_size));
317 //MI_CpuCopy8( sym_str, UnresolvedInfo.sym_str, copy_size);
318 memcpy( UnresolvedInfo.sym_str, sym_str, copy_size);
319
320 /*Added to global unresolved table*/
321 copy_size = sizeof( ELUnresolvedEntry);
322 UnrEnt = (ELUnresolvedEntry*)(malloc( copy_size));
323 //MI_CpuCopy8( &UnresolvedInfo, UnrEnt, copy_size);
324 memcpy( UnrEnt, &UnresolvedInfo, copy_size);
325
326 if( unresolved_table_block_flag == 0) { //If adding to the table is not prohibited
327 ELi_AddUnresolvedEntry( UnrEnt);
328 }
329
330 unresolved_num++; /*Count number of unresolved symbols*/
331 if( dbg_print_flag == 1) {
332 printf( "WARNING! cannot find symbol : %s\n", sym_str);
333 }
334 }
335 }else{
336 /*Get Ex header of section where symbol belongs*/
337 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx);
338 sym_loaded_adr = CurrentShdrEx->loaded_adr;
339 sym_loaded_adr += CurrentSymEx->Sym.st_value; //sym_loaded_adr is called S in the specifications
340 /*THUMB function flag (called T in the specifications) to differentiate THUMB or ARM*/
341 thumb_func_flag = CurrentSymEx->thumb_flag;
342 }
343
344 if( !UnresolvedInfo.sym_str) { /*Symbol cannot be resolved if sym_str is not set*/
345 /*Set to same variable name as in the specifications*/
346 UnresolvedInfo.S_ = (sym_loaded_adr);
347 UnresolvedInfo.T_ = (thumb_func_flag);
348
349 /*--------------- Resolve symbol (Execute Relocation) ---------------*/
350 // CurrentSymEx->relocation_val = ELi_DoRelocate( &UnresolvedInfo);
351 /*------------------------------------------------------------*/
352 }
353 }
354 }
355 /*-----------------------------------*/
356 /*--- Made GLOBAL symbol in library public to address table ---*/
357 for( i=0; i<num_of_sym; i++) {
358 CurrentSymEx = ELi_GetSymExfromList( ElfHandle->SymEx, i);
359 /*When global and the related section exist in the library*/
360 if( ((ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) ||
361 (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_WEAK) ||
362 (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_MW_SPECIFIC))&&
363 (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) {
364
365 ExportAdrEntry = (ELAdrEntry*)(malloc( sizeof(ELAdrEntry))); /*Memory allocation*/
366
367 ExportAdrEntry->next = NULL;
368
369 ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128);
370 copy_size = (u32)strlen( sym_str) + 1;
371 ExportAdrEntry->name = (char*)(malloc( copy_size));
372 //MI_CpuCopy8( sym_str, ExportAdrEntry->name, copy_size);
373 memcpy( ExportAdrEntry->name, sym_str, copy_size);
374
375 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx);
376 //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.
377 ExportAdrEntry->adr = (void*)(CurrentShdrEx->loaded_adr + ((CurrentSymEx->Sym.st_value)&0xFFFFFFFE));
378 ExportAdrEntry->func_flag = (u16)(ELF32_ST_TYPE( CurrentSymEx->Sym.st_info));
379 ExportAdrEntry->thumb_flag = CurrentSymEx->thumb_flag;
380
381 if( EL_GetAdrEntry( ExportAdrEntry->name) == NULL) { //If not in
382 if( dbg_print_flag == 1) {
383 printf( "Add Entry : %s(0x%x), func=%d, thumb=%d\n",
384 ExportAdrEntry->name,
385 (int)(ExportAdrEntry->adr),
386 ExportAdrEntry->func_flag,
387 ExportAdrEntry->thumb_flag);
388 }
389 EL_AddAdrEntry( ExportAdrEntry); //registration
390 }
391 }
392 }
393 /*----------------------------------------------------------------*/
394
395 /*---------- Free the ELSymEx List ----------*/
396 CurrentSymEx = ElfHandle->SymEx;
397 if( CurrentSymEx) {
398 while( CurrentSymEx->next != NULL) {
399 FwdSymEx = CurrentSymEx;
400 CurrentSymEx = CurrentSymEx->next;
401 free( FwdSymEx);
402 }
403 ElfHandle->SymEx = NULL;
404 }
405 /*-----------------------------------------*/
406
407 /* After completing relocation */
408 if( unresolved_num == 0) {
409 ElfHandle->process = EL_RELOCATED;
410 }
411 }
412
413 /*------------------------------------------------------
414 makelst-specific function
415 Register global items to address table from the symbol section
416
417 -----------------------------------------------------*/
ELi_DiscriminateGlobalSym(ELHandle * ElfHandle,u32 symsh_index)418 void ELi_DiscriminateGlobalSym( ELHandle* ElfHandle, u32 symsh_index)
419 {
420 u32 i;
421 u32 num_of_sym;
422 Elf32_Shdr CurrentSymShdr;
423 Elf32_Shdr* SymShdr; //SYM section header
424 ELSymEx* CurrentSymEx;
425 ELSymEx* FwdSymEx;
426 ELSymEx DmySymEx;
427 ELShdrEx* CurrentShdrEx;
428 ELAdrEntry* ExportAdrEntry;
429 char sym_str[128];
430 u32 copy_size;
431
432 /*Get SYM section header*/
433 ELi_GetShdr( ElfHandle, symsh_index, &CurrentSymShdr);
434 SymShdr = &CurrentSymShdr;
435
436 num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize); //Overall symbol count
437
438 /*---------- Create ELSymEx List ----------*/
439 CurrentSymEx = &DmySymEx;
440 for( i=0; i<num_of_sym; i++) {
441 CurrentSymEx->next = (void*)(malloc( sizeof(ELSymEx)));
442 CurrentSymEx = (ELSymEx*)(CurrentSymEx->next);
443
444 /*Copy symbol entry*/
445 ELi_GetEntry( ElfHandle, SymShdr, i, &(CurrentSymEx->Sym));
446
447 /*Set debug information flag*/
448 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx);
449 if( CurrentShdrEx) {
450 CurrentSymEx->debug_flag = CurrentShdrEx->debug_flag;
451 }else{
452 CurrentSymEx->debug_flag = 0;
453 }
454
455 // printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx);
456 }
457 CurrentSymEx->next = NULL;
458 ElfHandle->SymEx = DmySymEx.next;
459 /*-------------------------------------------*/
460
461 /*----- Set the ELSymEx Thumb flag (Only the function symbol is required) -----*/
462 CurrentSymEx = ElfHandle->SymEx;
463 for( i=0; i<num_of_sym; i++) {
464 if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) {
465 CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( ElfHandle, CurrentSymEx->Sym.st_shndx,
466 CurrentSymEx->Sym.st_value));
467 }else{
468 CurrentSymEx->thumb_flag = 0;
469 }
470 CurrentSymEx = CurrentSymEx->next;
471 }
472 /*---------------------------------------------------------------*/
473 /*--- Made GLOBAL symbol in library public to address table ---*/
474 for( i=0; i<num_of_sym; i++) {
475 CurrentSymEx = ELi_GetSymExfromList( ElfHandle->SymEx, i);
476 /*When global and the related section exist in the library*/
477 if( ((ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) ||
478 (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_WEAK) ||
479 (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_MW_SPECIFIC))&&
480 (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) {
481
482 ExportAdrEntry = (ELAdrEntry*)(malloc( sizeof(ELAdrEntry))); /*Memory allocation*/
483
484 ExportAdrEntry->next = NULL;
485
486 ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128);
487 copy_size = (u32)strlen( sym_str) + 1;
488 ExportAdrEntry->name = (char*)(malloc( copy_size));
489 //MI_CpuCopy8( sym_str, ExportAdrEntry->name, copy_size);
490 memcpy( ExportAdrEntry->name, sym_str, copy_size);
491
492 if( (CurrentSymEx->Sym.st_shndx) < SHN_LORESERVE) { //When there is a related section
493 if( (CurrentSymEx->Sym.st_shndx == SHN_ABS)) {
494 //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.
495 ExportAdrEntry->adr = (void*)((CurrentSymEx->Sym.st_value)&0xFFFFFFFE);
496 }else{
497 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx);
498 //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.
499 ExportAdrEntry->adr = (void*)(CurrentShdrEx->loaded_adr + ((CurrentSymEx->Sym.st_value)&0xFFFFFFFE));
500 }
501 ExportAdrEntry->func_flag = (u16)(ELF32_ST_TYPE( CurrentSymEx->Sym.st_info));
502 ExportAdrEntry->thumb_flag = CurrentSymEx->thumb_flag;
503
504 if( EL_GetAdrEntry( ExportAdrEntry->name) == NULL) { //If not in
505 if( dbg_print_flag == 1) {
506 printf( "Add Entry : %s(0x%x), func=%d, thumb=%d\n",
507 ExportAdrEntry->name,
508 (int)(ExportAdrEntry->adr),
509 ExportAdrEntry->func_flag,
510 ExportAdrEntry->thumb_flag);
511 }
512 EL_AddAdrEntry( ExportAdrEntry); //registration
513 }
514 }
515 }
516 }
517 /*----------------------------------------------------------------*/
518
519 /*---------- Free the ELSymEx List ----------*/
520 CurrentSymEx = ElfHandle->SymEx;
521 if( CurrentSymEx) {
522 while( CurrentSymEx->next != NULL) {
523 FwdSymEx = CurrentSymEx;
524 CurrentSymEx = CurrentSymEx->next;
525 free( FwdSymEx);
526 }
527 ElfHandle->SymEx = NULL;
528 }
529 /*-----------------------------------------*/
530 }
531
532
533 /*------------------------------------------------------
534 Resolve symbol based on unresolved information
535
536 It is necessary to know all of the r_type, S_, A_, P_, and T_
537 -----------------------------------------------------*/
538 #define _S_ (UnresolvedInfo->S_)
539 #define _A_ (UnresolvedInfo->A_)
540 #define _P_ (UnresolvedInfo->P_)
541 #define _T_ (UnresolvedInfo->T_)
ELi_DoRelocate(ELUnresolvedEntry * UnresolvedInfo)542 u32 ELi_DoRelocate( ELUnresolvedEntry* UnresolvedInfo)
543 {
544 s32 signed_val;
545 u32 relocation_val = 0;
546 u32 relocation_adr;
547
548 relocation_adr = _P_;
549
550 switch( (UnresolvedInfo->r_type)) {
551 case R_ARM_PC24:
552 case R_ARM_PLT32:
553 case R_ARM_CALL:
554 case R_ARM_JUMP24:
555 if( UnresolvedInfo->sh_type == SHT_REL) {
556 _A_ = (((*(vu32*)relocation_adr)|0xFF800000) << 2); //Generally, this should be -8
557 }
558 signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_);
559 if( _T_) { /*Jump from ARM to Thumb with BLX instruction (If less than v5, there must be a way to change a BX instruction into a BL instruction in a veneer)*/
560 relocation_val = (0xFA000000) | ((signed_val>>2) & 0x00FFFFFF) | (((signed_val>>1) & 0x1)<<24);
561 }else{ /*Jump from ARM to ARM using the BL instruction*/
562 signed_val >>= 2;
563 relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF);
564 }
565 *(vu32*)relocation_adr = relocation_val;
566 break;
567 case R_ARM_ABS32:
568 relocation_val = (( _S_ + _A_) | _T_);
569 *(vu32*)relocation_adr = relocation_val;
570 break;
571 case R_ARM_REL32:
572 relocation_val = (( _S_ + _A_) | _T_) - _P_;
573 *(vu32*)relocation_adr = relocation_val;
574 break;
575 case R_ARM_LDR_PC_G0:
576 signed_val = ( (s32)(_S_) + _A_) - (s32)(_P_);
577 signed_val >>= 2;
578 relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF);
579 *(vu32*)relocation_adr = relocation_val;
580 break;
581 case R_ARM_ABS16:
582 case R_ARM_ABS12:
583 case R_ARM_THM_ABS5:
584 case R_ARM_ABS8:
585 relocation_val = _S_ + _A_;
586 *(vu32*)relocation_adr = relocation_val;
587 break;
588 case R_ARM_THM_PC22:/*Different Name: R_ARM_THM_CALL*/
589 if( UnresolvedInfo->sh_type == SHT_REL) {
590 _A_ = (((*(vu16*)relocation_adr & 0x07FF)<<11) + ((*((vu16*)(relocation_adr)+1)) & 0x07FF));
591 _A_ = (_A_ | 0xFFC00000) << 1; //Generally, this should be -4 (Because the PC is the current instruction address +4)
592 }
593 signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_);
594 signed_val >>= 1;
595 if( _T_) { /*Jump from Thumb to Thumb using the BL instruction*/
596 relocation_val = ((*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF)) +
597 ((((*((vu16*)(relocation_adr)+1)) & 0xF800) | (signed_val & 0x07FF)) << 16);
598 }else{ /*Jump from Thumb to ARM with BLX instruction (If less than v5, there must be a way to change a BX instruction into a BL instruction in a veneer)*/
599 if( (signed_val & 0x1)) { //Come here when _P_ is not 4-byte aligned
600 signed_val += 1;
601 }
602 relocation_val = ((*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF)) +
603 ((((*((vu16*)(relocation_adr)+1)) & 0xE800) | (signed_val & 0x07FF)) << 16);
604 }
605 *(vu16*)relocation_adr = (vu16)relocation_val;
606 *((vu16*)relocation_adr+1) = (vu16)((u32)(relocation_val) >> 16);
607 break;
608 case R_ARM_THM_JUMP24:
609 break;
610 default:
611 if( dbg_print_flag == 1) {
612 printf( "ERROR! : unsupported relocation type!\n");
613 }
614 break;
615 }
616
617 return relocation_val;
618 }
619 #undef _S_
620 #undef _A_
621 #undef _P_
622 #undef _T_
623
624 /*------------------------------------------------------
625 Read ELSymEx of the index specified from the list.
626 -----------------------------------------------------*/
ELi_GetSymExfromList(ELSymEx * SymExStart,u32 index)627 ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index)
628 {
629 u32 i;
630 ELSymEx* SymEx;
631
632 SymEx = SymExStart;
633 for( i=0; i<index; i++) {
634 SymEx = (ELSymEx*)(SymEx->next);
635 if( SymEx == NULL) {
636 break;
637 }
638 }
639 return SymEx;
640 }
641
642 /*------------------------------------------------------
643 Read ELShdrx of the index specified from the list.
644 -----------------------------------------------------*/
ELi_GetShdrExfromList(ELShdrEx * ShdrExStart,u32 index)645 ELShdrEx* ELi_GetShdrExfromList( ELShdrEx* ShdrExStart, u32 index)
646 {
647 u32 i;
648 ELShdrEx* ShdrEx;
649
650 ShdrEx = ShdrExStart;
651 for( i=0; i<index; i++) {
652 ShdrEx = (ELShdrEx*)(ShdrEx->next);
653 if( ShdrEx == NULL) {
654 break;
655 }
656 }
657 return ShdrEx;
658 }
659
660
661
662 /*------------------------------------------------------
663 Determine whether the section for the specified index is debug information
664
665 <Definition of debugging information>
666 - Sections whose section name begins with .debug.
667
668 - Section, such as .rel.debug - section, where the sh_info indicates the debug information section number
669
670 -----------------------------------------------------*/
ELi_ShdrIsDebug(ELHandle * ElfHandle,u32 index)671 BOOL ELi_ShdrIsDebug( ELHandle* ElfHandle, u32 index)
672 {
673 Elf32_Shdr TmpShdr;
674 char shstr[6];
675
676 /*-- Get six characters of character string for section name --*/
677 ELi_GetShdr( ElfHandle, index, &TmpShdr);
678 ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
679 TmpShdr.sh_name, shstr, 6);
680 /*-------------------------------------*/
681
682 if( strncmp( shstr, ".debug", 6) == 0) { /*When debugging section*/
683 return TRUE;
684 }else{ /*When relocated section relates to the debugging section*/
685 if( (TmpShdr.sh_type == SHT_REL) || (TmpShdr.sh_type == SHT_RELA)) {
686 if( ELi_ShdrIsDebug( ElfHandle, TmpShdr.sh_info) == TRUE) {
687 return TRUE;
688 }
689 }
690 }
691
692 return FALSE;
693 }
694
695
696
697 /*------------------------------------------------------
698 Check the ElfHandle SymEx table, and determine whether the code in the specified offset of the specified index is ARM or THUMB
699
700 (Preset ElfHandle->SymShdr and ElfHandle->SymEx.)
701
702 sh_index: Section index to be checked
703 offset: Offset in section to check
704 -----------------------------------------------------*/
ELi_CodeIsThumb(ELHandle * ElfHandle,u16 sh_index,u32 offset)705 u32 ELi_CodeIsThumb( ELHandle* ElfHandle, u16 sh_index, u32 offset)
706 {
707 u32 i;
708 u32 thumb_flag;
709 Elf32_Shdr* SymShdr;
710 char str_adr[3];
711 ELSymEx* CurrentSymEx;
712
713 /*Get symbol section header and SymEx list*/
714 SymShdr = &(ElfHandle->SymShdr);
715 CurrentSymEx = ElfHandle->SymEx;
716
717 i = 0;
718 thumb_flag = 0;
719 while( CurrentSymEx != NULL) {
720
721 if( CurrentSymEx->Sym.st_shndx == sh_index) {
722 ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, str_adr, 3);
723 if( strncmp( str_adr, "$a\0", strlen("$a\0")) == 0) {
724 thumb_flag = 0;
725 }else if( strncmp( str_adr, "$t\0", strlen("$t\0")) == 0) {
726 thumb_flag = 1;
727 }
728 if( CurrentSymEx->Sym.st_value > offset) {
729 break;
730 }
731 }
732
733 CurrentSymEx = CurrentSymEx->next;
734 i++;
735 }
736
737 return thumb_flag;
738 }
739
740
741 /*---------------------------------------------------------
742 Initialize unresolved information entries
743 --------------------------------------------------------*/
ELi_UnresolvedInfoInit(ELUnresolvedEntry * UnresolvedInfo)744 void ELi_UnresolvedInfoInit( ELUnresolvedEntry* UnresolvedInfo)
745 {
746 UnresolvedInfo->sym_str = NULL;
747 UnresolvedInfo->r_type = 0;
748 UnresolvedInfo->S_ = 0;
749 UnresolvedInfo->A_ = 0;
750 UnresolvedInfo->P_ = 0;
751 UnresolvedInfo->T_ = 0;
752 UnresolvedInfo->remove_flag = 0;
753 }
754
755 /*------------------------------------------------------
756 Delete entry from the unresolved information table
757 -----------------------------------------------------*/
ELi_RemoveUnresolvedEntry(ELUnresolvedEntry * UnrEnt)758 BOOL ELi_RemoveUnresolvedEntry( ELUnresolvedEntry* UnrEnt)
759 {
760 ELUnresolvedEntry DmyUnrEnt;
761 ELUnresolvedEntry* CurrentUnrEnt;
762
763 if( UnrEnt == NULL) {
764 return FALSE;
765 }
766
767 DmyUnrEnt.next = ELUnrEntStart;
768 CurrentUnrEnt = &DmyUnrEnt;
769
770 while( CurrentUnrEnt->next != UnrEnt) {
771 if( CurrentUnrEnt->next == NULL) {
772 return FALSE;
773 }else{
774 CurrentUnrEnt = (ELUnresolvedEntry*)(CurrentUnrEnt->next);
775 }
776 }
777
778 CurrentUnrEnt->next = UnrEnt->next;
779 free( UnrEnt->sym_str);
780 free( UnrEnt);
781 ELUnrEntStart = DmyUnrEnt.next;
782
783 return TRUE;
784 }
785
786 /*---------------------------------------------------------
787 Add entry to the unresolved information table
788 --------------------------------------------------------*/
ELi_AddUnresolvedEntry(ELUnresolvedEntry * UnrEnt)789 void ELi_AddUnresolvedEntry( ELUnresolvedEntry* UnrEnt)
790 {
791 ELUnresolvedEntry DmyUnrEnt;
792 ELUnresolvedEntry* CurrentUnrEnt;
793
794 if( !ELUnrEntStart) {
795 ELUnrEntStart = UnrEnt;
796 }else{
797 DmyUnrEnt.next = ELUnrEntStart;
798 CurrentUnrEnt = &DmyUnrEnt;
799
800 while( CurrentUnrEnt->next != NULL) {
801 CurrentUnrEnt = CurrentUnrEnt->next;
802 }
803 CurrentUnrEnt->next = (void*)UnrEnt;
804 }
805 UnrEnt->next = NULL;
806 }
807
808 /*------------------------------------------------------
809 Search for entry corresponding to specified string in the unresolved information table
810 -----------------------------------------------------*/
ELi_GetUnresolvedEntry(char * ent_name)811 ELUnresolvedEntry* ELi_GetUnresolvedEntry( char* ent_name)
812 {
813 ELUnresolvedEntry* CurrentUnrEnt;
814
815 CurrentUnrEnt = ELUnrEntStart;
816 if( CurrentUnrEnt == NULL) {
817 return NULL;
818 }
819 while( 1) {
820 if( (strcmp( CurrentUnrEnt->sym_str, ent_name) == 0)&&
821 (CurrentUnrEnt->remove_flag == 0)) {
822 break;
823 }
824 CurrentUnrEnt = (ELUnresolvedEntry*)CurrentUnrEnt->next;
825 if( CurrentUnrEnt == NULL) {
826 break;
827 }
828 }
829 return CurrentUnrEnt;
830 }
831