1 /*---------------------------------------------------------------------------*
2   Project:  OS Dynamic Load APIs
3   File:     OSDynLoad.h
4 
5   Copyright (C) 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  *---------------------------------------------------------------------------*/
14 
15 #ifndef __OSDYNLOAD_H
16 #define __OSDYNLOAD_H
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /* ---------------------------------------------------------------- */
23 /* opaque module handle type */
24 /* ---------------------------------------------------------------- */
25 typedef void * OSDynLoad_ModuleHandle;
26 
27 /* ---------------------------------------------------------------- */
28 /* the core has a special handle value */
29 /* ---------------------------------------------------------------- */
30 #define MAINPROGRAM_MODULE_HANDLE ((OSDynLoad_ModuleHandle)(-1))
31 
32 /* ---------------------------------------------------------------- */
33 /* entrypoint function type and default prototype */
34 /* ---------------------------------------------------------------- */
35 #define OSDYNLOAD_ENTRY_REASON_LOAD     1
36 #define OSDYNLOAD_ENTRY_REASON_UNLOAD   2
37 #define OSDYNLOAD_ENTRY_REASON_MAX		OSDYNLOAD_ENTRY_REASON_UNLOAD
38 typedef int (*pf_rpl_entry)(OSDynLoad_ModuleHandle aHandle, int aReason);
39 int rpl_entry(OSDynLoad_ModuleHandle aHandle, int aReason);
40 void __rpl_call_dtors(void);
41 
42 /* ---------------------------------------------------------------- */
43 /* module load notification callbacks */
44 /* ---------------------------------------------------------------- */
45 typedef struct _OSDynLoad_NotifyHdr
46 {
47     char		    				*mpName;    		/* allocated C string for full path of file */
48     unsigned int    				mDebug_TextAddr;	/* address where TEXT segment of RPX/RPL is loaded */
49     unsigned int    				mDebug_TextOffset;  /* offset from linked address for the loaded TEXT segment */
50     unsigned int    				mDebug_TextSize;    /* size of loaded TEXT segment */
51     unsigned int    				mDebug_DataAddr;	/* address where DATA and BSS segment of RPX/RPL is loaded */
52     unsigned int    				mDebug_DataOffset;  /* offset from linked address for the loaded DATA and BSS segment */
53     unsigned int    				mDebug_DataSize;    /* size of loaded DATA and BSS segment */
54     unsigned int    				mDebug_ReadAddr;	/* address where RODATA segment of RPX/RPL is loaded */
55     unsigned int    				mDebug_ReadOffset;  /* offset from linked address for the loaded RODATA segment */
56     unsigned int    				mDebug_ReadSize;    /* size of loaded RODATA segment */
57 } OSDynLoad_NotifyHdr;
58 
59 /* ---------------------------------------------------------------- */
60 /* OSDynLoad_AcquireContainingModule restriction flags */
61 /* for OSDynLoad_AcquireContainingModule */
62 /* ---------------------------------------------------------------- */
63 typedef enum _OSDynLoad_SegmentRestrictionFlags
64 {
65 	OSDynLoad_SegmentRestriction_None,	/* normal case where you do not care or do not know whether the pointer is in the */
66 										/* CODE or DATA segment */
67 	OSDynLoad_SegmentRestriction_Code,	/* you want to be sure that the pointer is in the CODE segment; failure if DATA */
68 	OSDynLoad_SegmentRestriction_Data	/* you want to be sure that the pointer is in the DATA segment; failure if CODE */
69 } OSDynLoad_SegmentRestrictionFlags;
70 
71 /*---------------------------------------------------------------------------*
72 Name:			OSDynLoad_GetNumberOfRPLs
73 
74 Description:	Return the number of loaded RPLs.
75 
76 Concerns:		For development only.  This function will return 0 in a
77 				production build.
78 
79 Arguments:		None.
80 
81 Returns:		The number of loaded RPLs.
82 
83 *---------------------------------------------------------------------------*/
84 int OSDynLoad_GetNumberOfRPLs(void);
85 
86 /*---------------------------------------------------------------------------*
87 Name:			OSDynLoad_GetRPLInfo
88 
89 Description:	If possible, it will fill infobuffer with a maximum of count
90 				elements beginning with the index RPL[index].  If there are
91 				fewer RPLs than count, the remaining elements will be cleared.
92 				If count is smaller than what OSDynLoad_GetNumberOfRPLs
93 				returned, call this function repeatedly with an increasing
94 				index.
95 
96 Concerns:		For development only.  This function will return 1 in a
97 				production build if count is 0 otherwise it will return 0.
98 
99 				Note that the RPLs are not necessarily in order of launch.
100 
101 Arguments:		index - the RPL you want in infobuffer[0].
102 				count - the number of elements in infobuffer
103 				infobuffer - an allocated or fixed size array of OSDynLoad_NotifyHdr
104 
105 Returns:		0 if called when an RPL has been loaded since OSDynLoad_GetNumberOfRPLs
106 				was called; if it returns 0, you must start over with
107 				OSDynLoad_GetNumberOfRPLs.
108 
109              	1 for success.
110 
111 *---------------------------------------------------------------------------*/
112 int OSDynLoad_GetRPLInfo(unsigned int index, unsigned int count, OSDynLoad_NotifyHdr *infobuffer);
113 
114 typedef void (*OSDynLoad_pfNotifyFunc)(OSDynLoad_ModuleHandle aModuleHandle, void *apUserArg, int aIsLoad, OSDynLoad_NotifyHdr const *apNotify);
115 
116 int  OSDynLoad_AddNotifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg);
117 void OSDynLoad_DelNotifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg);
118 
119 /* ---------------------------------------------------------------- */
120 /* legacy old spelling of OSDynLoad_AddNotifyCallback */
121 /* ---------------------------------------------------------------- */
122 int  OSDynLoad_AddNofifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg);
123 
124 /* ---------------------------------------------------------------- */
125 /* allocator override - default allocator uses default heap */
126 /* ---------------------------------------------------------------- */
127 typedef int  (*OSDynLoad_pfMemAlloc)(int aMemBytes, int aMemAlign, void **appRetPtr);
128 typedef void (*OSDynLoad_pfMemFree)(void *pAddr);
129 int  OSDynLoad_SetAllocator(OSDynLoad_pfMemAlloc aAlloc, OSDynLoad_pfMemFree aFree);
130 int  OSDynLoad_GetAllocator(OSDynLoad_pfMemAlloc *apRetAlloc, OSDynLoad_pfMemFree *apRetFree);
131 
132 /* ---------------------------------------------------------------- */
133 /* tls allocator override - default allocator uses default heap */
134 /* for use by the loader to allocate the tls framework and data images in threads */
135 /* can only be changed in __preinit_user */
136 /* ---------------------------------------------------------------- */
137 int  OSDynLoad_SetTLSAllocator(OSDynLoad_pfMemAlloc aAlloc, OSDynLoad_pfMemFree aFree);
138 int  OSDynLoad_GetTLSAllocator(OSDynLoad_pfMemAlloc *apRetAlloc, OSDynLoad_pfMemFree *apRetFree);
139 
140 /* ---------------------------------------------------------------- */
141 /* acquire/release module */
142 /* ---------------------------------------------------------------- */
143 int  OSDynLoad_Acquire(char const *apBaseModuleName, OSDynLoad_ModuleHandle *apRetHandle);
144 void OSDynLoad_Release(OSDynLoad_ModuleHandle aModuleHandle);
145 
146 /* ---------------------------------------------------------------- */
147 /* test if module is loaded */
148 /* module is loaded if return == 0 and *apRetHandle != 0 */
149 /* ---------------------------------------------------------------- */
150 int OSDynLoad_IsModuleLoaded(char const *apFileName, OSDynLoad_ModuleHandle *apRetHandle);
151 
152 /* ---------------------------------------------------------------- */
153 /* retrieve the name of a module (the one used in dynamic linking) */
154 /* ---------------------------------------------------------------- */
155 int  OSDynLoad_GetModuleName(OSDynLoad_ModuleHandle aModuleHandle, char *apRetBuffer, int *apBufferSize);
156 
157 /* ---------------------------------------------------------------- */
158 /* find an export in a module by name */
159 /* log2n;n=num exported symbols, string comparison (bin search) */
160 /* ---------------------------------------------------------------- */
161 int  OSDynLoad_FindExport(OSDynLoad_ModuleHandle aModuleHandle, int aTypeIsData, char const *apExportName, void **appRetAddr);
162 
163 /* ---------------------------------------------------------------- */
164 /* find a loader tag that was embedded in an RPL at makerpl stage*/
165 /* ---------------------------------------------------------------- */
166 int  OSDynLoad_FindTag(OSDynLoad_ModuleHandle aModuleHandle, char const *apTag, char *apRetBuffer, int *apBufferSize);
167 
168 /* ---------------------------------------------------------------- */
169 /* free TLS memory allocated in a thread */
170 /* ---------------------------------------------------------------- */
171 void __OSDynLoad_TLSExitThread(OSThread *apThread);
172 
173 /*---------------------------------------------------------------------------*
174   Name:         OSDynLoad_AcquireContainingModule
175 
176   Description:  Load an RPL module that contains an object, returning its handle.
177 
178   Arguments:    apObject            global or static object in some RPL module
179   				aRestrict			a flag where you say that apObject must be in CODE or
180   									DATA or that there is no restriction
181                 apRetHandle         pointer to memory to receive handle of loaded module
182                 					that contains apObject.  Since apObject has an
183                 					address, it must already be loaded so this function
184                 					actually just increases the ref count of the
185                 					RPL module.  apObject cannot be a stack based or
186                 					allocated (for example, malloc or new) object.
187 
188   Caveat:		Zero size objects will not be found if they are the last object in
189   				a code or data segment.
190 
191   Returns:      0 for success.  OSDYNLOAD_ERR_xxx on failure
192   								OSDYNLOAD_ERR_BAD_HANDLE_RETURN_POINTER if apRetHandle parameter is NULL
193   								OSDYNLOAD_ERR_NULL_OBJECT if apObject parameter is NULL
194   								OSDYNLOAD_ERR_CONTAINING_MODULE_NOT_FOUND if module not found
195  *---------------------------------------------------------------------------*/
196 int OSDynLoad_AcquireContainingModule(void *apObject, OSDynLoad_SegmentRestrictionFlags aRestrict, OSDynLoad_ModuleHandle *apRetHandle);
197 
198 /* ---------------------------------------------------------------- */
199 /* Loader Heap Statistics */
200 /* ---------------------------------------------------------------- */
201 typedef struct _OSDynLoad_LoaderHeapStatistics
202 {
203     unsigned int    				mCodeHeap_MemBytesUsed;	        /* current total amount in bytes of allocations in code heap */
204     unsigned int    				mCodeHeap_UsedNumAllocations;   /* current number of allocations in code heap */
205     unsigned int    				mCodeHeap_MemBytesFree;         /* current total amount of free memory in code heap */
206     unsigned int    				mCodeHeap_MemLargestFreeBlock;	/* largest allocation available in code heap */
207     unsigned int    				mDataHeap_MemBytesUsed;	        /* current total amount in bytes of allocations in data heap */
208     unsigned int    				mDataHeap_UsedNumAllocations;   /* current number of allocations in data heap */
209 } OSDynLoad_LoaderHeapStatistics;
210 
211 /*---------------------------------------------------------------------------*
212   Name:         OSDynLoad_GetLoaderHeapStatistics
213 
214   Description:  Return heap information from the loader.
215 
216   Arguments:    apRetLoaderHeapStatistics   pointer to memory to receive OSDynLoad_LoaderHeapStatistics.
217                 					        apRetLoaderHeapStatistics can be global, stack based or
218                 					        allocated (for example, malloc or new).
219 
220   Returns:      0 for success.  OSDYNLOAD_ERR_xxx on failure
221                                 OSDYNLOAD_ERR_LOADER_MEM_INFO_BAD_PTR if apRetLoaderHeapStatistics is not valid memory
222    								OSDYNLOAD_ERR_NULL_LOADER_MEM_INFO if apRetLoaderHeapStatistics parameter is NULL
223 
224  *---------------------------------------------------------------------------*/
225 int OSDynLoad_GetLoaderHeapStatistics(OSDynLoad_LoaderHeapStatistics *apRetLoaderHeapStatistics);
226 
227 #ifdef __cplusplus
228 }   // extern "C"
229 #endif
230 
231 #define OSDYNLOAD_ERRCODE(x)                                    ((int)(0xBAD10000 | (x)))
232 
233 #define OSDYNLOAD_ERR_NONE                                      0
234 #define OSDYNLOAD_ERR_UNKNOWN                                   OSDYNLOAD_ERRCODE(0x001)
235 #define OSDYNLOAD_ERR_MEMORY_ALLOCATION_FAILURE                 OSDYNLOAD_ERRCODE(0x002)
236 #define OSDYNLOAD_ERR_BAD_MODULE_HANDLE                         OSDYNLOAD_ERRCODE(0x003)
237 #define OSDYNLOAD_ERR_FILE_TOO_SMALL                            OSDYNLOAD_ERRCODE(0x004)
238 #define OSDYNLOAD_ERR_BAD_ELF_HEADER                            OSDYNLOAD_ERRCODE(0x005)
239 #define OSDYNLOAD_ERR_NOT_32BIT_ELF                             OSDYNLOAD_ERRCODE(0x006)
240 #define OSDYNLOAD_ERR_WRONG_ENDIANNESS                          OSDYNLOAD_ERRCODE(0x007)
241 #define OSDYNLOAD_ERR_UNSUPPORTED_HEADER_VERSION                OSDYNLOAD_ERRCODE(0x008)
242 #define OSDYNLOAD_ERR_WRONG_TARGET_MACHINE                      OSDYNLOAD_ERRCODE(0x009)
243 #define OSDYNLOAD_ERR_UNSUPPORTED_FILE_VERSION                  OSDYNLOAD_ERRCODE(0x00A)
244 #define OSDYNLOAD_ERR_NO_SECTION_HEADERS                        OSDYNLOAD_ERRCODE(0x00B)
245 #define OSDYNLOAD_ERR_MALFORMED_RPL                             OSDYNLOAD_ERRCODE(0x00C)
246 #define OSDYNLOAD_ERR_NOT_CAFE_RPL                              OSDYNLOAD_ERRCODE(0x00D)
247 #define OSDYNLOAD_ERR_NOTIFY_FUNCPTR_IS_NULL                    OSDYNLOAD_ERRCODE(0x00E)
248 #define OSDYNLOAD_ERR_NULL_FILENAME                             OSDYNLOAD_ERRCODE(0x00F)
249 #define OSDYNLOAD_ERR_EMPTY_FILENAME                            OSDYNLOAD_ERRCODE(0x010)
250 #define OSDYNLOAD_ERR_BAD_HANDLE_RETURN_POINTER                 OSDYNLOAD_ERRCODE(0x011)
251 #define OSDYNLOAD_ERR_NO_FILENAME                               OSDYNLOAD_ERRCODE(0x012)
252 #define OSDYNLOAD_ERR_LOADER_RETURNED_NO_DATA                   OSDYNLOAD_ERRCODE(0x013)
253 #define OSDYNLOAD_ERR_LOADER_PTR_BAD                            OSDYNLOAD_ERRCODE(0x014)
254 #define OSDYNLOAD_ERR_NULL_LOADER                               OSDYNLOAD_ERRCODE(0x015)
255 #define OSDYNLOAD_ERR_CANT_LOAD_INSIDE_MODULE_ENTRYPOINT        OSDYNLOAD_ERRCODE(0x016)
256 #define OSDYNLOAD_ERR_ALLOCATOR_PTR_BAD                         OSDYNLOAD_ERRCODE(0x017)
257 #define OSDYNLOAD_ERR_MODULE_HAS_NONRELOCATABLE_CODE            OSDYNLOAD_ERRCODE(0x018)
258 #define OSDYNLOAD_ERR_CANT_LINK_BLIND_SYMBOL                    OSDYNLOAD_ERRCODE(0x019)
259 #define OSDYNLOAD_ERR_IMPORT_NOT_FOUND_IN_EXPORTING_MODULE      OSDYNLOAD_ERRCODE(0x01A)
260 #define OSDYNLOAD_ERR_MODULE_HAS_NO_DATA_EXPORTS                OSDYNLOAD_ERRCODE(0x01B)
261 #define OSDYNLOAD_ERR_MODULE_HAS_NO_CODE_EXPORTS                OSDYNLOAD_ERRCODE(0x01C)
262 #define OSDYNLOAD_ERR_EXPORT_NOT_FOUND                          OSDYNLOAD_ERRCODE(0x01D)
263 #define OSDYNLOAD_ERR_BAD_ARGUMENT                              OSDYNLOAD_ERRCODE(0x01E)
264 #define OSDYNLOAD_ERR_BUFFER_TOO_SMALL                          OSDYNLOAD_ERRCODE(0x01F)
265 #define OSDYNLOAD_ERR_LOADER_FAILURE                            OSDYNLOAD_ERRCODE(0x021)
266 #define OSDYNLOAD_ERR_TAG_NOT_FOUND                             OSDYNLOAD_ERRCODE(0x022)
267 #define OSDYNLOAD_ERR_MODULE_NOT_FOUND							OSDYNLOAD_ERRCODE(0x023)
268 #define OSDYNLOAD_ERR_ALLOC_FAILED_LD_SECT_INFO 				OSDYNLOAD_ERRCODE(0x024)
269 #define OSDYNLOAD_ERR_ALLOC_FAILED_MAIN_NOTIF_ENTRY 			OSDYNLOAD_ERRCODE(0x025)
270 #define OSDYNLOAD_ERR_FAILED_DEBUG_SET_CALLBACK 				OSDYNLOAD_ERRCODE(0x026)
271 #define OSDYNLOAD_ERR_NULL_OBJECT                               OSDYNLOAD_ERRCODE(0x027)
272 #define OSDYNLOAD_ERR_CONTAINING_MODULE_NOT_FOUND               OSDYNLOAD_ERRCODE(0x028)
273 #define OSDYNLOAD_ERR_LOAD_ENTRYPOINT_FAILED                    OSDYNLOAD_ERRCODE(0x029)
274 #define OSDYNLOAD_ERR_UNKNOWN_MOD_FOR_HANDLE                    OSDYNLOAD_ERRCODE(0x02A)
275 #define OSDYNLOAD_ERR_LOADER_BUSY                               OSDYNLOAD_ERRCODE(0x02B)
276 #define OSDYNLOAD_ERR_LOADER_MEM_INFO_BAD_PTR                   OSDYNLOAD_ERRCODE(0x02C)    // apRetLoaderHeapStatistics is invalid memory
277 #define OSDYNLOAD_ERR_NULL_LOADER_MEM_INFO                      OSDYNLOAD_ERRCODE(0x02D)    // apRetLoaderHeapStatistics is null
278 #define OSDYNLOAD_ERR_PREVIOUS_LOADER_FAILURE                   OSDYNLOAD_ERRCODE(0x02E)
279 #define OSDYNLOAD_ERR_SYS_HEAP_MEMORY_ALLOCATION_FAILURE        OSDYNLOAD_ERRCODE(0x02F)
280 #define OSDYNLOAD_ERR_TLS_INCONSISTENCY                         OSDYNLOAD_ERRCODE(0x030)
281 #define OSDYNLOAD_ERR_TLS_ALLOCATOR_UNCHANGEABLE                OSDYNLOAD_ERRCODE(0x031)
282 #define OSDYNLOAD_ERR_TLS_TOO_MANY_MODULES                      OSDYNLOAD_ERRCODE(0x032)
283 #define OSDYNLOAD_ERR_TLS_FINDEXPORT_UNSUPPORTED                OSDYNLOAD_ERRCODE(0x033)
284 #define OSDYNLOAD_ERR_TAG_ADDRSPACE_WRONG                       OSDYNLOAD_ERRCODE(0x034)
285 #define OSDYNLOAD_ERR_INVAL_TAG_VALUE_RET_BUF                   OSDYNLOAD_ERRCODE(0x035)
286 #define OSDYNLOAD_ERR_INVAL_TAG_VALUE_SIZE_RET_BUF              OSDYNLOAD_ERRCODE(0x036)
287 #define OSDYNLOAD_ERR_INVAL_TAG_INPUT_BUF                       OSDYNLOAD_ERRCODE(0x037)
288 #define OSDYNLOAD_ERR_TAG_SNPRINTF_INTERNAL                     OSDYNLOAD_ERRCODE(0x038)
289 #define OSDYNLOAD_ERR_TAG_VALUE_SIZE_IS_ZERO                    OSDYNLOAD_ERRCODE(0x039)
290 #define OSDYNLOAD_ERR_MISSING_SHSTRTAB_INDEX                    OSDYNLOAD_ERRCODE(0x03A)
291 #define OSDYNLOAD_ERR_MISSING_SHSTRTAB                          OSDYNLOAD_ERRCODE(0x03B)
292 #define OSDYNLOAD_ERR_MISSING_IMPORT_NAME                       OSDYNLOAD_ERRCODE(0x03C)
293 #define OSDYNLOAD_ERR_MISSING_TLS_DATA                          OSDYNLOAD_ERRCODE(0x03D)
294 #define OSDYNLOAD_ERR_MISSING_RPX_ENTRYPOINT                    OSDYNLOAD_ERRCODE(0x03E)
295 #define OSDYNLOAD_ERR_DISPLACEMENT_TOO_FAR                      OSDYNLOAD_ERRCODE(0x03F)
296 
297 /* ---------------------------------------------------------------- */
298 /* for exporting via in-code (not in header) definition decoration  */
299 /* ---------------------------------------------------------------- */
300 
301 #define RPL_EXPORT_FUNC(r, f, a) \
302     r f a; \
303     void * const __attribute__((section(".export"))) fexport_ ## f = (void *)f; \
304     r f a
305 
306 #define RPL_EXPORT_DATA(t, d) \
307     extern t d; \
308     void * const __attribute__((section(".export"))) dexport_ ## d = (void *)&d; \
309     t d
310 
311 #define RPL_EXPORT_DATA_ARRAY(t, d, num) \
312     extern t d[num]; \
313     void * const __attribute__((section(".export"))) dexport_ ## d = (void *)&d; \
314     t d[num]
315 
316 #define RPL_EXPORT_CLASS_FUNC(r, c, f, a) \
317     void * const __attribute__((section(".export"))) fexport_ ## c ## f = (void *)c::f; \
318     r c::f a
319 
320 #define RPL_EXPORT_CLASS_STATIC_DATA(t, c, d) \
321     void * const __attribute__((section(".export"))) dexport_ ## c ## d = (void *)&c::d; \
322     t c::d
323 
324 #define RPL_EXPORT_CLASS_STATIC_DATA_ARRAY(t, c, d, num) \
325     void * const __attribute__((section(".export"))) dexport_ ## c ## d = (void *)&c::d; \
326     t c::d[num]
327 
328 #endif // __OSDYNLOAD_H
329