1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ELF Loader
3 File: insertsection.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-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include "types.h"
19 #include "elf.h"
20 #include "elf_loader.h"
21 #include "arch.h"
22 #include "loader_subset.h"
23 #include <string.h>
24 #include <stdlib.h>
25
26
27
28 extern u32 ELi_ALIGN( u32 addr, u32 align_size);
29
30
31
ELi_LoadObject2(ELHandle * ElfHandle,void * obj_offset,void * buf)32 u16 ELi_LoadObject2( ELHandle* ElfHandle, void* obj_offset, void* buf)
33 {
34 u16 i;
35 #if (SPECIAL_SECTION_ENABLE == 1) /*Add special section*/
36 u16 j;
37 #endif
38 ELShdrEx* FwdShdrEx;
39 ELShdrEx* CurrentShdrEx;
40 ELShdrEx DmyShdrEx;
41 u32 newelf_shoff = 0; //Write pointer to stripped ELF image
42 u32 buf_shdr;
43 u32 section_num = 0;
44 u32 stripped_section_num = 0;
45 u32 tmp_buf;
46 u32 *shdr_table; //Table for new/old number correspondence for section headers
47 u32 special_sect_name;
48
49
50 /* Check initialization of ELHandle */
51 if( ElfHandle->process != EL_INITIALIZED) {
52 return EL_FAILED;
53 }
54 /* Buffer NULL check */
55 if( buf == NULL) {
56 return EL_FAILED;
57 }
58 /* Get ELF header */
59 ElfHandle->ELi_ReadStub( &(ElfHandle->CurrentEhdr), ElfHandle->FileStruct,
60 (u32)(ElfHandle->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr));
61
62 /* Section handle build */
63 ElfHandle->elf_offset = obj_offset;
64 ElfHandle->buf_current = (void*)((u32)buf + sizeof( Elf32_Ehdr));
65 ElfHandle->shentsize = ElfHandle->CurrentEhdr.e_shentsize;
66
67 /*Section header table build*/
68 shdr_table = (u32*)malloc( 4 * ElfHandle->CurrentEhdr.e_shnum);
69
70 /*---------- Create ELShdrEx and shdr_table Lists ----------*/
71 CurrentShdrEx = &DmyShdrEx;
72 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
73 CurrentShdrEx->next = (void*)(malloc( sizeof(ELShdrEx)));
74 CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
75 memset( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Clear zero
76
77 /*Set flag to distinguish whether this is debugging information*/
78 if( ELi_ShdrIsDebug( ElfHandle, i) == TRUE) { /*When it is debugging information*/
79 CurrentShdrEx->debug_flag = 1;
80 shdr_table[i] = 0xFFFFFFFF;
81 }else{ /*When not debugging information*/
82 CurrentShdrEx->debug_flag = 0;
83 shdr_table[i] = stripped_section_num; /*Create section new/old table*/
84 stripped_section_num++;
85 }
86 /*Copy section header*/
87 ELi_GetShdr( ElfHandle, i, &(CurrentShdrEx->Shdr));
88 // printf( "shdr_table[0x%x] = 0x%x\n", i, section_num);
89 section_num++;
90 /*Get section string*/
91 #if 0 // Do not dynamically ensure section string buffer
92 CurrentShdrEx->str = (char*)malloc( 128); //Get 128 character buffer
93 ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
94 CurrentShdrEx->Shdr.sh_name,
95 CurrentShdrEx->str, 128);
96 #else
97 {
98 u32 length;
99
100 length = ELi_GetStrLen( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx, CurrentShdrEx->Shdr.sh_name ) + 1;
101
102 CurrentShdrEx->str = (char*)malloc(length);
103 if(CurrentShdrEx->str == 0)
104 {
105 return EL_FAILED;
106 }
107 ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
108 CurrentShdrEx->Shdr.sh_name,
109 CurrentShdrEx->str, length);
110 }
111 #endif
112 /*Index maintenance of section name of special section*/
113 if( i == ElfHandle->CurrentEhdr.e_shstrndx){
114 special_sect_name = CurrentShdrEx->Shdr.sh_size;
115 }
116 }
117 #if (SPECIAL_SECTION_ENABLE == 1) /*Add special section*/
118 section_num++; //Add special section
119 ElfHandle->CurrentEhdr.e_shnum++; //Add special section
120 CurrentShdrEx->next = (void*)(malloc( sizeof(ELShdrEx)));
121 CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next);
122 memset( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Clear zero
123 CurrentShdrEx->Shdr.sh_name = special_sect_name;
124 CurrentShdrEx->Shdr.sh_type = SPECIAL_SECTION_TYPE;
125 CurrentShdrEx->Shdr.sh_flags = 0;
126 CurrentShdrEx->Shdr.sh_addr = 0;
127 CurrentShdrEx->Shdr.sh_offset = 0;
128 CurrentShdrEx->Shdr.sh_size = (stripped_section_num)*4; //(ElfHandle->CurrentEhdr.e_shnum)*4; (When old section number is in the index)
129 CurrentShdrEx->Shdr.sh_link = 0;
130 CurrentShdrEx->Shdr.sh_info = 0;
131 CurrentShdrEx->Shdr.sh_addralign = 4;
132 CurrentShdrEx->Shdr.sh_entsize = 4;
133 #if 0 // Do not dynamically allocate section string buffer
134 CurrentShdrEx->str = (char*)malloc( 128);
135 #else
136 CurrentShdrEx->str = (char*)malloc( strlen(SPECIAL_SECTION_NAME) + 1 );
137 if(CurrentShdrEx->str == 0)
138 {
139 return EL_FAILED;
140 }
141 #endif
142 strcpy( CurrentShdrEx->str, SPECIAL_SECTION_NAME);
143 #endif
144 CurrentShdrEx->next = NULL;
145 ElfHandle->ShdrEx = DmyShdrEx.next;
146 /*--------------------------------------------------------*/
147 //printf( "stripped section_num : %d\n", stripped_section_num);
148
149 /*---------- Check and copy all sections ----------*/
150 // printf( "\nLoad to RAM:\n");
151 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
152 //
153 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
154
155 #if (SPECIAL_SECTION_ENABLE == 1) /*Add special section*/
156 if( CurrentShdrEx->Shdr.sh_type == SPECIAL_SECTION_TYPE) {
157 //Series of processes equivalent to ELi_CopySectionToBuffer
158 u32 load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
159 u32 sh_size = CurrentShdrEx->Shdr.sh_size;
160 u32* reverse_shdr_table = (u32*)malloc( 4 * stripped_section_num);
161 /*Index converts to new section number table*/
162 for( j=0; j<(ElfHandle->CurrentEhdr.e_shnum - 1); j++) {
163 if( shdr_table[j] != 0xFFFFFFFF) {
164 reverse_shdr_table[shdr_table[j]] = j;
165 }
166 }
167 memcpy( (u32*)load_start, reverse_shdr_table, sh_size); //Copy new/old section correspondence table
168 free( reverse_shdr_table);
169 CurrentShdrEx->loaded_adr = load_start;
170 ElfHandle->buf_current = (void*)(load_start + sh_size);
171 }else{
172 #else
173 {
174 #endif
175 if( CurrentShdrEx->Shdr.sh_type != SHT_NULL) { //NULL section (section 0) has no content
176 //Copy to memory
177 CurrentShdrEx->loaded_adr = (u32)
178 ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr));
179 }
180 #if (SPECIAL_SECTION_ENABLE == 1) /*Add special section*/
181 //For section string sections
182 if( (CurrentShdrEx->Shdr.sh_type == SHT_STRTAB)&&
183 (i == ElfHandle->CurrentEhdr.e_shstrndx)) {
184 strcpy( ElfHandle->buf_current, SPECIAL_SECTION_NAME);
185 //Update section data capacity
186 CurrentShdrEx->Shdr.sh_size += (strlen( SPECIAL_SECTION_NAME) + 1);
187 //Update buffer address
188 ElfHandle->buf_current += (strlen( SPECIAL_SECTION_NAME) + 1);
189 }
190 #endif
191 }
192 }
193 /*-------------------------------------------------------*/
194
195
196 /*Only the section content up to this point was copied to stripped ELF*/
197
198
199 /*---------- Copy section header to stripped elf ----------*/
200 buf_shdr = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
201 ElfHandle->buf_current = (void*)buf_shdr;
202 // printf( "buf_shdr = 0x%x\n", buf_shdr);
203 // printf( "buf = 0x%x\n", (u32)buf);
204
205 newelf_shoff = buf_shdr - ((u32)(buf));
206 // printf( "newelf_shoff = 0x%x\n", newelf_shoff);
207
208 section_num = 0;
209 for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
210 //
211 tmp_buf = buf_shdr + ( section_num * sizeof( Elf32_Shdr));
212
213 CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
214 /*Update offset*/
215 if( CurrentShdrEx->loaded_adr != 0) {
216 CurrentShdrEx->Shdr.sh_offset = (CurrentShdrEx->loaded_adr - (u32)buf);
217 }
218 /*Copy section header to stripped ELF image*/
219 memcpy( (u8*)tmp_buf, &(CurrentShdrEx->Shdr),
220 sizeof( Elf32_Shdr));
221 section_num++; /*Update section count*/
222 }
223 //printf( "section_num : %d\n", section_num);
224
225 // After copy ends
226 ElfHandle->process = EL_COPIED;
227 /*------------------------------------------------------------*/
228
229 ElfHandle->newelf_size = (buf_shdr - (u32)buf) + (section_num*sizeof( Elf32_Shdr));
230 // printf( "newelf_size = 0x%x\n", ElfHandle->newelf_size);
231
232 /*---------- Update ELF Header ----------*/
233 ElfHandle->CurrentEhdr.e_shnum = section_num; /*Apply the increased section count to the ELF header*/
234 //Update the section header offset
235 ElfHandle->CurrentEhdr.e_shoff = newelf_shoff;
236 memcpy( (u8*)buf, &(ElfHandle->CurrentEhdr), sizeof( Elf32_Ehdr)); /*Copy ELF header to the stripped ELF image*/
237 /*-----------------------------------*/
238
239 /*---------- Free the ELShdrEx List ----------*/
240 CurrentShdrEx = ElfHandle->ShdrEx;
241 if( CurrentShdrEx) {
242 do{
243 FwdShdrEx = CurrentShdrEx;
244 CurrentShdrEx = CurrentShdrEx->next;
245 free( FwdShdrEx->str);
246 free( FwdShdrEx);
247 }while( CurrentShdrEx != NULL);
248 ElfHandle->ShdrEx = NULL;
249 }
250 /*-----------------------------------------*/
251
252 /*Flush cache before DLL is called on RAM*/
253 // DC_FlushAll();
254 // DC_WaitWriteBufferEmpty();
255
256 return (ElfHandle->process);
257 }
258