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