/*---------------------------------------------------------------------------* Project: TwlSDK - ELF Loader File: elf_loader.c Copyright 2006-2008 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. $Date:: 2008-12-15#$ $Rev: 9650 $ $Author: kitase_hirotake $ *---------------------------------------------------------------------------*/ #include "el_config.h" #ifdef SDK_TWL #include #else #include #endif #include "elf.h" #include "arch.h" #include "elf_loader.h" #include "loader_subset.h" #include #ifndef SDK_TWL OSHeapHandle EL_Heap; #endif #if 1 /*------------------------------------------------------ Function to notify the IS-TWL_DEBUGGER -----------------------------------------------------*/ void _ISTDbgLib_StartRegistRelocationInfo( ISTDOVERLAYPROC nProc ); BOOL _ISTDbgLib_RegistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA ); void _ISTDbgLib_EndRegistRelocationInfo( ISTDOVERLAYPROC nProc ); BOOL _ISTDbgLib_UnregistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll ); SDK_WEAK_SYMBOL void _ISTDbgLib_StartRegistRelocationInfo( ISTDOVERLAYPROC nProc ) { (void)nProc; return; } SDK_WEAK_SYMBOL BOOL _ISTDbgLib_RegistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA ) { (void)nProc; (void)nDll; (void)nELF; (void)nSection; (void)nLMA; return TRUE; } SDK_WEAK_SYMBOL void _ISTDbgLib_EndRegistRelocationInfo( ISTDOVERLAYPROC nProc ) { (void)nProc; return; } SDK_WEAK_SYMBOL BOOL _ISTDbgLib_UnregistRelocationInfo( ISTDOVERLAYPROC nProc, u32 nDll ) { (void)nProc; (void)nDll; return TRUE; } /* stub */ static void ELi_START_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable ); static BOOL ELi_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA, BOOL enable ); static void ELi_END_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable ); static BOOL ELi_UNREGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, BOOL enable ); static void ELi_START_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable ) { if( enable) { _ISTDbgLib_StartRegistRelocationInfo( nProc); } } static BOOL ELi_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, u32 nELF, u32 nSection, u32 nLMA, BOOL enable ) { if( enable) { return( _ISTDbgLib_RegistRelocationInfo( nProc, nDll, nELF, nSection, nLMA)); } return( FALSE); } static void ELi_END_REGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, BOOL enable ) { if( enable) { _ISTDbgLib_EndRegistRelocationInfo( nProc); } } static BOOL ELi_UNREGISTER_RELOCATION_INFO( ISTDOVERLAYPROC nProc, u32 nDll, BOOL enable ) { if( enable) { return( _ISTDbgLib_UnregistRelocationInfo( nProc, nDll)); } return( FALSE); } #endif /*------------------------------------------------------ External Functions -----------------------------------------------------*/ extern ELDesc* i_eldesc_sim; /*------------------------------------------------------ Global Variables -----------------------------------------------------*/ static ELReadImage i_elReadImage; ELAlloc i_elAlloc; ELFree i_elFree; static BOOL i_el_initialized = FALSE; static OSMutex i_el_mutex; /*------------------------------------------------------ Local Function Declarations -----------------------------------------------------*/ static void ELi_FreeObject( ELObject** ELObjEntStart); static void ELi_InitObject( ELObject* MYObject); BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt); static void elAddObjEntry( ELObject** StartEnt, ELObject* ObjEnt); static BOOL ELi_ReInitDesc( ELDesc* elElfDesc); static ELResult elLoadSegments( ELDesc* elElfDesc, ELObject* MYObject); static ELResult elLoadSections( ELDesc* elElfDesc, ELObject* MYObject, u32 dll_fileid, u32 elf_num); // Relocate ELF object or that archive in a buffer static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, u32 dll_fileid); // Core function that relocates ELF object to buffer static ELResult ELi_LoadObject( ELDesc* elElfDesc, ELObject* MYObject, void* obj_offset, void* buf, u32 dll_fileid, u32 elf_num); // Stub function that reads data from the ELF object static BOOL ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); static BOOL ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); static BOOL ELi_ReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); // Delete entry from address table //BOOL elRemoveAdrEntry( ELAdrEntry* AdrEnt); // Add entry to address table void elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt); // Search for entry corresponding to specified string in address table ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt); // Release all address tables static void elFreeAdrTbl( ELAdrEntry** ELAdrEntStart); /*--------------------------------------------------------- Find size of the ELF object buf: Address of ELF image --------------------------------------------------------*/ u32 EL_GetElfSize( const void* buf) { Elf32_Ehdr Ehdr; u32 size; if( ELF_LoadELFHeader( buf, &Ehdr) == NULL) { return 0; } size = (u32)(Ehdr.e_shoff + (Ehdr.e_shentsize * Ehdr.e_shnum)); return size; } /*--------------------------------------------------------- Find the size of the linked library --------------------------------------------------------*/ u32 EL_GetLibSize( ELDlld my_dlld) { if( my_dlld == 0) { return( 0); } return( ((ELObject*)my_dlld)->lib_size); } /*------------------------------------------------------ Initialize the dynamic link system -----------------------------------------------------*/ #if 0 //#ifndef SDK_TWL void ELi_Init( void) { void* heap_start; if( i_el_initialized) { return; } i_el_initialized = TRUE; /*--- Set memory allocation relationship ---*/ OS_InitArena(); heap_start = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1); OS_SetMainArenaLo( heap_start ); EL_Heap = OS_CreateHeap( OS_ARENA_MAIN, heap_start, (void*)((u32)(OS_GetMainArenaHi())+1)); OS_SetCurrentHeap( OS_ARENA_MAIN, EL_Heap); /*--------------------------------------*/ OS_InitMutex( &i_el_mutex); } #else void ELi_Init( ELAlloc alloc, ELFree free) { i_elAlloc = alloc; i_elFree = free; if( i_el_initialized) { return; } i_el_initialized = TRUE; OS_InitMutex( &i_el_mutex); } void* ELi_Malloc( ELDesc* elElfDesc, ELObject* MYObject, size_t size) { void* ptr; ptr = OSAPI_MALLOC( size); if( ptr == NULL) { ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_NO_MORE_RESOURCE); return( NULL); } return( ptr); } #endif /*------------------------------------------------------ Initialize the ELDesc structure -----------------------------------------------------*/ BOOL ELi_InitDesc( ELDesc* elElfDesc) { if( elElfDesc == NULL) { /*NULL check*/ return FALSE; } /*Set defaut values*/ elElfDesc->ShdrEx = NULL; elElfDesc->SymEx = NULL; elElfDesc->SymExTbl = NULL; elElfDesc->SymExTarget = 0xFFFFFFFF; elElfDesc->process = (u32)EL_PROC_INITIALIZED; /*Set the flag*/ elElfDesc->result = (u32)EL_RESULT_SUCCESS; /**/ elElfDesc->ELObjectStart = NULL; elElfDesc->ELStaticObj = NULL; return TRUE; } /*------------------------------------------------------ Reinitialize the ELDesc structure if the object has finished reading -----------------------------------------------------*/ static BOOL ELi_ReInitDesc( ELDesc* elElfDesc) { if( elElfDesc == NULL) { /*NULL check*/ return FALSE; } /*Set defaut values*/ elElfDesc->ShdrEx = NULL; elElfDesc->SymEx = NULL; elElfDesc->SymExTbl = NULL; elElfDesc->SymExTarget = 0xFFFFFFFF; elElfDesc->process = (u32)EL_PROC_INITIALIZED; /*Set the flag*/ elElfDesc->result = (u32)EL_RESULT_SUCCESS; return TRUE; } /*------------------------------------------------------ Relocate ELF object or that archive in a buffer elElfDesc: Header structure ObjFile: Object file or archive file structure buf: Buffer for loading -----------------------------------------------------*/ ELDlld EL_LoadLibraryfromFile( ELDesc* elElfDesc, const char* FilePath, void* buf) { ELDlld dlld; u32 len; FSFile file[1]; FSFileID file_id[1]; if( elElfDesc == NULL) { return( 0); } OS_LockMutex( &i_el_mutex); FS_InitFile(file); if( !FS_OpenFileEx(file, FilePath, FS_FILEMODE_R) ) { ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF); OS_UnlockMutex( &i_el_mutex); return 0; } if( !FS_ConvertPathToFileID( file_id, FilePath ) ) { (void)FS_CloseFile(file); OS_UnlockMutex( &i_el_mutex); return 0; } /*Set read function*/ elElfDesc->i_elReadStub = ELi_ReadFile; elElfDesc->FileStruct = (int*)file; len = FS_GetFileLength( file ); dlld = ELi_LoadLibrary( elElfDesc, NULL, len, buf, file_id[0].file_id); if( dlld != 0) { ((ELObject*)dlld)->file_id = file_id[0].file_id; } if( !FS_CloseFile(file)) { ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF); dlld = 0; } OS_UnlockMutex( &i_el_mutex); return( dlld); } /*------------------------------------------------------ Relocate ELF object or that archive in a buffer elElfDesc: Header structure readfunc: User function the reads object or archive files buf: Buffer for loading -----------------------------------------------------*/ ELDlld EL_LoadLibrary( ELDesc* elElfDesc, ELReadImage readfunc, u32 len, void* buf) { ELDlld dlld; if( elElfDesc == NULL) { return( 0); } OS_LockMutex( &i_el_mutex); i_elReadImage = readfunc; elElfDesc->i_elReadStub = ELi_ReadUsr; dlld = ELi_LoadLibrary( elElfDesc, NULL, len, buf, 0xFFFFFFFF); if( dlld != 0) { ((ELObject*)dlld)->file_id = 0xFFFFFFFF; } OS_UnlockMutex( &i_el_mutex); return( dlld); } /*------------------------------------------------------ Relocate ELF object or that archive in a buffer elElfDesc: Header structure obj_image: Image address on RAM of object file or archive file buf: Buffer for loading -----------------------------------------------------*/ ELDlld EL_LoadLibraryfromMem( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf) { ELDlld dlld; if( elElfDesc == NULL) { return( 0); } OS_LockMutex( &i_el_mutex); /*Set read function*/ elElfDesc->i_elReadStub = ELi_ReadMem; elElfDesc->FileStruct = NULL; dlld = ELi_LoadLibrary( elElfDesc, obj_image, obj_len, buf, 0xFFFFFFFF); if( dlld != 0) { ((ELObject*)dlld)->file_id = 0xFFFFFFFF; } OS_UnlockMutex( &i_el_mutex); return( dlld); } /*------------------------------------------------------ Relocate ELF object or that archive in a buffer elElfDesc: Header structure obj_image: Image address on RAM of object file or archive file buf: Buffer for loading -----------------------------------------------------*/ static ELDlld ELi_LoadLibrary( ELDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf, u32 dll_fileid) { ELResult result; u32 image_pointer; u32 arch_size; u32 elf_num = 0; /*Number of ELF objects*/ ArchHdr ArHdr; char OBJMAG[8]; char ELFMAG[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3}; ELObject* MYObject; /*-------*/ if( elElfDesc->i_elReadStub == NULL) { ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_CANNOT_ACCESS_ELF); return( 0); } /*-------*/ /* Allocate individual object management structure */ MYObject = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject)); if(MYObject == NULL) return 0; ELi_InitObject( MYObject); elAddObjEntry( &(elElfDesc->ELObjectStart), MYObject); elElfDesc->ar_head = obj_image; image_pointer = 0; MYObject->lib_start = buf; MYObject->buf_current = buf; if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)obj_image, 0, 8) == FALSE) { /*Get the OBJ character string*/ ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF); return( 0); } /*--------------- For archive files ---------------*/ if( OSAPI_STRNCMP( OBJMAG, ARMAG, 8) == 0) { arch_size = sizeof( ArchHdr); image_pointer += 8; /*To first entry*/ while( image_pointer < obj_len) { if( elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4) == FALSE) { /*Get the OBJ character string*/ ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF); break; } if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) { /*Reset initial values*/ (void)ELi_ReInitDesc( elElfDesc); result = ELi_LoadObject( elElfDesc, MYObject, (void*)(image_pointer+arch_size), MYObject->buf_current, dll_fileid, elf_num); if( result != EL_RESULT_SUCCESS) { break; } elf_num++; }else{ } /*To next entry*/ if( elElfDesc->i_elReadStub( &ArHdr, elElfDesc->FileStruct, (u32)(obj_image), image_pointer, arch_size) == FALSE) { ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF); return( 0); } image_pointer += arch_size + AR_GetEntrySize( &ArHdr); } }else{/*--------------- For ELF files ---------------*/ if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) { /*Reset initial values*/ (void)ELi_ReInitDesc( elElfDesc); result = ELi_LoadObject( elElfDesc, MYObject, 0, MYObject->buf_current, dll_fileid, elf_num); if( result != EL_RESULT_SUCCESS) { }else{ elf_num++; } }else{ ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF); } } /*-------------------------------------------------------*/ if( elf_num) { if( OS_IsRunOnDebugger() == FALSE) { (void)ELi_FreeVenTbl( elElfDesc, MYObject); /*Release the veneer link list when not debugging*/ } MYObject->stat = elf_num; //When (MEMO)Segment was loaded, buf_current was not advanced, so it was not applied to lib_size MYObject->lib_size = ((u32)(MYObject->buf_current)) - ((u32)(MYObject->lib_start)); PRINTDEBUG( "library size : 0x%x\n", MYObject->lib_size); return( (ELDlld)MYObject); }else{ /* Object could not be processed so structure was destroyed */ (void)elRemoveObjEntry( &(elElfDesc->ELObjectStart), MYObject); return 0; //NULL } } /*------------------------------------------------------ Relocate ELF object to buffer elElfDesc: Header structure MYObject: Individual object management structure obj_offset: Offset from image address on object file RAM buf: Buffer to load (TODO: Buffer overflow countermeasure) -----------------------------------------------------*/ static ELResult ELi_LoadObject( ELDesc* elElfDesc, ELObject* MYObject, void* obj_offset, void* buf, u32 dll_fileid, u32 elf_num) { ELResult ret_val; /* Check initialization of ELDesc */ if( elElfDesc->process != (u32)EL_PROC_INITIALIZED) { return( EL_RESULT_FAILURE); } /* Get ELF header */ if( elElfDesc->i_elReadStub( &(elElfDesc->CurrentEhdr), elElfDesc->FileStruct, (u32)(elElfDesc->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr)) == FALSE) { ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_CANNOT_ACCESS_ELF); return( EL_RESULT_CANNOT_ACCESS_ELF); } /* Build ELDesc structure */ elElfDesc->elf_offset = obj_offset; elElfDesc->shentsize = elElfDesc->CurrentEhdr.e_shentsize; elElfDesc->entry_adr = elElfDesc->CurrentEhdr.e_entry; /* Process for each ELF file type */ switch( elElfDesc->CurrentEhdr.e_type) { case ET_NONE: PRINTDEBUG( "ERROR : Elf type \"ET_NONE\"\n"); ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF); ret_val = EL_RESULT_UNSUPPORTED_ELF; break; case ET_REL: /* X to execute; O to relocate */ PRINTDEBUG( "Elf type \"ET_REL\"\n"); if( buf == NULL) { /* Buffer NULL check */ ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_NO_MORE_RESOURCE); return EL_RESULT_NO_MORE_RESOURCE; } ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num); break; case ET_EXEC: /* O to execute; X to relocate */ PRINTDEBUG( "Elf type \"ET_EXEC\"\n"); ret_val = elLoadSegments( elElfDesc, MYObject); break; case ET_DYN: /* O to execute; O to relocate (TODO: untested)*/ PRINTDEBUG( "Elf type \"ET_DYN\"\n"); if( buf == NULL) { //Handle as ET_EXEC when the load address is not specified ret_val = elLoadSegments( elElfDesc, MYObject); }else{ //Handle as ET_REL when the load address is not specified ret_val = elLoadSections( elElfDesc, MYObject, dll_fileid, elf_num); } break; case ET_CORE: PRINTDEBUG( "ERROR : Elf type \"ET_CORE\"\n"); ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_UNSUPPORTED_ELF); ret_val = EL_RESULT_UNSUPPORTED_ELF; break; default: PRINTDEBUG( "ERROR : Invalid Elf type 0x%x\n", elElfDesc->CurrentEhdr.e_type); ELi_SetResultCode( elElfDesc, MYObject, EL_RESULT_INVALID_ELF); ret_val = EL_RESULT_INVALID_ELF; break; } return( ret_val); } /*------------------------------------------------------ Check and copy all segments elElfDesc: Header structure -----------------------------------------------------*/ static ELResult elLoadSegments( ELDesc* elElfDesc, ELObject* MYObject) { u16 i; //u32 load_start; Elf32_Phdr CurrentPhdr; for( i=0; i<(elElfDesc->CurrentEhdr.e_phnum); i++) { /*Copy program header*/ ELi_GetPhdr( elElfDesc, i, &CurrentPhdr); if( CurrentPhdr.p_type == PT_LOAD) { /*If loadable segment, load to memory*/ if( ELi_CopySegmentToBuffer( elElfDesc, MYObject, &CurrentPhdr) == NULL) { return( EL_RESULT_CANNOT_ACCESS_ELF); } }else{ PRINTDEBUG( "WARNING : skip segment (type = 0x%x)\n", CurrentPhdr.p_type); } } ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED); return( EL_RESULT_SUCCESS); } /*------------------------------------------------------ Check and copy all sections elElfDesc: Header structure -----------------------------------------------------*/ static ELResult elLoadSections( ELDesc* elElfDesc, ELObject* MYObject, u32 dll_fileid, u32 elf_num) { u16 i; ELShdrEx* FwdShdrEx; ELShdrEx* CurrentShdrEx; ELShdrEx* InfoShdrEx; //For example, consider CurrentShdrEx as .text for rel.text ELShdrEx DmyShdrEx; #if (DEBUG_PRINT_ON == 1) u16 j; u32 num_of_entry; char sym_str[128]; //For debug print u32 offset; //For debug print #endif /*---------- Create ELShdrEx List ----------*/ CurrentShdrEx = &DmyShdrEx; for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { CurrentShdrEx->next = ELi_Malloc( elElfDesc, MYObject, sizeof(ELShdrEx)); if(CurrentShdrEx->next == NULL) { return( EL_RESULT_NO_MORE_RESOURCE); } CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next); OSAPI_CPUFILL8( CurrentShdrEx, 0, sizeof(ELShdrEx)); //Zero-clear /*Set flag to distinguish whether this is debugging information*/ if( ELi_ShdrIsDebug( elElfDesc, i) == TRUE) { /*When it is debugging information*/ CurrentShdrEx->debug_flag = 1; }else{ /*When not debugging information*/ /*Copy section header*/ ELi_GetShdr( elElfDesc, i, &(CurrentShdrEx->Shdr)); CurrentShdrEx->debug_flag = 0; } } CurrentShdrEx->next = NULL; elElfDesc->ShdrEx = DmyShdrEx.next; /*--------------------------------------------*/ ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim)); /*---------- Check and copy all sections ----------*/ PRINTDEBUG( "\nLoad to RAM:\n"); for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { /**/ CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i); // PRINTDEBUG( "section:%d sh_flag=0x%x\n", i, CurrentShdrEx->Shdr.sh_flags); // PRINTDEBUG( "section:%d sh_type=0x%x\n", i, CurrentShdrEx->Shdr.sh_type); if( CurrentShdrEx->debug_flag == 1) { /*When it is debugging information*/ PRINTDEBUG( "skip debug-section %02x\n", i); }else{ /*When not debugging information*/ BOOL bLocate = FALSE; /* .text section */ if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))&& (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { //Copy to memory CurrentShdrEx->loaded_adr = (u32) ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr)); bLocate = TRUE; } /* .data, .data1 section (Initialized data) */ else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&& (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { //Copy to memory CurrentShdrEx->loaded_adr = (u32) ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr)); bLocate = TRUE; } /* bss section */ else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&& (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) { //Do not copy CurrentShdrEx->loaded_adr = (u32) ELi_AllocSectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr)); bLocate = TRUE; } /* .rodata, .rodata1 section*/ else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&& (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { //Copy to memory CurrentShdrEx->loaded_adr = (u32) ELi_CopySectionToBuffer( elElfDesc, MYObject, &(CurrentShdrEx->Shdr)); bLocate = TRUE; } if (bLocate) { if( CurrentShdrEx->loaded_adr == NULL) { //When failed in ELi_CopySectionToBuffer ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim)); return( EL_RESULT_CANNOT_ACCESS_ELF); } (void)ELi_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, dll_fileid, elf_num, i, CurrentShdrEx->loaded_adr, (elElfDesc != i_eldesc_sim)); } PRINTDEBUG( "section %02x relocated at %08x\n", i, CurrentShdrEx->loaded_adr); } } /* After copy ends */ ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_COPIED); /*----------------------------------------------------*/ ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim)); /*---------- Publication of global symbols and relocating of local symbols ----------*/ PRINTDEBUG( "\nRelocate Symbols:\n"); for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { /**/ CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, i); if( CurrentShdrEx->debug_flag == 1) { /*When it is debugging information*/ }else{ /*When not debugging information*/ if( CurrentShdrEx->Shdr.sh_type == SHT_REL) { /*Relocate*/ InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, CurrentShdrEx->Shdr.sh_info); if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE) return( (ELResult)(elElfDesc->result)); //EL_RESULT_NO_MORE_RESOURCE or EL_RESULT_UNSUPPORTED_ELF } #if (DEBUG_PRINT_ON == 1) num_of_entry = (CurrentShdrEx->Shdr.sh_size) / (CurrentShdrEx->Shdr.sh_entsize); PRINTDEBUG( "num of REL = %x\n", num_of_entry); PRINTDEBUG( "Section Header Info.\n"); PRINTDEBUG( "link : %x\n", CurrentShdrEx->Shdr.sh_link); PRINTDEBUG( "info : %x\n", CurrentShdrEx->Shdr.sh_info); PRINTDEBUG( " Offset Info Type Sym.Value Sym.Name\n"); offset = 0; for( j=0; jRel), offset, sizeof(Elf32_Rel)); ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr)); ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym), (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rel.r_info)), sizeof(Elf32_Sym)); ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128); PRINTDEBUG( "%08x ", elElfDesc->Rel.r_offset); PRINTDEBUG( "%08x ", elElfDesc->Rel.r_info); PRINTDEBUG( " "); PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value); PRINTDEBUG( sym_str); PRINTDEBUG( "\n"); /*To next entry*/ offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); } #endif } else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) { /*Relocate*/ InfoShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, CurrentShdrEx->Shdr.sh_info); if( InfoShdrEx->loaded_adr != 0) { //Relocate internally if targeted section is loaded if(ELi_RelocateSym( elElfDesc, MYObject, i) == FALSE) return( EL_RESULT_NO_MORE_RESOURCE); } #if (DEBUG_PRINT_ON == 1) num_of_entry = (CurrentShdrEx->Shdr.sh_size) / (CurrentShdrEx->Shdr.sh_entsize); PRINTDEBUG( "num of RELA = %x\n", num_of_entry); PRINTDEBUG( "Section Header Info.\n"); PRINTDEBUG( "link : %x\n", CurrentShdrEx->Shdr.sh_link); PRINTDEBUG( "info : %x\n", CurrentShdrEx->Shdr.sh_info); PRINTDEBUG( " Offset Info Type Sym.Value Sym.Name\n"); offset = 0; for( j=0; jRela), offset, sizeof(Elf32_Rel)); ELi_GetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr)); ELi_GetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym), (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rela.r_info)), sizeof(Elf32_Sym)); ELi_GetStrAdr( elElfDesc, elElfDesc->SymShdr.sh_link, elElfDesc->Sym.st_name, sym_str, 128); PRINTDEBUG( "%08x ", elElfDesc->Rela.r_offset); PRINTDEBUG( "%08x ", elElfDesc->Rela.r_info); PRINTDEBUG( " "); PRINTDEBUG( "%08x ", elElfDesc->Sym.st_value); PRINTDEBUG( sym_str); PRINTDEBUG( "\n"); /*To next entry*/ offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); } #endif } else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) { /*Register global symbol in address table*/ if(ELi_GoPublicGlobalSym( elElfDesc, MYObject, i) == FALSE) return( EL_RESULT_NO_MORE_RESOURCE); } } } /*Create in ELi_RelocateSym and ELi_GoPublicGlobalSym & and release the used symbol list*/ ELi_FreeSymList( elElfDesc); /*---------- Free the ELShdrEx List ----------*/ CurrentShdrEx = elElfDesc->ShdrEx; if( CurrentShdrEx) { do { FwdShdrEx = CurrentShdrEx; CurrentShdrEx = CurrentShdrEx->next; OSAPI_FREE( FwdShdrEx); }while( CurrentShdrEx != NULL); elElfDesc->ShdrEx = NULL; } /*-----------------------------------------*/ /*Flush cache before DLL is called on RAM*/ #if (TARGET_ARM_V5 == 1) OSAPI_FLUSHCACHEALL(); OSAPI_WAITCACHEBUF(); #endif return( EL_RESULT_SUCCESS); } /*------------------------------------------------------ Resolve unresolved symbols using the address table -----------------------------------------------------*/ ELProcess ELi_ResolveAllLibrary( ELDesc* elElfDesc) { ELAdrEntry* AdrEnt; ELImportEntry* UnrEnt; ELImportEntry* NextEnt; // ELImportEntry* CurrentUnrEnt; // ELImportEntry* FwdUnrEnt; ELObject* ObjEnt; ELObject* ExpObjEnt; BOOL ret_val; if( elElfDesc == NULL) { return( EL_PROC_NOTHING); } ObjEnt = elElfDesc->ELObjectStart; if( (ObjEnt == NULL)||((ObjEnt == elElfDesc->ELStaticObj)&&(ObjEnt->next == NULL))) { return( EL_PROC_NOTHING); /* If there is no dll */ } while( ObjEnt != NULL) { UnrEnt = (ELImportEntry*)ObjEnt->UnresolvedImportAdrEnt; PRINTDEBUG( "\nResolve all symbols:\n"); while( UnrEnt != NULL) { NextEnt = UnrEnt->next; AdrEnt = elGetAdrEntry( elElfDesc, UnrEnt->sym_str, &ExpObjEnt); /*Search from address table*/ if( AdrEnt) { /*When found in address table*/ UnrEnt->S_ = (u32)(AdrEnt->adr); UnrEnt->T_ = (u32)(AdrEnt->thumb_flag); PRINTDEBUG( "\n symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_); ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt); /*Resolve symbol*/ if( ret_val == FALSE) { return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED Is osPanic better? TODO: continuation }else{ PRINTDEBUG( "%s ... ObjEnt:0x%x, ExpObjEnt:0x%x\n", UnrEnt->sym_str, ObjEnt, ExpObjEnt); UnrEnt->Dlld = (struct ELObject*)ExpObjEnt; /*Register ObjEnt referenced in resolution*/ /* Change link from Unresolved to Resolved */ (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt); ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt); } }else{ /*When not found in address table*/ if( elElfDesc != i_eldesc_sim) { PRINTDEBUG( "\n ERROR! cannot find symbol : %s\n\n", UnrEnt->sym_str); return( (ELProcess)(ObjEnt->process)); //Should be EL_PROC_COPIED Is osPanic better? TODO: Continue } /*----- For simulation, assume it was forcefully resolved -----*/ UnrEnt->S_ = (u32)0; UnrEnt->T_ = (u32)0; ret_val = ELi_DoRelocate( elElfDesc, ObjEnt, UnrEnt); UnrEnt->Dlld = (struct ELObject*)NULL; /*Register ObjEnt referenced in resolution*/ /* Change link from Unresolved to Resolved */ (void)ELi_ExtractImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), UnrEnt); ELi_AddImportEntry( &(ObjEnt->ResolvedImportAdrEnt), UnrEnt); /*--------------------------------------------------------*/ } UnrEnt = NextEnt; /*To next unresolved entry*/ } ELi_SetProcCode( NULL, ObjEnt, EL_PROC_RELOCATED); ObjEnt->lib_size = ((u32)(ObjEnt->buf_current)) - ((u32)(ObjEnt->lib_start)); //There is the possibility that veneer was added, so update the size. ObjEnt = ObjEnt->next; } ELi_SetProcCode( elElfDesc, NULL, EL_PROC_RELOCATED); /*TODO: When fixed, only the UnrEnt entry that could not be resolved here should be deleted*/ #if 0 /*---------- Free the ELImportEntry List ----------*/ ELi_FreeImportTbl( &ELUnrEntStart); /*-------------------------------------------*/ #endif /*Release the veneer link request*/ // (void)ELi_FreeVenTbl(); /*Flush cache before DLL is called on RAM*/ #if (TARGET_ARM_V5 == 1) OSAPI_FLUSHCACHEALL(); OSAPI_WAITCACHEBUF(); #endif return EL_PROC_RELOCATED; } /*------------------------------------------------------ Unlink the object -----------------------------------------------------*/ BOOL ELi_Unlink( ELDesc* elElfDesc, ELDlld my_dlld) { ELObject* MYObject; ELObject* ObjEnt; ELImportEntry* ResEnt; ELImportEntry* NextEnt; u32 file_id; if( elElfDesc == NULL) { return( FALSE); } if( my_dlld == 0) { ELi_SetResultCode( elElfDesc, NULL, EL_RESULT_INVALID_PARAMETER); return( FALSE); } /* Object to unlink */ MYObject = (ELObject*)my_dlld; /* Get the file ID of the object to unlink */ file_id = MYObject->file_id; #if 0 /* Hide all export information */ if( MYObject->ExportAdrEnt) { MYObject->HiddenAdrEnt = MYObject->ExportAdrEnt; MYObject->ExportAdrEnt = NULL; } #else /* Clear all export information */ elFreeAdrTbl( &(MYObject->ExportAdrEnt)); #endif /* Reference other objects and make the resolved portions unresolved */ ObjEnt = elElfDesc->ELObjectStart; while( ObjEnt != NULL) { ResEnt = ObjEnt->ResolvedImportAdrEnt; while( ResEnt != NULL) { NextEnt = ResEnt->next; PRINTDEBUG( "Compare ObjEnt:0x%x, ExpObjEnt:0x%x\n", ResEnt->Dlld, MYObject); if( ResEnt->Dlld == (struct ELObject*)MYObject) { PRINTDEBUG( "Unlink from ObjEnt:0x%x, ExpObjEnt:0x%x\n", ObjEnt, MYObject); /* Link from Resolved to Unresolved */ (void)ELi_ExtractImportEntry( &(ObjEnt->ResolvedImportAdrEnt), ResEnt); ELi_AddImportEntry( &(ObjEnt->UnresolvedImportAdrEnt), ResEnt); ResEnt->Dlld = NULL; } ResEnt = NextEnt; } ObjEnt = ObjEnt->next; } /*Do not destroy import information or self*/ /*Destroy the veneer table*/ (void)ELi_FreeVenTbl( elElfDesc, MYObject); /*Release the veneer link request*/ ELi_SetProcCode( elElfDesc, MYObject, EL_PROC_NOTHING); ELi_START_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim)); (void)ELi_UNREGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, file_id, (elElfDesc != i_eldesc_sim)); ELi_END_REGISTER_RELOCATION_INFO( ISTDRELOCATIONPROC_AUTO, (elElfDesc != i_eldesc_sim)); return( TRUE); } /*------------------------------------------------------ Deallocate all object lists -----------------------------------------------------*/ static void ELi_FreeObject( ELObject** ELObjEntStart) { ELObject* FwdObjEnt; ELObject* CurrentObjEnt; /*---------- Free the ELObject List ----------*/ CurrentObjEnt = (*ELObjEntStart); if( CurrentObjEnt) { do { FwdObjEnt = CurrentObjEnt; CurrentObjEnt = CurrentObjEnt->next; /**/ elFreeAdrTbl( &(FwdObjEnt->ExportAdrEnt)); elFreeAdrTbl( &(FwdObjEnt->HiddenAdrEnt)); ELi_FreeImportTbl( &(FwdObjEnt->ResolvedImportAdrEnt)); ELi_FreeImportTbl( &(FwdObjEnt->UnresolvedImportAdrEnt)); OSAPI_FREE( FwdObjEnt); }while( CurrentObjEnt != NULL); (*ELObjEntStart) = NULL; } /*----------------------------------*/ } /*------------------------------------------------------ Check whether there are unresolved external references remaining in the object -----------------------------------------------------*/ BOOL EL_IsResolved( ELDlld my_dlld) { ELObject* MYObject; if( my_dlld == 0) { return( FALSE); } MYObject = (ELObject*)my_dlld; /*TODO: Check whether MYObject is linked to the list*/ if( (MYObject->stat != 0)&&(MYObject->UnresolvedImportAdrEnt == NULL)) { return( TRUE); }else{ return( FALSE); } } /*------------------------------------------------------ Initializes the object management structure. -----------------------------------------------------*/ static void ELi_InitObject( ELObject* MYObject) { MYObject->next = NULL; MYObject->lib_size = 0; MYObject->ExportAdrEnt = NULL; MYObject->HiddenAdrEnt = NULL; MYObject->ResolvedImportAdrEnt = NULL; MYObject->UnresolvedImportAdrEnt = NULL; MYObject->ELVenEntStart = NULL; MYObject->ELV4tVenEntStart = NULL; MYObject->stat = 0; MYObject->process = (u32)EL_PROC_INITIALIZED; MYObject->result = (u32)EL_RESULT_SUCCESS; } /*------------------------------------------------------ Delete entry from the object table -----------------------------------------------------*/ BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt) { ELObject DmyObjEnt; ELObject* CurObjEnt; DmyObjEnt.next = (*StartEnt); CurObjEnt = &DmyObjEnt; while( CurObjEnt->next != ObjEnt) { if( CurObjEnt->next == NULL) { return FALSE; }else{ CurObjEnt = (ELObject*)CurObjEnt->next; } } /*Relink link list*/ CurObjEnt->next = ObjEnt->next; (*StartEnt) = DmyObjEnt.next; /*Free*/ elFreeAdrTbl( &(ObjEnt->ExportAdrEnt)); elFreeAdrTbl( &(ObjEnt->HiddenAdrEnt)); ELi_FreeImportTbl( &(ObjEnt->ResolvedImportAdrEnt)); ELi_FreeImportTbl( &(ObjEnt->UnresolvedImportAdrEnt)); ELi_InitObject( ObjEnt); //stat = 0; OSAPI_FREE( ObjEnt); return TRUE; } /*------------------------------------------------------ Add entry to object table -----------------------------------------------------*/ static void elAddObjEntry( ELObject** StartEnt, ELObject* ObjEnt) { ELObject DmyObjEnt; ELObject* CurObjEnt; if( (*StartEnt) == NULL) { (*StartEnt) = ObjEnt; }else{ DmyObjEnt.next = (*StartEnt); CurObjEnt = &DmyObjEnt; while( CurObjEnt->next != NULL) { CurObjEnt = (ELObject*)CurObjEnt->next; } CurObjEnt->next = (void*)ObjEnt; } ObjEnt->next = NULL; } /*------------------------------------------------------ Delete entry from address table -----------------------------------------------------*/ #if 0 BOOL elRemoveAdrEntry( ELAdrEntry* AdrEnt) { ELAdrEntry DmyAdrEnt; ELAdrEntry* CurrentAdrEnt; DmyAdrEnt.next = ELAdrEntStart; CurrentAdrEnt = &DmyAdrEnt; while( CurrentAdrEnt->next != AdrEnt) { if( CurrentAdrEnt->next == NULL) { return FALSE; }else{ CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; } } /*Relink link list*/ CurrentAdrEnt->next = AdrEnt->next; ELAdrEntStart = DmyAdrEnt.next; /*Free*/ OSAPI_FREE( AdrEnt); return TRUE; } #endif /*------------------------------------------------------ Add entry to address table -----------------------------------------------------*/ void elAddAdrEntry( ELAdrEntry** ELAdrEntStart, ELAdrEntry* AdrEnt) { ELAdrEntry DmyAdrEnt; ELAdrEntry* CurrentAdrEnt; if( (*ELAdrEntStart) == NULL) { (*ELAdrEntStart) = AdrEnt; }else{ DmyAdrEnt.next = (*ELAdrEntStart); CurrentAdrEnt = &DmyAdrEnt; while( CurrentAdrEnt->next != NULL) { CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; } CurrentAdrEnt->next = (void*)AdrEnt; } AdrEnt->next = NULL; } /*------------------------------------------------------ Add entry from application to address table -----------------------------------------------------*/ BOOL ELi_Export( ELDesc* elElfDesc, ELAdrEntry* AdrEnt) { ELAdrEntry DmyAdrEnt; ELAdrEntry* CurrentAdrEnt; if( elElfDesc == NULL) { return( FALSE); } if( elElfDesc->ELStaticObj == NULL) { elElfDesc->ELStaticObj = (ELObject*)ELi_Malloc( elElfDesc, NULL, sizeof( ELObject)); if(elElfDesc->ELStaticObj == NULL) { return( FALSE); } ELi_InitObject( elElfDesc->ELStaticObj); elAddObjEntry( &(elElfDesc->ELObjectStart), elElfDesc->ELStaticObj); } if( !(elElfDesc->ELStaticObj->ExportAdrEnt)) { elElfDesc->ELStaticObj->ExportAdrEnt = (ELAdrEntry*)AdrEnt; }else{ DmyAdrEnt.next = (ELAdrEntry*)elElfDesc->ELStaticObj->ExportAdrEnt; CurrentAdrEnt = &DmyAdrEnt; while( CurrentAdrEnt->next != NULL) { CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; } CurrentAdrEnt->next = (void*)AdrEnt; } AdrEnt->next = NULL; return( TRUE); } /*------------------------------------------------------ Add entry of static side to address table -----------------------------------------------------*/ #ifndef SDK_TWL SDK_WEAK_SYMBOL void EL_AddStaticSym( void) //__declspec(weak) void EL_AddStaticSym( void) #else SDK_WEAK_SYMBOL void EL_AddStaticSym( void) #endif { PRINTDEBUG( "please link file which is generated by \"makelst\".\n"); while( 1) {}; } /*------------------------------------------------------ Return entry corresponding to specified character string from entire address table and set the object that is exporting that entry to the ExpObEnt -----------------------------------------------------*/ ELAdrEntry* elGetAdrEntry( ELDesc* elElfDesc, const char* ent_name, ELObject** ExpObjEnt) { ELObject* ObjEnt; ELAdrEntry* CurrentAdrEnt; ObjEnt = elElfDesc->ELObjectStart; while( ObjEnt != NULL) { CurrentAdrEnt = ObjEnt->ExportAdrEnt; while( CurrentAdrEnt != NULL) { if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) { (*ExpObjEnt) = ObjEnt; //Specify object that is exporting goto get_end; } CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; } ObjEnt = ObjEnt->next; } (*ExpObjEnt) = NULL; //Nobody is exporting get_end: return CurrentAdrEnt; } /*------------------------------------------------------ Return address corresponding to specified string in address table -----------------------------------------------------*/ void* ELi_GetGlobalAdr( ELDesc* elElfDesc, ELDlld my_dlld, const char* ent_name) { u32 adr; ELAdrEntry* CurrentAdrEnt; ELObject* DmyObjEnt; if( elElfDesc == NULL) { return( 0); } if( my_dlld == 0) { /*Search from entirety*/ CurrentAdrEnt = elGetAdrEntry( elElfDesc, ent_name, &DmyObjEnt); }else{ /*Search from specific objects*/ CurrentAdrEnt = ((ELObject*)my_dlld)->ExportAdrEnt; while( CurrentAdrEnt != NULL) { if( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) == 0) { break; } CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; } } if( CurrentAdrEnt) { if( CurrentAdrEnt->thumb_flag) { //TODO: only for func_flag adr = (u32)(CurrentAdrEnt->adr) + 1; }else{ adr = (u32)(CurrentAdrEnt->adr); } }else{ adr = 0; } return (void*)(adr); } /*------------------------------------------------------ Release all address tables -----------------------------------------------------*/ static void elFreeAdrTbl( ELAdrEntry** ELAdrEntStart) { ELAdrEntry* FwdAdrEnt; ELAdrEntry* CurrentAdrEnt; /*---------- Free the ELAdrEntry List ----------*/ CurrentAdrEnt = (*ELAdrEntStart); if( CurrentAdrEnt) { do { FwdAdrEnt = CurrentAdrEnt; CurrentAdrEnt = CurrentAdrEnt->next; OSAPI_FREE( FwdAdrEnt->name); //Symbol name character-string OSAPI_FREE( FwdAdrEnt); //Structure itself }while( CurrentAdrEnt != NULL); (*ELAdrEntStart) = NULL; } /*------------------------------------*/ } /*------------------------------------------------------ Stub that reads data from the ELF object -----------------------------------------------------*/ static BOOL ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) { #pragma unused( file_base) if( FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET) == FALSE) { return( FALSE); } if( FS_ReadFile( file_struct, buf, (s32)(size)) == (s32)size) { return( TRUE); }else{ return( FALSE); } } static BOOL ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) { #pragma unused(file_struct) OSAPI_CPUCOPY8( (void*)(file_base + file_offset), buf, size); return( TRUE); } static BOOL ELi_ReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) { #pragma unused(file_struct) #pragma unused(file_base) if( i_elReadImage( file_offset, buf, size) == 0) { return( TRUE); } return( FALSE); } /*------------------------------------------------------ Set of error codes/process codes Set ELResult when initial value is SUCCESS and an error occurs Set ELProcess when the initial value is INITIALIZED, and in conjunction with progress. -----------------------------------------------------*/ void ELi_SetResultCode( ELDesc* elElfDesc, ELObject* MYObject, ELResult result) { if( elElfDesc != NULL) { elElfDesc->result = (u32)result; } if( MYObject != NULL) { MYObject->result = (u32)result; } } void ELi_SetProcCode( ELDesc* elElfDesc, ELObject* MYObject, ELProcess process) { if( elElfDesc != NULL) { elElfDesc->process = (u32)process; } if( MYObject != NULL) { MYObject->process = (u32)process; } }