1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ELF Loader
3 File: el.c
4
5 Copyright 2006-2009 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:: 2009-06-04#$
14 $Rev: 10698 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include "el_config.h"
19
20 #include <twl/el.h>
21
22
23 #include "elf.h"
24 #include "arch.h"
25 #include "elf_loader.h"
26 #include "loader_subset.h"
27
28
29 /*------------------------------------------------------
30 External Variables
31 -----------------------------------------------------*/
32 extern ELAlloc i_elAlloc;
33 extern ELFree i_elFree;
34
35
36 /*------------------------------------------------------
37 External Functions
38 -----------------------------------------------------*/
39 extern BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt);
40
41
42 /*------------------------------------------------------
43 Global Variables
44 -----------------------------------------------------*/
45 ELDesc* i_eldesc = NULL; // For link
46 ELDesc* i_eldesc_sim = NULL; // For simulation link
47
48
49 /*---------------------------------------------------------------------------*
50 Name: EL_Init
51
52 Description: Initializes the dynamic link system.
53
54 Arguments: alloc: Heap-allocation function
55 free: Heap-deallocation function
56
57 Returns: 0 if successful; -1 if failed.
58 *---------------------------------------------------------------------------*/
EL_Init(ELAlloc alloc,ELFree free)59 s32 EL_Init( ELAlloc alloc, ELFree free)
60 {
61 if( i_eldesc != NULL) {
62 return( -1); //Initialized
63 }
64
65 ELi_Init( alloc, free);
66
67 i_eldesc = ELi_Malloc( NULL, NULL, ((sizeof( ELDesc))*2)); //For link and simulation-link
68 if( i_eldesc == NULL) {
69 return( -1);
70 }
71
72 (void)ELi_InitDesc( i_eldesc);
73 i_eldesc_sim = &(i_eldesc[1]);
74 (void)ELi_InitDesc( i_eldesc_sim);
75
76 return( 0);
77 }
78
79 #if 1
80 /*---------------------------------------------------------------------------*
81 Name: EL_CalcEnoughBufferSizeforLink*
82
83 Description: Returns a buffer size sufficient to test and relocate the dynamic link.
84 Returns a slightly larger size when the dynamic object is referencing externally.
85
86
87 Arguments: FilePath: Path name of the dynamic object
88 buf: Buffer address for the relocating destination (writing is not actually performed)
89 readfunc: Read function prepared by the application
90 len: Size of the dynamic object
91 obj_image: Address on the memory where the dynamic object exists
92 obj_len: Size of the dynamic object
93 link_mode: Mode for testing dynamic links
94
95 Returns: Buffer size when successful; -1 if failed.
96 *---------------------------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLinkFile(const char * FilePath,const void * buf,ELLinkMode link_mode)97 s32 EL_CalcEnoughBufferSizeforLinkFile( const char* FilePath, const void* buf, ELLinkMode link_mode)
98 {
99 ELDlld dlld;
100 u32 size;
101
102 if( link_mode != EL_LINKMODE_ONESHOT) {
103 return( -1);
104 }
105 dlld = EL_LoadLibraryfromFile( i_eldesc_sim, FilePath, (void*)buf, 0xFFFFFFFF);
106 if( dlld) {
107 if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
108 return( -1);
109 }
110 size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
111
112 (void)ELi_Unlink( i_eldesc, dlld);
113 (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
114 return( (s32)size);
115 }
116 return( -1);
117 }
118
119 /*------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLink(ELReadImage readfunc,u32 len,const void * buf,ELLinkMode link_mode)120 s32 EL_CalcEnoughBufferSizeforLink( ELReadImage readfunc, u32 len, const void* buf, ELLinkMode link_mode)
121 {
122 ELDlld dlld;
123 u32 size;
124
125 if( link_mode != EL_LINKMODE_ONESHOT) {
126 return( -1);
127 }
128 dlld = EL_LoadLibrary( i_eldesc_sim, readfunc, len, (void*)buf, 0xFFFFFFFF);
129 if( dlld) {
130 if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
131 return( -1);
132 }
133 size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
134
135 (void)ELi_Unlink( i_eldesc, dlld);
136 (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
137 return( (s32)size);
138 }
139 return( -1);
140 }
141
142 /*------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLinkImage(void * obj_image,u32 obj_len,const void * buf,ELLinkMode link_mode)143 s32 EL_CalcEnoughBufferSizeforLinkImage( void* obj_image, u32 obj_len, const void* buf, ELLinkMode link_mode)
144 {
145 ELDlld dlld;
146 u32 size;
147
148 if( link_mode != EL_LINKMODE_ONESHOT) {
149 return( -1);
150 }
151 dlld = EL_LoadLibraryfromMem( i_eldesc_sim, obj_image, obj_len, (void*)buf, 0xFFFFFFFF);
152 if( dlld) {
153 if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
154 return( -1);
155 }
156 size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
157
158 (void)ELi_Unlink( i_eldesc, dlld);
159 (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
160 return( (s32)size);
161 }
162 return( -1);
163 }
164 #endif
165
166
167 /*---------------------------------------------------------------------------*
168 Name: EL_Link*
169
170 Description: Relocates dynamic objects (files/user functions/from memory).
171
172 Arguments: FilePath: Path name of the dynamic object
173 readfunc: Read function prepared by the application
174 len: Size of the dynamic object
175 obj_image: Address on the memory where the dynamic object exists
176 obj_len: Size of the dynamic object
177 buf: Buffer address for the relocation destination
178
179 Returns: Dynamic module handle when successful, 0 if failed.
180 *---------------------------------------------------------------------------*/
EL_LinkFileEx(const char * FilePath,void * buf,u32 buf_size)181 ELDlld EL_LinkFileEx( const char* FilePath, void* buf, u32 buf_size)
182 {
183 return( EL_LoadLibraryfromFile( i_eldesc, FilePath, buf, buf_size));
184 }
185
186 /*------------------------------------------------------*/
EL_LinkEx(ELReadImage readfunc,u32 len,void * buf,u32 buf_size)187 ELDlld EL_LinkEx( ELReadImage readfunc, u32 len, void* buf, u32 buf_size)
188 {
189 return( EL_LoadLibrary( i_eldesc, readfunc, len, buf, buf_size));
190 }
191
192 /*------------------------------------------------------*/
EL_LinkImageEx(void * obj_image,u32 obj_len,void * buf,u32 buf_size)193 ELDlld EL_LinkImageEx( void* obj_image, u32 obj_len, void* buf, u32 buf_size)
194 {
195 return( EL_LoadLibraryfromMem( i_eldesc, obj_image, obj_len, buf, buf_size));
196 }
197
198 /*---------------------------------------------------------------------------*
199 Name: EL_Link*
200
201 Description: Relocates dynamic objects (files/user functions/from memory).
202
203 Arguments: FilePath: Path name of the dynamic object
204 readfunc: Read function prepared by the application
205 len: Size of the dynamic object
206 obj_image: Address on the memory where the dynamic object exists
207 obj_len: Size of the dynamic object
208 buf: Buffer address for the relocation destination
209
210 Returns: Dynamic module handle when successful, 0 if failed.
211 *---------------------------------------------------------------------------*/
EL_LinkFile(const char * FilePath,void * buf)212 ELDlld EL_LinkFile( const char* FilePath, void* buf)
213 {
214 return( EL_LoadLibraryfromFile( i_eldesc, FilePath, buf, 0xFFFFFFFF));
215 }
216
217 /*------------------------------------------------------*/
EL_Link(ELReadImage readfunc,u32 len,void * buf)218 ELDlld EL_Link( ELReadImage readfunc, u32 len, void* buf)
219 {
220 return( EL_LoadLibrary( i_eldesc, readfunc, len, buf, 0xFFFFFFFF));
221 }
222
223 /*------------------------------------------------------*/
EL_LinkImage(void * obj_image,u32 obj_len,void * buf)224 ELDlld EL_LinkImage( void* obj_image, u32 obj_len, void* buf)
225 {
226 return( EL_LoadLibraryfromMem( i_eldesc, obj_image, obj_len, buf, 0xFFFFFFFF));
227 }
228
229
230 /*---------------------------------------------------------------------------*
231 Name: EL_ResolveAll
232
233 Description: Resolves unresolved symbols.
234
235 Arguments: None.
236
237 Returns: EL_RELOCATED when successful, EL_FAILED if failed.
238 *---------------------------------------------------------------------------*/
EL_ResolveAll(void)239 u16 EL_ResolveAll( void)
240 {
241 if( ELi_ResolveAllLibrary( i_eldesc) == EL_PROC_RELOCATED) {
242 return( EL_RELOCATED);
243 }
244 return( EL_FAILED);
245 }
246
247
248 /*---------------------------------------------------------------------------*
249 Name: EL_Export
250
251 Description: Registers symbol information to the DLL system.
252
253 Arguments: None.
254
255 Returns: If successful, TRUE.
256 *---------------------------------------------------------------------------*/
EL_Export(ELAdrEntry * AdrEnt)257 BOOL EL_Export( ELAdrEntry* AdrEnt)
258 {
259 /* (TODO) Do not apply to simulation because not added to i_eldesc_sim */
260 return ELi_Export( i_eldesc, AdrEnt);
261 }
262
263
264 /*---------------------------------------------------------------------------*
265 Name: EL_GetGlobalAdr
266
267 Description: Searches a symbol from the dynamic module and returns the address.
268
269 Arguments: my_dlld: Handle of dynamic module targeted for the search
270 ent_name: Symbol name
271
272 Returns: Address of symbol when successful, 0 if failed.
273 *---------------------------------------------------------------------------*/
EL_GetGlobalAdr(ELDlld my_dlld,const char * ent_name)274 void* EL_GetGlobalAdr( ELDlld my_dlld, const char* ent_name)
275 {
276 return( ELi_GetGlobalAdr( i_eldesc, my_dlld, ent_name));
277 }
278
279
280 /*---------------------------------------------------------------------------*
281 Name: EL_Unlink
282
283 Description: Unlinks the dynamic module.
284
285 Arguments: my_dlld: Handle of dynamic module to unlink
286
287 Returns: EL_SUCCESS when successful, EL_FAILED if failed.
288 *---------------------------------------------------------------------------*/
EL_Unlink(ELDlld my_dlld)289 u16 EL_Unlink( ELDlld my_dlld)
290 {
291 if( ELi_Unlink( i_eldesc, my_dlld) == TRUE) {
292 /* ReLink not possible because corresponding object structure is destroyed */
293 (void)elRemoveObjEntry( &(i_eldesc->ELObjectStart), (ELObject*)my_dlld); // No problem if it fails
294 return( EL_SUCCESS);
295 }
296 return( EL_FAILED);
297 }
298
299
300 /*---------------------------------------------------------------------------*
301 Name: EL_GetResultCode
302
303 Description: Returns detailed results of final processes.
304
305 Arguments: None.
306
307 Returns: Error code of type ELResult.
308 *---------------------------------------------------------------------------*/
EL_GetResultCode(void)309 ELResult EL_GetResultCode( void)
310 {
311 if( i_eldesc == NULL) {
312 return( EL_RESULT_FAILURE);
313 }
314 return( (ELResult)(i_eldesc->result));
315 }
316
317 #if 0
318 ELResult EL_GetResultCode( ELDlld my_dlld)
319 {
320 ELObject* MYObject;
321
322 if( my_dlld == 0) {
323 return( EL_RESULT_INVALID_PARAMETER);
324 }
325
326 // Object that references results
327 MYObject = (ELObject*)my_dlld;
328
329 return( MYObject->result);
330 }
331 #endif
332