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