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