1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - ELF Loader
3   File:     elf.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 "el_config.h"
19 
20 #ifdef SDK_TWL
21 #include <twl.h>
22 #else
23 #include <nitro.h>
24 #endif
25 
26 #include "elf.h"
27 
28 
29 static int  endian;
30 static BOOL load_strndx_done = FALSE;
31 
32 
33 /*---------------------------------------------------------
34  Read byte data
35  --------------------------------------------------------*/
load_elf32_byte(u8 * dest,u8 * org,int lsb)36 static u8 *load_elf32_byte(u8 *dest, u8 *org, int lsb)
37 {
38 #pragma unused(lsb)
39   u8 *temp_ptr;
40 
41   temp_ptr = (u8 *)org;
42   *dest = *temp_ptr;
43   temp_ptr++;
44 
45   return temp_ptr;
46 }
47 
48 /*---------------------------------------------------------
49  Read half-word data
50  --------------------------------------------------------*/
load_elf32_half(Elf32_Half * dest,u8 * org,int lsb)51 static u8 *load_elf32_half(Elf32_Half *dest, u8 *org, int lsb)
52 {
53   u8 *temp_ptr;
54 
55   temp_ptr = (u8 *)org;
56   if( lsb == ELFDATA2LSB ) {
57     *dest = (u16)((u16)(*temp_ptr) & 0x00ff);
58     temp_ptr++;
59     *dest |= ((u16)(*temp_ptr) << 8 ) & 0xff00;
60     temp_ptr++;
61   }
62   else /* ELFDATA2MSB */ {
63     *dest = (u16)(((u16)(*temp_ptr) << 8 ) & 0xff00);
64     temp_ptr++;
65     *dest |= ((u16)(*temp_ptr) & 0x00ff);
66     temp_ptr++;
67   }
68   return (void *)temp_ptr;
69 }
70 
71 /*---------------------------------------------------------
72  Read word data
73  --------------------------------------------------------*/
load_elf32_sword(Elf32_Sword * dest,u8 * org,int lsb)74 static u8 *load_elf32_sword(Elf32_Sword *dest, u8 *org, int lsb)
75 {
76   u8 *temp_ptr;
77   u32 temp;
78 
79   temp_ptr = (u8 *)org;
80   if( lsb == ELFDATA2LSB ) {
81     temp = ((u32)(*temp_ptr) & 0x000000ff);
82     temp_ptr++;
83     temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
84     temp_ptr++;
85     temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
86     temp_ptr++;
87     temp |= (((u32)(*temp_ptr) << 24 ) & 0xff000000);
88     temp_ptr++;
89   }
90   else /* ELFDATA2MSB */ {
91     temp = (((u32)(*temp_ptr) << 24 ) & 0xff000000);
92     temp_ptr++;
93     temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
94     temp_ptr++;
95     temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
96     temp_ptr++;
97     temp |= ((u32)(*temp_ptr) & 0x000000ff);
98     temp_ptr++;
99   }
100   *dest = *( (Elf32_Sword *)&temp );
101   return (void *)temp_ptr;
102 }
103 
104 
load_elf32_word(Elf32_Word * dest,u8 * org,int lsb)105 static u8 *load_elf32_word(Elf32_Word *dest, u8 *org, int lsb)
106 {
107   u8 *temp_ptr;
108   temp_ptr = (u8 *)org;
109   if( lsb == ELFDATA2LSB ) {
110     *dest = ((u32)(*temp_ptr) & 0x000000ff);
111     temp_ptr++;
112     *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
113     temp_ptr++;
114     *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
115     temp_ptr++;
116     *dest |= (((u32)(*temp_ptr) << 24 ) & 0xff000000);
117     temp_ptr++;
118   }
119   else /* ELFDATA2MSB */ {
120     *dest = (((u32)(*temp_ptr) << 24 ) & 0xff000000);
121     temp_ptr++;
122     *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
123     temp_ptr++;
124     *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
125     temp_ptr++;
126     *dest |= ((u32)(*temp_ptr) & 0x000000ff);
127     temp_ptr++;
128   }
129   return (void *)temp_ptr;
130 }
131 
132 /*---------------------------------------------------------
133  Read ELF header
134 
135     buf: Address of ELF header
136     ehdr: Buffer for writing read data
137  --------------------------------------------------------*/
ELF_LoadELFHeader(const void * buf,Elf32_Ehdr * ehdr)138 void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr)
139 {
140     u8 *file_ptr;
141 
142     if( !buf ) {
143         return NULL;
144     }
145 
146     file_ptr = (u8 *)buf;
147 
148     /* Copy to buffer */
149     OSAPI_CPUCOPY8( (void*)file_ptr, ehdr->e_ident, EI_NIDENT);
150     file_ptr += EI_NIDENT;
151 
152     /* Magic Number */
153     if( ehdr->e_ident[EI_MAG0] != ELFMAG0 ) {
154         return NULL;
155     }
156     if( ehdr->e_ident[EI_MAG1] != ELFMAG1 ) {
157         return NULL;
158     }
159     if( ehdr->e_ident[EI_MAG2] != ELFMAG2 ) {
160         return NULL;
161     }
162     if( ehdr->e_ident[EI_MAG3] != ELFMAG3 ) {
163         return NULL;
164     }
165 
166     /* CLASS */
167     switch( ehdr->e_ident[EI_CLASS] ) {
168       case ELFCLASSNONE:
169         break;
170       case ELFCLASS32:
171         break;
172       case ELFCLASS64:
173         break;
174       default:
175         break;
176     }
177 
178     /* DATA */
179     switch( ehdr->e_ident[EI_DATA] ) {
180       case ELFDATANONE:
181         break;
182       case ELFDATA2LSB:
183         endian = ELFDATA2LSB;
184         break;
185       case ELFDATA2MSB:
186         endian = ELFDATA2MSB;
187         break;
188       default:
189         break;
190     }
191 
192     /* TYPE */
193     file_ptr = load_elf32_half(&(ehdr->e_type), file_ptr, endian);
194     switch( ehdr->e_type ) {
195       case ET_NONE:
196         break;
197       case ET_REL:
198         break;
199       case ET_EXEC:
200         break;
201       case ET_DYN:
202         break;
203       case ET_CORE:
204         break;
205       case ET_LOPROC:
206         break;
207       case ET_HIPROC:
208         break;
209       default:
210         break;
211     }
212 
213     /*---------- ELF Header Display  ----------*/
214     PRINTDEBUG( "\nELF Header:\n");
215     file_ptr = load_elf32_half(&(ehdr->e_machine), file_ptr, endian);
216     PRINTDEBUG("e_machine = %d\n",ehdr->e_machine);
217 
218     file_ptr = load_elf32_word(&(ehdr->e_version), file_ptr, endian);
219     PRINTDEBUG("e_version = %d\n",ehdr->e_version);
220 
221     file_ptr = load_elf32_word(&(ehdr->e_entry), file_ptr, endian);
222     PRINTDEBUG("e_entry(entry point) = 0x%08x\n",ehdr->e_entry);
223 
224     file_ptr = load_elf32_word(&(ehdr->e_phoff), file_ptr, endian);
225     PRINTDEBUG("e_phoff(program header offset) = 0x%08x\n",ehdr->e_phoff);
226 
227     file_ptr = load_elf32_word(&(ehdr->e_shoff), file_ptr, endian);
228     PRINTDEBUG("e_shoff(section header offset) = 0x%08x\n",ehdr->e_shoff);
229 
230     file_ptr = load_elf32_word(&(ehdr->e_flags), file_ptr, endian);
231     PRINTDEBUG("e_flags = 0x%08x\n",ehdr->e_flags);
232     if( ehdr->e_flags & EF_ARM_HASENTRY ) {
233         PRINTDEBUG("has entry\n");
234     }
235     if( ehdr->e_flags & EF_ARM_SYMSARESORTED ) {
236         PRINTDEBUG("symbols are sorted\n");
237     }
238     if( ehdr->e_flags & EF_ARM_DYNSYMSUSESEGIDX ) {
239         PRINTDEBUG("dynamic symbols use segmnet index\n");
240     }
241     if( ehdr->e_flags & EF_ARM_MAPSYMSFIRST ) {
242         PRINTDEBUG("map symbols first\n");
243     }
244     PRINTDEBUG("EABI version %x \n", (ehdr->e_flags & EF_ARM_EABIMASK) >> 24 );
245 
246 
247     file_ptr = load_elf32_half(&(ehdr->e_ehsize), file_ptr, endian);
248     PRINTDEBUG("e_ehsize = %d\n",ehdr->e_ehsize);
249 
250     file_ptr = load_elf32_half(&(ehdr->e_phentsize), file_ptr, endian);
251     PRINTDEBUG("e_phentsize = %d\n",ehdr->e_phentsize);
252 
253     file_ptr = load_elf32_half(&(ehdr->e_phnum), file_ptr, endian);
254     PRINTDEBUG("e_phnum = %d\n",ehdr->e_phnum);
255 
256     file_ptr = load_elf32_half(&(ehdr->e_shentsize), file_ptr, endian);
257     PRINTDEBUG("e_shentsize = %d\n",ehdr->e_shentsize);
258 
259     file_ptr = load_elf32_half(&(ehdr->e_shnum), file_ptr, endian);
260     PRINTDEBUG("e_shnum = %d\n",ehdr->e_shnum);
261 
262     file_ptr = load_elf32_half(&(ehdr->e_shstrndx), file_ptr, endian);
263     PRINTDEBUG("e_shstrndx(section index no. of the section header string table section = %d\n",ehdr->e_shstrndx);
264     PRINTDEBUG( "\n");
265     /*-----------------------------------*/
266 
267     return file_ptr;
268 }
269 
270 
271 /*---------------------------------------------------------
272  Relocation Entry Load
273  --------------------------------------------------------*/
ELF_LoadRel(const void * buf,Elf32_Rel * rel)274 static void *ELF_LoadRel(const void *buf, Elf32_Rel *rel)
275 {
276     u8 *file_ptr;
277 
278     if( !buf ) {
279         return NULL;
280     }
281 
282     file_ptr = (u8 *)buf;
283     file_ptr = load_elf32_word(&(rel->r_offset), file_ptr, endian);
284     file_ptr = load_elf32_word(&(rel->r_info), file_ptr, endian);
285 
286     return file_ptr;
287 }
288 
ELF_LoadRela(const void * buf,Elf32_Rela * rela)289 static void *ELF_LoadRela(const void *buf, Elf32_Rela *rela)
290 {
291     u8 *file_ptr;
292 
293     if( !buf ) {
294         return NULL;
295     }
296 
297     file_ptr = (u8 *)buf;
298     file_ptr = load_elf32_word(&(rela->r_offset), file_ptr, endian);
299     file_ptr = load_elf32_word(&(rela->r_info), file_ptr, endian);
300     file_ptr = load_elf32_sword(&(rela->r_addend), file_ptr, endian);
301 
302     return file_ptr;
303 }
304 
305 
306 /*---------------------------------------------------------
307  Symbol Table Entry Load
308     buf: Pointer to buffer to load the symbol entry
309     sym: Header address of load source symbol entry
310  --------------------------------------------------------*/
ELF_LoadSymbol(const void * buf,Elf32_Sym * sym)311 static void *ELF_LoadSymbol(const void *buf, Elf32_Sym *sym)
312 {
313     u8 *file_ptr;
314 
315     if( !buf ) {
316         return NULL;
317     }
318 
319     file_ptr = (u8 *)buf;
320     file_ptr = load_elf32_word(&(sym->st_name), file_ptr, endian);
321     file_ptr = load_elf32_word(&(sym->st_value), file_ptr, endian);
322     file_ptr = load_elf32_word(&(sym->st_size), file_ptr, endian);
323     file_ptr = load_elf32_byte(&(sym->st_info), file_ptr, endian);
324     file_ptr = load_elf32_byte(&(sym->st_other), file_ptr, endian);
325     file_ptr = load_elf32_half(&(sym->st_shndx), file_ptr, endian);
326 
327     return file_ptr;
328 }
329 
330 
331 /*---------------------------------------------------------
332  Section Header Load
333     buf: Pointer to buffer to load the section header
334     shdr: Starting address of load source section header
335  --------------------------------------------------------*/
ELF_LoadSectionHeader(const void * buf,Elf32_Shdr * shdr)336 static void *ELF_LoadSectionHeader(const void *buf,Elf32_Shdr *shdr)
337 {
338     u8 *file_ptr;
339 
340     if( !buf ) {
341         return NULL;
342     }
343 
344     file_ptr = (u8 *)buf;
345     file_ptr = load_elf32_word(&(shdr->sh_name), file_ptr, endian);
346     file_ptr = load_elf32_word(&(shdr->sh_type), file_ptr, endian);
347     file_ptr = load_elf32_word(&(shdr->sh_flags), file_ptr, endian);
348     file_ptr = load_elf32_word(&(shdr->sh_addr), file_ptr, endian);
349     file_ptr = load_elf32_word(&(shdr->sh_offset), file_ptr, endian);
350     file_ptr = load_elf32_word(&(shdr->sh_size), file_ptr, endian);
351     file_ptr = load_elf32_word(&(shdr->sh_link), file_ptr, endian);
352     file_ptr = load_elf32_word(&(shdr->sh_info), file_ptr, endian);
353     file_ptr = load_elf32_word(&(shdr->sh_addralign), file_ptr, endian);
354     file_ptr = load_elf32_word(&(shdr->sh_entsize ), file_ptr, endian);
355 
356     return file_ptr;
357 }
358