/*---------------------------------------------------------------------------* Project: OS Dynamic Load APIs File: OSDynLoad.h Copyright (C) Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #ifndef __OSDYNLOAD_H #define __OSDYNLOAD_H #ifdef __cplusplus extern "C" { #endif /* ---------------------------------------------------------------- */ /* opaque module handle type */ /* ---------------------------------------------------------------- */ typedef void * OSDynLoad_ModuleHandle; /* ---------------------------------------------------------------- */ /* the core has a special handle value */ /* ---------------------------------------------------------------- */ #define MAINPROGRAM_MODULE_HANDLE ((OSDynLoad_ModuleHandle)(-1)) /* ---------------------------------------------------------------- */ /* entrypoint function type and default prototype */ /* ---------------------------------------------------------------- */ #define OSDYNLOAD_ENTRY_REASON_LOAD 1 #define OSDYNLOAD_ENTRY_REASON_UNLOAD 2 #define OSDYNLOAD_ENTRY_REASON_MAX OSDYNLOAD_ENTRY_REASON_UNLOAD typedef int (*pf_rpl_entry)(OSDynLoad_ModuleHandle aHandle, int aReason); int rpl_entry(OSDynLoad_ModuleHandle aHandle, int aReason); void __rpl_call_dtors(void); /* ---------------------------------------------------------------- */ /* module load notification callbacks */ /* ---------------------------------------------------------------- */ typedef struct _OSDynLoad_NotifyHdr { char *mpName; /* allocated C string for full path of file */ unsigned int mDebug_TextAddr; /* address where TEXT segment of RPX/RPL is loaded */ unsigned int mDebug_TextOffset; /* offset from linked address for the loaded TEXT segment */ unsigned int mDebug_TextSize; /* size of loaded TEXT segment */ unsigned int mDebug_DataAddr; /* address where DATA and BSS segment of RPX/RPL is loaded */ unsigned int mDebug_DataOffset; /* offset from linked address for the loaded DATA and BSS segment */ unsigned int mDebug_DataSize; /* size of loaded DATA and BSS segment */ unsigned int mDebug_ReadAddr; /* address where RODATA segment of RPX/RPL is loaded */ unsigned int mDebug_ReadOffset; /* offset from linked address for the loaded RODATA segment */ unsigned int mDebug_ReadSize; /* size of loaded RODATA segment */ } OSDynLoad_NotifyHdr; /* ---------------------------------------------------------------- */ /* OSDynLoad_AcquireContainingModule restriction flags */ /* for OSDynLoad_AcquireContainingModule */ /* ---------------------------------------------------------------- */ typedef enum _OSDynLoad_SegmentRestrictionFlags { OSDynLoad_SegmentRestriction_None, /* normal case where you do not care or do not know whether the pointer is in the */ /* CODE or DATA segment */ OSDynLoad_SegmentRestriction_Code, /* you want to be sure that the pointer is in the CODE segment; failure if DATA */ OSDynLoad_SegmentRestriction_Data /* you want to be sure that the pointer is in the DATA segment; failure if CODE */ } OSDynLoad_SegmentRestrictionFlags; /*---------------------------------------------------------------------------* Name: OSDynLoad_GetNumberOfRPLs Description: Return the number of loaded RPLs. Concerns: For development only. This function will return 0 in a production build. Arguments: None. Returns: The number of loaded RPLs. *---------------------------------------------------------------------------*/ int OSDynLoad_GetNumberOfRPLs(void); /*---------------------------------------------------------------------------* Name: OSDynLoad_GetRPLInfo Description: If possible, it will fill infobuffer with a maximum of count elements beginning with the index RPL[index]. If there are fewer RPLs than count, the remaining elements will be cleared. If count is smaller than what OSDynLoad_GetNumberOfRPLs returned, call this function repeatedly with an increasing index. Concerns: For development only. This function will return 1 in a production build if count is 0 otherwise it will return 0. Note that the RPLs are not necessarily in order of launch. Arguments: index - the RPL you want in infobuffer[0]. count - the number of elements in infobuffer infobuffer - an allocated or fixed size array of OSDynLoad_NotifyHdr Returns: 0 if called when an RPL has been loaded since OSDynLoad_GetNumberOfRPLs was called; if it returns 0, you must start over with OSDynLoad_GetNumberOfRPLs. 1 for success. *---------------------------------------------------------------------------*/ int OSDynLoad_GetRPLInfo(unsigned int index, unsigned int count, OSDynLoad_NotifyHdr *infobuffer); typedef void (*OSDynLoad_pfNotifyFunc)(OSDynLoad_ModuleHandle aModuleHandle, void *apUserArg, int aIsLoad, OSDynLoad_NotifyHdr const *apNotify); int OSDynLoad_AddNotifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg); void OSDynLoad_DelNotifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg); /* ---------------------------------------------------------------- */ /* legacy old spelling of OSDynLoad_AddNotifyCallback */ /* ---------------------------------------------------------------- */ int OSDynLoad_AddNofifyCallback(OSDynLoad_pfNotifyFunc aFunc, void *pUserArg); /* ---------------------------------------------------------------- */ /* allocator override - default allocator uses default heap */ /* ---------------------------------------------------------------- */ typedef int (*OSDynLoad_pfMemAlloc)(int aMemBytes, int aMemAlign, void **appRetPtr); typedef void (*OSDynLoad_pfMemFree)(void *pAddr); int OSDynLoad_SetAllocator(OSDynLoad_pfMemAlloc aAlloc, OSDynLoad_pfMemFree aFree); int OSDynLoad_GetAllocator(OSDynLoad_pfMemAlloc *apRetAlloc, OSDynLoad_pfMemFree *apRetFree); /* ---------------------------------------------------------------- */ /* tls allocator override - default allocator uses default heap */ /* for use by the loader to allocate the tls framework and data images in threads */ /* can only be changed in __preinit_user */ /* ---------------------------------------------------------------- */ int OSDynLoad_SetTLSAllocator(OSDynLoad_pfMemAlloc aAlloc, OSDynLoad_pfMemFree aFree); int OSDynLoad_GetTLSAllocator(OSDynLoad_pfMemAlloc *apRetAlloc, OSDynLoad_pfMemFree *apRetFree); /* ---------------------------------------------------------------- */ /* acquire/release module */ /* ---------------------------------------------------------------- */ int OSDynLoad_Acquire(char const *apBaseModuleName, OSDynLoad_ModuleHandle *apRetHandle); void OSDynLoad_Release(OSDynLoad_ModuleHandle aModuleHandle); /* ---------------------------------------------------------------- */ /* test if module is loaded */ /* module is loaded if return == 0 and *apRetHandle != 0 */ /* ---------------------------------------------------------------- */ int OSDynLoad_IsModuleLoaded(char const *apFileName, OSDynLoad_ModuleHandle *apRetHandle); /* ---------------------------------------------------------------- */ /* retrieve the name of a module (the one used in dynamic linking) */ /* ---------------------------------------------------------------- */ int OSDynLoad_GetModuleName(OSDynLoad_ModuleHandle aModuleHandle, char *apRetBuffer, int *apBufferSize); /* ---------------------------------------------------------------- */ /* find an export in a module by name */ /* log2n;n=num exported symbols, string comparison (bin search) */ /* ---------------------------------------------------------------- */ int OSDynLoad_FindExport(OSDynLoad_ModuleHandle aModuleHandle, int aTypeIsData, char const *apExportName, void **appRetAddr); /* ---------------------------------------------------------------- */ /* find a loader tag that was embedded in an RPL at makerpl stage*/ /* ---------------------------------------------------------------- */ int OSDynLoad_FindTag(OSDynLoad_ModuleHandle aModuleHandle, char const *apTag, char *apRetBuffer, int *apBufferSize); /* ---------------------------------------------------------------- */ /* free TLS memory allocated in a thread */ /* ---------------------------------------------------------------- */ void __OSDynLoad_TLSExitThread(OSThread *apThread); /*---------------------------------------------------------------------------* Name: OSDynLoad_AcquireContainingModule Description: Load an RPL module that contains an object, returning its handle. Arguments: apObject global or static object in some RPL module aRestrict a flag where you say that apObject must be in CODE or DATA or that there is no restriction apRetHandle pointer to memory to receive handle of loaded module that contains apObject. Since apObject has an address, it must already be loaded so this function actually just increases the ref count of the RPL module. apObject cannot be a stack based or allocated (for example, malloc or new) object. Caveat: Zero size objects will not be found if they are the last object in a code or data segment. Returns: 0 for success. OSDYNLOAD_ERR_xxx on failure OSDYNLOAD_ERR_BAD_HANDLE_RETURN_POINTER if apRetHandle parameter is NULL OSDYNLOAD_ERR_NULL_OBJECT if apObject parameter is NULL OSDYNLOAD_ERR_CONTAINING_MODULE_NOT_FOUND if module not found *---------------------------------------------------------------------------*/ int OSDynLoad_AcquireContainingModule(void *apObject, OSDynLoad_SegmentRestrictionFlags aRestrict, OSDynLoad_ModuleHandle *apRetHandle); /* ---------------------------------------------------------------- */ /* Loader Heap Statistics */ /* ---------------------------------------------------------------- */ typedef struct _OSDynLoad_LoaderHeapStatistics { unsigned int mCodeHeap_MemBytesUsed; /* current total amount in bytes of allocations in code heap */ unsigned int mCodeHeap_UsedNumAllocations; /* current number of allocations in code heap */ unsigned int mCodeHeap_MemBytesFree; /* current total amount of free memory in code heap */ unsigned int mCodeHeap_MemLargestFreeBlock; /* largest allocation available in code heap */ unsigned int mDataHeap_MemBytesUsed; /* current total amount in bytes of allocations in data heap */ unsigned int mDataHeap_UsedNumAllocations; /* current number of allocations in data heap */ } OSDynLoad_LoaderHeapStatistics; /*---------------------------------------------------------------------------* Name: OSDynLoad_GetLoaderHeapStatistics Description: Return heap information from the loader. Arguments: apRetLoaderHeapStatistics pointer to memory to receive OSDynLoad_LoaderHeapStatistics. apRetLoaderHeapStatistics can be global, stack based or allocated (for example, malloc or new). Returns: 0 for success. OSDYNLOAD_ERR_xxx on failure OSDYNLOAD_ERR_LOADER_MEM_INFO_BAD_PTR if apRetLoaderHeapStatistics is not valid memory OSDYNLOAD_ERR_NULL_LOADER_MEM_INFO if apRetLoaderHeapStatistics parameter is NULL *---------------------------------------------------------------------------*/ int OSDynLoad_GetLoaderHeapStatistics(OSDynLoad_LoaderHeapStatistics *apRetLoaderHeapStatistics); #ifdef __cplusplus } // extern "C" #endif #define OSDYNLOAD_ERRCODE(x) ((int)(0xBAD10000 | (x))) #define OSDYNLOAD_ERR_NONE 0 #define OSDYNLOAD_ERR_UNKNOWN OSDYNLOAD_ERRCODE(0x001) #define OSDYNLOAD_ERR_MEMORY_ALLOCATION_FAILURE OSDYNLOAD_ERRCODE(0x002) #define OSDYNLOAD_ERR_BAD_MODULE_HANDLE OSDYNLOAD_ERRCODE(0x003) #define OSDYNLOAD_ERR_FILE_TOO_SMALL OSDYNLOAD_ERRCODE(0x004) #define OSDYNLOAD_ERR_BAD_ELF_HEADER OSDYNLOAD_ERRCODE(0x005) #define OSDYNLOAD_ERR_NOT_32BIT_ELF OSDYNLOAD_ERRCODE(0x006) #define OSDYNLOAD_ERR_WRONG_ENDIANNESS OSDYNLOAD_ERRCODE(0x007) #define OSDYNLOAD_ERR_UNSUPPORTED_HEADER_VERSION OSDYNLOAD_ERRCODE(0x008) #define OSDYNLOAD_ERR_WRONG_TARGET_MACHINE OSDYNLOAD_ERRCODE(0x009) #define OSDYNLOAD_ERR_UNSUPPORTED_FILE_VERSION OSDYNLOAD_ERRCODE(0x00A) #define OSDYNLOAD_ERR_NO_SECTION_HEADERS OSDYNLOAD_ERRCODE(0x00B) #define OSDYNLOAD_ERR_MALFORMED_RPL OSDYNLOAD_ERRCODE(0x00C) #define OSDYNLOAD_ERR_NOT_CAFE_RPL OSDYNLOAD_ERRCODE(0x00D) #define OSDYNLOAD_ERR_NOTIFY_FUNCPTR_IS_NULL OSDYNLOAD_ERRCODE(0x00E) #define OSDYNLOAD_ERR_NULL_FILENAME OSDYNLOAD_ERRCODE(0x00F) #define OSDYNLOAD_ERR_EMPTY_FILENAME OSDYNLOAD_ERRCODE(0x010) #define OSDYNLOAD_ERR_BAD_HANDLE_RETURN_POINTER OSDYNLOAD_ERRCODE(0x011) #define OSDYNLOAD_ERR_NO_FILENAME OSDYNLOAD_ERRCODE(0x012) #define OSDYNLOAD_ERR_LOADER_RETURNED_NO_DATA OSDYNLOAD_ERRCODE(0x013) #define OSDYNLOAD_ERR_LOADER_PTR_BAD OSDYNLOAD_ERRCODE(0x014) #define OSDYNLOAD_ERR_NULL_LOADER OSDYNLOAD_ERRCODE(0x015) #define OSDYNLOAD_ERR_CANT_LOAD_INSIDE_MODULE_ENTRYPOINT OSDYNLOAD_ERRCODE(0x016) #define OSDYNLOAD_ERR_ALLOCATOR_PTR_BAD OSDYNLOAD_ERRCODE(0x017) #define OSDYNLOAD_ERR_MODULE_HAS_NONRELOCATABLE_CODE OSDYNLOAD_ERRCODE(0x018) #define OSDYNLOAD_ERR_CANT_LINK_BLIND_SYMBOL OSDYNLOAD_ERRCODE(0x019) #define OSDYNLOAD_ERR_IMPORT_NOT_FOUND_IN_EXPORTING_MODULE OSDYNLOAD_ERRCODE(0x01A) #define OSDYNLOAD_ERR_MODULE_HAS_NO_DATA_EXPORTS OSDYNLOAD_ERRCODE(0x01B) #define OSDYNLOAD_ERR_MODULE_HAS_NO_CODE_EXPORTS OSDYNLOAD_ERRCODE(0x01C) #define OSDYNLOAD_ERR_EXPORT_NOT_FOUND OSDYNLOAD_ERRCODE(0x01D) #define OSDYNLOAD_ERR_BAD_ARGUMENT OSDYNLOAD_ERRCODE(0x01E) #define OSDYNLOAD_ERR_BUFFER_TOO_SMALL OSDYNLOAD_ERRCODE(0x01F) #define OSDYNLOAD_ERR_LOADER_FAILURE OSDYNLOAD_ERRCODE(0x021) #define OSDYNLOAD_ERR_TAG_NOT_FOUND OSDYNLOAD_ERRCODE(0x022) #define OSDYNLOAD_ERR_MODULE_NOT_FOUND OSDYNLOAD_ERRCODE(0x023) #define OSDYNLOAD_ERR_ALLOC_FAILED_LD_SECT_INFO OSDYNLOAD_ERRCODE(0x024) #define OSDYNLOAD_ERR_ALLOC_FAILED_MAIN_NOTIF_ENTRY OSDYNLOAD_ERRCODE(0x025) #define OSDYNLOAD_ERR_FAILED_DEBUG_SET_CALLBACK OSDYNLOAD_ERRCODE(0x026) #define OSDYNLOAD_ERR_NULL_OBJECT OSDYNLOAD_ERRCODE(0x027) #define OSDYNLOAD_ERR_CONTAINING_MODULE_NOT_FOUND OSDYNLOAD_ERRCODE(0x028) #define OSDYNLOAD_ERR_LOAD_ENTRYPOINT_FAILED OSDYNLOAD_ERRCODE(0x029) #define OSDYNLOAD_ERR_UNKNOWN_MOD_FOR_HANDLE OSDYNLOAD_ERRCODE(0x02A) #define OSDYNLOAD_ERR_LOADER_BUSY OSDYNLOAD_ERRCODE(0x02B) #define OSDYNLOAD_ERR_LOADER_MEM_INFO_BAD_PTR OSDYNLOAD_ERRCODE(0x02C) // apRetLoaderHeapStatistics is invalid memory #define OSDYNLOAD_ERR_NULL_LOADER_MEM_INFO OSDYNLOAD_ERRCODE(0x02D) // apRetLoaderHeapStatistics is null #define OSDYNLOAD_ERR_PREVIOUS_LOADER_FAILURE OSDYNLOAD_ERRCODE(0x02E) #define OSDYNLOAD_ERR_SYS_HEAP_MEMORY_ALLOCATION_FAILURE OSDYNLOAD_ERRCODE(0x02F) #define OSDYNLOAD_ERR_TLS_INCONSISTENCY OSDYNLOAD_ERRCODE(0x030) #define OSDYNLOAD_ERR_TLS_ALLOCATOR_UNCHANGEABLE OSDYNLOAD_ERRCODE(0x031) #define OSDYNLOAD_ERR_TLS_TOO_MANY_MODULES OSDYNLOAD_ERRCODE(0x032) #define OSDYNLOAD_ERR_TLS_FINDEXPORT_UNSUPPORTED OSDYNLOAD_ERRCODE(0x033) #define OSDYNLOAD_ERR_TAG_ADDRSPACE_WRONG OSDYNLOAD_ERRCODE(0x034) #define OSDYNLOAD_ERR_INVAL_TAG_VALUE_RET_BUF OSDYNLOAD_ERRCODE(0x035) #define OSDYNLOAD_ERR_INVAL_TAG_VALUE_SIZE_RET_BUF OSDYNLOAD_ERRCODE(0x036) #define OSDYNLOAD_ERR_INVAL_TAG_INPUT_BUF OSDYNLOAD_ERRCODE(0x037) #define OSDYNLOAD_ERR_TAG_SNPRINTF_INTERNAL OSDYNLOAD_ERRCODE(0x038) #define OSDYNLOAD_ERR_TAG_VALUE_SIZE_IS_ZERO OSDYNLOAD_ERRCODE(0x039) #define OSDYNLOAD_ERR_MISSING_SHSTRTAB_INDEX OSDYNLOAD_ERRCODE(0x03A) #define OSDYNLOAD_ERR_MISSING_SHSTRTAB OSDYNLOAD_ERRCODE(0x03B) #define OSDYNLOAD_ERR_MISSING_IMPORT_NAME OSDYNLOAD_ERRCODE(0x03C) #define OSDYNLOAD_ERR_MISSING_TLS_DATA OSDYNLOAD_ERRCODE(0x03D) #define OSDYNLOAD_ERR_MISSING_RPX_ENTRYPOINT OSDYNLOAD_ERRCODE(0x03E) #define OSDYNLOAD_ERR_DISPLACEMENT_TOO_FAR OSDYNLOAD_ERRCODE(0x03F) /* ---------------------------------------------------------------- */ /* for exporting via in-code (not in header) definition decoration */ /* ---------------------------------------------------------------- */ #define RPL_EXPORT_FUNC(r, f, a) \ r f a; \ void * const __attribute__((section(".export"))) fexport_ ## f = (void *)f; \ r f a #define RPL_EXPORT_DATA(t, d) \ extern t d; \ void * const __attribute__((section(".export"))) dexport_ ## d = (void *)&d; \ t d #define RPL_EXPORT_DATA_ARRAY(t, d, num) \ extern t d[num]; \ void * const __attribute__((section(".export"))) dexport_ ## d = (void *)&d; \ t d[num] #define RPL_EXPORT_CLASS_FUNC(r, c, f, a) \ void * const __attribute__((section(".export"))) fexport_ ## c ## f = (void *)c::f; \ r c::f a #define RPL_EXPORT_CLASS_STATIC_DATA(t, c, d) \ void * const __attribute__((section(".export"))) dexport_ ## c ## d = (void *)&c::d; \ t c::d #define RPL_EXPORT_CLASS_STATIC_DATA_ARRAY(t, c, d, num) \ void * const __attribute__((section(".export"))) dexport_ ## c ## d = (void *)&c::d; \ t c::d[num] #endif // __OSDYNLOAD_H