1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ELF Loader
3 File: el.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-12-15#$
14 $Rev: 9650 $
15 $Author: kitase_hirotake $
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: Initialize the dynamic link system
53
54 Arguments: alloc Heap getting 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 an buffer size sufficient to test and relocate the dynamic link.
84 Return 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);
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);
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);
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 API/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 hande when successful, 0 if failed
180 *---------------------------------------------------------------------------*/
EL_LinkFile(const char * FilePath,void * buf)181 ELDlld EL_LinkFile( const char* FilePath, void* buf)
182 {
183 return( EL_LoadLibraryfromFile( i_eldesc, FilePath, buf));
184 }
185
186 /*------------------------------------------------------*/
EL_Link(ELReadImage readfunc,u32 len,void * buf)187 ELDlld EL_Link( ELReadImage readfunc, u32 len, void* buf)
188 {
189 return( EL_LoadLibrary( i_eldesc, readfunc, len, buf));
190 }
191
192 /*------------------------------------------------------*/
EL_LinkImage(void * obj_image,u32 obj_len,void * buf)193 ELDlld EL_LinkImage( void* obj_image, u32 obj_len, void* buf)
194 {
195 return( EL_LoadLibraryfromMem( i_eldesc, obj_image, obj_len, buf));
196 }
197
198
199 /*---------------------------------------------------------------------------*
200 Name: EL_ResolveAll
201
202 Description: Resolves unresolved symbols
203
204 Arguments: None.
205
206 Returns: EL_RELOCATED when successful, EL_FAILED if failed
207 *---------------------------------------------------------------------------*/
EL_ResolveAll(void)208 u16 EL_ResolveAll( void)
209 {
210 if( ELi_ResolveAllLibrary( i_eldesc) == EL_PROC_RELOCATED) {
211 return( EL_RELOCATED);
212 }
213 return( EL_FAILED);
214 }
215
216
217 /*---------------------------------------------------------------------------*
218 Name: EL_Export
219
220 Description: Registers symbol information to the DLL system
221
222 Arguments: None.
223
224 Returns: If successful, TRUE.
225 *---------------------------------------------------------------------------*/
EL_Export(ELAdrEntry * AdrEnt)226 BOOL EL_Export( ELAdrEntry* AdrEnt)
227 {
228 /* (TODO) Do not apply to simulation because not added to i_eldesc_sim */
229 return ELi_Export( i_eldesc, AdrEnt);
230 }
231
232
233 /*---------------------------------------------------------------------------*
234 Name: EL_GetGlobalAdr
235
236 Description: Searches a symbol from the dynamic module and returns the address
237
238 Arguments: my_dlld Handle of dynamic module targeted for the search
239 ent_name Symbol name
240
241 Returns: Address of symbol when successful, 0 if failed
242 *---------------------------------------------------------------------------*/
EL_GetGlobalAdr(ELDlld my_dlld,const char * ent_name)243 void* EL_GetGlobalAdr( ELDlld my_dlld, const char* ent_name)
244 {
245 return( ELi_GetGlobalAdr( i_eldesc, my_dlld, ent_name));
246 }
247
248
249 /*---------------------------------------------------------------------------*
250 Name: EL_Unlink
251
252 Description: Unlinks the dynamic module.
253
254 Arguments: my_dlld Handle of dynamic module to unlink
255
256 Returns: EL_SUCCESS when successful, EL_FAILED if failed
257 *---------------------------------------------------------------------------*/
EL_Unlink(ELDlld my_dlld)258 u16 EL_Unlink( ELDlld my_dlld)
259 {
260 if( ELi_Unlink( i_eldesc, my_dlld) == TRUE) {
261 /* ReLink not possible because corresponding object structure is destroyed */
262 (void)elRemoveObjEntry( &(i_eldesc->ELObjectStart), (ELObject*)my_dlld); // No problem if it fails
263 return( EL_SUCCESS);
264 }
265 return( EL_FAILED);
266 }
267
268
269 /*---------------------------------------------------------------------------*
270 Name: EL_GetResultCode
271
272 Description: Returns detailed results of final processes
273
274 Arguments: None.
275
276 Returns: Error code of type ELResult
277 *---------------------------------------------------------------------------*/
EL_GetResultCode(void)278 ELResult EL_GetResultCode( void)
279 {
280 if( i_eldesc == NULL) {
281 return( EL_RESULT_FAILURE);
282 }
283 return( (ELResult)(i_eldesc->result));
284 }
285
286 #if 0
287 ELResult EL_GetResultCode( ELDlld my_dlld)
288 {
289 ELObject* MYObject;
290
291 if( my_dlld == 0) {
292 return( EL_RESULT_INVALID_PARAMETER);
293 }
294
295 // Object that references results
296 MYObject = (ELObject*)my_dlld;
297
298 return( MYObject->result);
299 }
300 #endif
301