diff --git a/build/libraries/devices/sdmc/ARM7/drnand.c b/build/libraries/devices/sdmc/ARM7/drnand.c index e13e38b..6bdde1e 100644 --- a/build/libraries/devices/sdmc/ARM7/drnand.c +++ b/build/libraries/devices/sdmc/ARM7/drnand.c @@ -539,7 +539,7 @@ static BOOL sdi_get_nom( u32 MIN_NOM) u32 SS = 512; //セクタサイズ(FIX) u32 SC, n, MAX, SFdash; u16 i; - + RSC[0] = 1; //FAT12,16では1 RSC[1] = 1; RSC[2] = 1; diff --git a/build/libraries/el/ARM7/Makefile b/build/libraries/el/ARM7/Makefile new file mode 100644 index 0000000..9ec01e7 --- /dev/null +++ b/build/libraries/el/ARM7/Makefile @@ -0,0 +1,66 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - el/ARM7 +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +TWL_CODEGEN_ALL ?= True + +# Codegen for sub processer +TWL_PROC = ARM7 + +SRCDIR = ../common . +SRCDIR += $(TWL_NITROSDK_ROOT)/build/libraries/el/common/src \ + $(TWL_NITROSDK_ROOT)/build/libraries/el/ARM7/src \ + +INCDIR = ../common +INCDIR += $(TWL_NITROSDK_ROOT)/build/libraries/el/common/include \ + +SRCS = arch.c \ + elf.c \ + elf_loader.c \ + loader_subset.c \ + +TARGET_LIB = libel_sp$(TWL_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +# DEBUG版ビルドの場合、RELEASE版でビルドして +# DEBUG版のライブラリを装います。 + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(TWL_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/el/ARM9/Makefile b/build/libraries/el/ARM9/Makefile new file mode 100644 index 0000000..4d1746f --- /dev/null +++ b/build/libraries/el/ARM9/Makefile @@ -0,0 +1,53 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - el/ARM9 +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +TWL_CODEGEN_ALL ?= True + +SRCDIR = ../common . +SRCDIR += $(TWL_NITROSDK_ROOT)/build/libraries/el/common/src \ + $(TWL_NITROSDK_ROOT)/build/libraries/el/ARM9/src \ + +INCDIR = ../common +INCDIR += $(TWL_NITROSDK_ROOT)/build/libraries/el/common/include \ + +SRCS = arch.c \ + elf.c \ + elf_loader.c \ + loader_subset.c \ + +TARGET_LIB = libel$(TWL_LIBSUFFIX).a + + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(TWL_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/el/Makefile b/build/libraries/el/Makefile new file mode 100644 index 0000000..465d136 --- /dev/null +++ b/build/libraries/el/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - el +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +#ifdef TWL_WITH_ARM7 +SUBDIRS += ARM7 +#endif + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/el/common/Makefile b/build/libraries/el/common/Makefile new file mode 100644 index 0000000..97f9022 --- /dev/null +++ b/build/libraries/el/common/Makefile @@ -0,0 +1,20 @@ +# +# Makefile +# +L_MAIN_DIR := ../../.. +include $(L_MAIN_DIR)/make/Makefile.defs + +L_TARGETS := libel.a + +L_SOURCES := elf.c arch.c elf_loader.c loader_subset.c + +L_INCLUDES := -I. \ + -I$(D_MAIN_DIR)/include/el \ + +L_LDLIBS := + +L_DEFS := + +L_DEPENDANCIES := + +include $(D_MAIN_DIR)/make/Makefile.rules diff --git a/build/libraries/el/common/arch.c b/build/libraries/el/common/arch.c new file mode 100644 index 0000000..8440aef --- /dev/null +++ b/build/libraries/el/common/arch.c @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: arch.c + + Copyright 2006,2007 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. + *---------------------------------------------------------------------------*/ + +#include "el_config.h" + +#if (TARGET_OS_NITRO == 1) + #include +#else + #include +#endif + +#include "arch.h" + + +/*--------------------------------------------------------- + エントリヘッダからエントリのサイズを求める + --------------------------------------------------------*/ +u32 AR_GetEntrySize( ArchHdr* ArHdr) +{ + u16 i; + u32 digit = 1; + u32 size = 0; + + /*----- 何桁あるか調べる -----*/ + for( i=0; i<10; i++) { + if( ArHdr->ar_size[i] == 0x20) { + break; + }else{ + digit *= 10; + } + } + digit /= 10; + /*----------------------------*/ + + /*----- サイズを算出する -----*/ + for( i=0; i<10; i++) { + size += (*(((u8*)(ArHdr->ar_size))+i) - 0x30) * digit; //charをu8に変換 + if( digit == 1) { + break; + }else{ + digit /= 10; + } + } + /*----------------------------*/ + + return size; +} + + diff --git a/build/libraries/el/common/arch.h b/build/libraries/el/common/arch.h new file mode 100644 index 0000000..f03f8cb --- /dev/null +++ b/build/libraries/el/common/arch.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: arch.h + + Copyright 2006,2007 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 ARCH_H_ +#define ARCH_H_ + + + +/*--------------------------------------------------------- + Archive Header + --------------------------------------------------------*/ +#define ARMAG "!\n" /* magic string */ +#define SARMAG 8 /* length of magic string */ + +#define ARFMAG "\`\n" /* header trailer string */ +#define AR_NAME_LEN 16 /* ar_name size, includes `/' */ + + +typedef struct /* archive file member header - printable ascii */ +{ + char ar_name[16]; /* file member name - `/' terminated */ + char ar_date[12]; /* file member date - decimal */ + char ar_uid[6]; /* file member user id - decimal */ + char ar_gid[6]; /* file member group id - decimal */ + char ar_mode[8]; /* file member mode - octal */ + char ar_size[10]; /* file member size - decimal */ + char ar_fmag[2]; /* ARFMAG - string to end header */ +}ArchHdr; /* 計60(0x3C)バイト */ + + + + + + +/*--------------------------------------------------------- + エントリヘッダからエントリのサイズを求める + --------------------------------------------------------*/ +u32 AR_GetEntrySize( ArchHdr* ArHdr); + + +#endif /*ARCH_H_*/ diff --git a/build/libraries/el/common/el_config.h b/build/libraries/el/common/el_config.h new file mode 100644 index 0000000..8929175 --- /dev/null +++ b/build/libraries/el/common/el_config.h @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader Configuration + File: el_config.h + + Copyright 2006,2007 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 __ELF_LOADER_CONFIG_H__ +#define __ELF_LOADER_CONFIG_H__ + +/*********************************************************************** + デバッグプリント ON/OFF +***********************************************************************/ +#define DEBUG_PRINT_ON (0) + +/*********************************************************************** + ターゲットOS指定 +***********************************************************************/ +#define TARGET_OS_NITRO (1) +#define TARGET_OS_CTR (TARGET_OS_NITRO ^ 1) + +/*********************************************************************** + ターゲットARMアーキテクチャ指定(ARM7TDMIはV4にする) +***********************************************************************/ +#ifdef SDK_ARM7 + #define TARGET_ARM_V4 (1) +#else + #define TARGET_ARM_V4 (0) +#endif + +#define TARGET_ARM_V5 (TARGET_ARM_V4 ^ 1) + + +/*********************************************************************** + NITRO OSのとき +***********************************************************************/ +#if (TARGET_OS_NITRO == 1) + + #if( DEBUG_PRINT_ON == 1) + #define PRINTDEBUG OS_TPrintf + #else + #define PRINTDEBUG( ...) ((void)0) + #endif + + + #define OSAPI_CPUFILL8 MI_CpuFill8 + #define OSAPI_CPUCOPY8 MI_CpuCopy8 + #define OSAPI_MALLOC OS_Alloc + #define OSAPI_FREE OS_Free + #define OSAPI_STRLEN STD_GetStringLength + #define OSAPI_STRNCMP STD_CompareNString + #define OSAPI_STRCMP STD_CompareString + #define OSAPI_FLUSHCACHEALL DC_FlushAll + #define OSAPI_WAITCACHEBUF DC_WaitWriteBufferEmpty + + +/*********************************************************************** + CTR OSのとき +***********************************************************************/ +#else + + #if (DEBUG_PRINT_ON == 1) + #if (CTR_DEF_ENVIRONMENT_DSEMU == 1) + #define PRINTDEBUG osTPrintf + #else + #include + #define PRINTDEBUG vlink_dos_printf + #endif + #else + #define PRINTDEBUG( ...) ((void)0) + #endif + + + #define OSAPI_CPUFILL8 miCpuFill8 + #define OSAPI_CPUCOPY8 miCpuCopy8 + #define OSAPI_MALLOC i_elAlloc + #define OSAPI_FREE i_elFree + #define OSAPI_STRLEN strlen + #define OSAPI_STRNCMP strncmp + #define OSAPI_STRCMP strcmp + #define OSAPI_FLUSHCACHEALL osFlushDCacheAll + #define OSAPI_WAITCACHEBUF osWaitWriteBufferEmpty + + +#endif + + +#endif /*__ELF_LOADER_CONFIG_H__*/ diff --git a/build/libraries/el/common/elf.c b/build/libraries/el/common/elf.c new file mode 100644 index 0000000..5940755 --- /dev/null +++ b/build/libraries/el/common/elf.c @@ -0,0 +1,351 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: elf.c + + Copyright 2006,2007 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. + *---------------------------------------------------------------------------*/ + +#include "el_config.h" + +#if (TARGET_OS_NITRO == 1) + #include +#else + #include +#endif + +#include "elf.h" + +static int endian; +static BOOL load_strndx_done = FALSE; + + +/*--------------------------------------------------------- + バイトデータを読み出す + --------------------------------------------------------*/ +static u8 *load_elf32_byte(u8 *dest, u8 *org, int lsb) +{ + u8 *temp_ptr; + + temp_ptr = (u8 *)org; + *dest = *temp_ptr; + temp_ptr++; + + return temp_ptr; +} + +/*--------------------------------------------------------- + ハーフワードデータを読み出す + --------------------------------------------------------*/ +static u8 *load_elf32_half(Elf32_Half *dest, u8 *org, int lsb) +{ + u8 *temp_ptr; + + temp_ptr = (u8 *)org; + if( lsb == ELFDATA2LSB ) { + *dest = (u16)((u16)(*temp_ptr) & 0x00ff); + temp_ptr++; + *dest |= ((u16)(*temp_ptr) << 8 ) & 0xff00; + temp_ptr++; + } + else /* ELFDATA2MSB */ { + *dest = (u16)(((u16)(*temp_ptr) << 8 ) & 0xff00); + temp_ptr++; + *dest |= ((u16)(*temp_ptr) & 0x00ff); + temp_ptr++; + } + return (void *)temp_ptr; +} + +/*--------------------------------------------------------- + ワードデータを読み出す + --------------------------------------------------------*/ +static u8 *load_elf32_sword(Elf32_Sword *dest, u8 *org, int lsb) +{ + u8 *temp_ptr; + u32 temp; + + temp_ptr = (u8 *)org; + if( lsb == ELFDATA2LSB ) { + temp = ((u32)(*temp_ptr) & 0x000000ff); + temp_ptr++; + temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00); + temp_ptr++; + temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000); + temp_ptr++; + temp |= (((u32)(*temp_ptr) << 24 ) & 0xff000000); + temp_ptr++; + } + else /* ELFDATA2MSB */ { + temp = (((u32)(*temp_ptr) << 24 ) & 0xff000000); + temp_ptr++; + temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000); + temp_ptr++; + temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00); + temp_ptr++; + temp |= ((u32)(*temp_ptr) & 0x000000ff); + temp_ptr++; + } + *dest = *( (Elf32_Sword *)&temp ); + return (void *)temp_ptr; +} + + +static u8 *load_elf32_word(Elf32_Word *dest, u8 *org, int lsb) +{ + u8 *temp_ptr; + temp_ptr = (u8 *)org; + if( lsb == ELFDATA2LSB ) { + *dest = ((u32)(*temp_ptr) & 0x000000ff); + temp_ptr++; + *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00); + temp_ptr++; + *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000); + temp_ptr++; + *dest |= (((u32)(*temp_ptr) << 24 ) & 0xff000000); + temp_ptr++; + } + else /* ELFDATA2MSB */ { + *dest = (((u32)(*temp_ptr) << 24 ) & 0xff000000); + temp_ptr++; + *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000); + temp_ptr++; + *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00); + temp_ptr++; + *dest |= ((u32)(*temp_ptr) & 0x000000ff); + temp_ptr++; + } + return (void *)temp_ptr; +} + +/*--------------------------------------------------------- + ELFヘッダを読み出す + + buf : ELFヘッダのアドレス + ehdr : 読み出したデータを書き込むバッファ + --------------------------------------------------------*/ +void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr) +{ + u8 *file_ptr; + + if( !buf ) { + return NULL; + } + + file_ptr = (u8 *)buf; + + /* バッファにコピー */ + OSAPI_CPUCOPY8( (void*)file_ptr, ehdr->e_ident, EI_NIDENT); + file_ptr += EI_NIDENT; + + /* Magic number */ + if( ehdr->e_ident[EI_MAG0] != ELFMAG0 ) { + return NULL; + } + if( ehdr->e_ident[EI_MAG1] != ELFMAG1 ) { + return NULL; + } + if( ehdr->e_ident[EI_MAG2] != ELFMAG2 ) { + return NULL; + } + if( ehdr->e_ident[EI_MAG3] != ELFMAG3 ) { + return NULL; + } + + /* CLASS */ + switch( ehdr->e_ident[EI_CLASS] ) { + case ELFCLASSNONE: + break; + case ELFCLASS32: + break; + case ELFCLASS64: + break; + default: + break; + } + + /* DATA */ + switch( ehdr->e_ident[EI_DATA] ) { + case ELFDATANONE: + break; + case ELFDATA2LSB: + endian = ELFDATA2LSB; + break; + case ELFDATA2MSB: + endian = ELFDATA2MSB; + break; + default: + break; + } + + /* TYPE */ + file_ptr = load_elf32_half(&(ehdr->e_type), file_ptr, endian); + switch( ehdr->e_type ) { + case ET_NONE: + break; + case ET_REL: + break; + case ET_EXEC: + break; + case ET_DYN: + break; + case ET_CORE: + break; + case ET_LOPROC: + break; + case ET_HIPROC: + break; + default: + break; + } + + /*---------- ELFヘッダ表示 ----------*/ + PRINTDEBUG( "\nELF Header:\n"); + file_ptr = load_elf32_half(&(ehdr->e_machine), file_ptr, endian); + PRINTDEBUG("e_machine = %d\n",ehdr->e_machine); + + file_ptr = load_elf32_word(&(ehdr->e_version), file_ptr, endian); + PRINTDEBUG("e_version = %d\n",ehdr->e_version); + + file_ptr = load_elf32_word(&(ehdr->e_entry), file_ptr, endian); + PRINTDEBUG("e_entry(entry point) = 0x%08x\n",ehdr->e_entry); + + file_ptr = load_elf32_word(&(ehdr->e_phoff), file_ptr, endian); + PRINTDEBUG("e_phoff(program header offset) = 0x%08x\n",ehdr->e_phoff); + + file_ptr = load_elf32_word(&(ehdr->e_shoff), file_ptr, endian); + PRINTDEBUG("e_shoff(section header offset) = 0x%08x\n",ehdr->e_shoff); + + file_ptr = load_elf32_word(&(ehdr->e_flags), file_ptr, endian); + PRINTDEBUG("e_flags = 0x%08x\n",ehdr->e_flags); + if( ehdr->e_flags & EF_ARM_HASENTRY ) { + PRINTDEBUG("has entry\n"); + } + if( ehdr->e_flags & EF_ARM_SYMSARESORTED ) { + PRINTDEBUG("symbols are sorted\n"); + } + if( ehdr->e_flags & EF_ARM_DYNSYMSUSESEGIDX ) { + PRINTDEBUG("dynamic symbols use segmnet index\n"); + } + if( ehdr->e_flags & EF_ARM_MAPSYMSFIRST ) { + PRINTDEBUG("map symbols first\n"); + } + PRINTDEBUG("EABI version %x \n", (ehdr->e_flags & EF_ARM_EABIMASK) >> 24 ); + + + file_ptr = load_elf32_half(&(ehdr->e_ehsize), file_ptr, endian); + PRINTDEBUG("e_ehsize = %d\n",ehdr->e_ehsize); + + file_ptr = load_elf32_half(&(ehdr->e_phentsize), file_ptr, endian); + PRINTDEBUG("e_phentsize = %d\n",ehdr->e_phentsize); + + file_ptr = load_elf32_half(&(ehdr->e_phnum), file_ptr, endian); + PRINTDEBUG("e_phnum = %d\n",ehdr->e_phnum); + + file_ptr = load_elf32_half(&(ehdr->e_shentsize), file_ptr, endian); + PRINTDEBUG("e_shentsize = %d\n",ehdr->e_shentsize); + + file_ptr = load_elf32_half(&(ehdr->e_shnum), file_ptr, endian); + PRINTDEBUG("e_shnum = %d\n",ehdr->e_shnum); + + file_ptr = load_elf32_half(&(ehdr->e_shstrndx), file_ptr, endian); + PRINTDEBUG("e_shstrndx(section index no. of the section header string table section = %d\n",ehdr->e_shstrndx); + PRINTDEBUG( "\n"); + /*-----------------------------------*/ + + return file_ptr; +} + + +/*--------------------------------------------------------- + Relocation Entry Load + --------------------------------------------------------*/ +static void *ELF_LoadRel(const void *buf, Elf32_Rel *rel) +{ + u8 *file_ptr; + + if( !buf ) { + return NULL; + } + + file_ptr = (u8 *)buf; + file_ptr = load_elf32_word(&(rel->r_offset), file_ptr, endian); + file_ptr = load_elf32_word(&(rel->r_info), file_ptr, endian); + + return file_ptr; +} + +static void *ELF_LoadRela(const void *buf, Elf32_Rela *rela) +{ + u8 *file_ptr; + + if( !buf ) { + return NULL; + } + + file_ptr = (u8 *)buf; + file_ptr = load_elf32_word(&(rela->r_offset), file_ptr, endian); + file_ptr = load_elf32_word(&(rela->r_info), file_ptr, endian); + file_ptr = load_elf32_sword(&(rela->r_addend), file_ptr, endian); + + return file_ptr; +} + + +/*--------------------------------------------------------- + Symbol Table Entry Load + buf : シンボルエントリをロードしたいバッファへのポインタ + sym : ロード元シンボルエントリの先頭アドレス + --------------------------------------------------------*/ +static void *ELF_LoadSymbol(const void *buf, Elf32_Sym *sym) +{ + u8 *file_ptr; + + if( !buf ) { + return NULL; + } + + file_ptr = (u8 *)buf; + file_ptr = load_elf32_word(&(sym->st_name), file_ptr, endian); + file_ptr = load_elf32_word(&(sym->st_value), file_ptr, endian); + file_ptr = load_elf32_word(&(sym->st_size), file_ptr, endian); + file_ptr = load_elf32_byte(&(sym->st_info), file_ptr, endian); + file_ptr = load_elf32_byte(&(sym->st_other), file_ptr, endian); + file_ptr = load_elf32_half(&(sym->st_shndx), file_ptr, endian); + + return file_ptr; +} + + +/*--------------------------------------------------------- + Section Header Load + buf : セクションヘッダをロードしたいバッファへのポインタ + shdr : ロード元セクションヘッダの先頭アドレス + --------------------------------------------------------*/ +static void *ELF_LoadSectionHeader(const void *buf,Elf32_Shdr *shdr) +{ + u8 *file_ptr; + + if( !buf ) { + return NULL; + } + + file_ptr = (u8 *)buf; + file_ptr = load_elf32_word(&(shdr->sh_name), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_type), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_flags), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_addr), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_offset), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_size), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_link), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_info), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_addralign), file_ptr, endian); + file_ptr = load_elf32_word(&(shdr->sh_entsize ), file_ptr, endian); + + return file_ptr; +} diff --git a/build/libraries/el/common/elf.h b/build/libraries/el/common/elf.h new file mode 100644 index 0000000..ab47a20 --- /dev/null +++ b/build/libraries/el/common/elf.h @@ -0,0 +1,435 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: elf.h + + Copyright 2006,2007 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 ELF_H_ +#define ELF_H_ + +#include "el_config.h" +#if (TARGET_OS_NITRO == 1) +#else +#include +#endif + +/*--------------------------------------------------------- + 型定義 + --------------------------------------------------------*/ +typedef u32 Elf32_Addr; /* size:4, align:4 Unsigned program address */ +typedef u16 Elf32_Half; /* size:2, align:2 Unsigned medium int */ +typedef u32 Elf32_Off; /* size:4, align:4 Unsigned file offset */ +typedef s32 Elf32_Sword; /* size:4, align:4 Signed large int */ +typedef u32 Elf32_Word; /* size:4, align:4 Unsigned large int */ + +/*--------------------------------------------------------- + ELF Header + --------------------------------------------------------*/ +/* e_identのインデックス */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class 0=invalid, 1=32bit, 2=64bit */ +#define EI_DATA 5 /* Data encoding 0=invalid, 1=LSB, 2=MSB */ +#define EI_VERSION 6 /* File version 現在は1 */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; /* ELFの形式(再配置可能, 実行可能など) */ + Elf32_Half e_machine; /* ファイルで要求されるアーキテクチャ */ + Elf32_Word e_version; /* ELFフォーマットのバージョン(現在は1) */ + Elf32_Addr e_entry; /* プログラムのエントリポイント。指定無しなら0。 */ + Elf32_Off e_phoff; /* プログラムヘッダテーブルのファイル先頭からのオフセット */ + Elf32_Off e_shoff; /* セクションヘッダテーブルのファイル先頭からのオフセット */ + Elf32_Word e_flags; /* プロセッサ固有のフラグ */ + Elf32_Half e_ehsize; /* ELFヘッダのサイズ */ + Elf32_Half e_phentsize; /* 1プログラムヘッダのサイズ */ + Elf32_Half e_phnum; /* プログラムヘッダの数 */ + Elf32_Half e_shentsize; /* 1セクションヘッダのサイズ */ + Elf32_Half e_shnum; /* セクションヘッダの数 */ + Elf32_Half e_shstrndx; /* セクション名文字列テーブルセクションへのインデックス */ +} Elf32_Ehdr; + +/* e_ident[EI_*]の中身定義 */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* ARM and Thumb processors use 32-bit ELF. */ +#define ELFCLASS64 2 +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* little-endian */ +#define ELFDATA2MSB 2 /* big-endian */ + + +/* [e_type] */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* [e_machine] */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_MIPS_RS4_BE 10 +#define EM_ARM 40 /* ARM/Thumb Architecture */ + + +/* [e_version] This member identifies the object file version.*/ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + + +/* + ARM-specific e_flags + e_flags Field Value Meaning + EF_ARM_HASENTRY (0x02) e_entry contains a program-loader entry point + (see section 4.1.1, Entry points, below). + EF_ARM_SYMSARESORTED (0x04) Each subsection of the symbol table is sorted by symbol value + (see section 4.4.8, Symbol table order, below) + EF_ARM_DYNSYMSUSESEGIDX (0x8) Symbols in dynamic symbol tables that are defined in sections + included in program segment n have st_shndx = n + 1. + (see section 4.4.9, Dynamic symbol table entries, below). + EF_ARM_MAPSYMSFIRST (0x10) Mapping symbols precede other local symbols in the symbol table + (see section 4.4.8, Symbol table order, below). + + EF_ARM_EABIMASK (0xFF000000)(current version is 0x02000000) + This masks an 8-bit version number, the version of the ARM + EABI to which this ELF file conforms. This EABI is version 2. A + value of 0 denotes unknown conformance. +*/ +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0xFF000000 + + +/*--------------------------------------------------------- + Program headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* [p_type] */ +#define PT_NULL 0 /* 使われないエントリで、他のメンバの値の意味は未定義 */ +#define PT_LOAD 1 /* 実行時にロードされるセグメント */ +#define PT_DYNAMIC 2 /* 動的構造体配列を保持するセグメント */ +#define PT_INTERP 3 /* ファイルの解釈に使われるインタプリタのパスを保持するセグメント */ +#define PT_NOTE 4 /* ファイルの解釈には使われない情報を保持するセグメント */ +#define PT_SHLIB 5 /* 予約 */ +#define PT_PHDR 6 /* プログラムヘッダテーブル(プログラムのメモリイメージの一部である場合のみ存在) */ +//#define PT_TLS ? /* スレッド局所記憶領域のテンプレート */ + +#define PT_LOOS 0x60000000 /* OS固有に予約された領域 */ +#define PT_HIOS 0x6fffffff + +#define PT_LOPROC 0x70000000 /* プロセッサ固有に予約された領域 */ +#define PT_HIPROC 0x7fffffff + +/* [p_flags]*/ +#define PF_X 1 /*実行可能*/ +#define PF_W 2 /*書き込み可能*/ +#define PF_R 4 /*読み出し可能*/ +#define PF_ARM_SB 0x10000000 /*The segment contains the location addressed by the static base*/ +#define PF_ARM_PI 0x20000000 /*The segment is position-independent*/ +#define PF_ARM_ENTRY 0x80000000 /*The segment contains the entry point*/ +#define PF_MASKPROC 0xf0000000 + + +/*--------------------------------------------------------- + Section headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word sh_name; /*セクションヘッダ文字列テーブルセクションのインデックス*/ + Elf32_Word sh_type; /* タイプ(下記定義参照) */ + Elf32_Word sh_flags; + Elf32_Addr sh_addr; /* */ + Elf32_Off sh_offset; /* ファイルの先頭からのオフセット */ + Elf32_Word sh_size; /* バイト単位のサイズ */ + Elf32_Word sh_link; /* sh_typeによって値の意味が変わる */ + Elf32_Word sh_info; /* sh_typeによって値の意味が変わる */ + Elf32_Word sh_addralign; /* アラインメント制限(0or1で制限なし,4で4ByteAlign) */ + Elf32_Word sh_entsize; /* 固定サイズのエントリテーブルがある場合、1要素のサイズ */ +} Elf32_Shdr; + +/* sh_addr mod sh_addralign = 0 でなければならない */ + +/* Section Types, [sh_type] */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + + +/* [sh_flags] */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 +/* ARM-EABI-specific */ +#define SHF_ENTRYSECT 0x10000000 /* The section contains an entry point. */ +#define SHF_COMDEF 0x80000000 /* The section may be multiply defined in the input to a link step. */ +/* others */ +#define SHF_LINK_ORDER 0x80 + +/*セクションインデックス*/ +//Sym->st_shndxなど +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + + +//ここからはヘッダでなく実体データ構造 + +/*--------------------------------------------------------- + Symbol Table Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Word st_name; /* シンボル文字列テーブルのインデックス */ + Elf32_Addr st_value; /* おそらく関連するセクション内でのオフセット値 */ + Elf32_Word st_size; /* サイズがないか、不明な場合は 0 */ + unsigned char st_info; /* バインド と タイプ */ + unsigned char st_other; /* 現在は 0 が入る */ + Elf32_Half st_shndx; /* 関連するセクションヘッダテーブルのインデックス */ +} Elf32_Sym; + + +/* st_info */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* st_info の BIND */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* st_info の TYPE */ +#define STT_NOTYPE 0 /*未定義*/ +#define STT_OBJECT 1 /*データオブジェクト*/ +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + +/*--------------------------------------------------------- + Relocation Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + + +/* r_info の TYPE */ +#define R_ARM_NONE 0 /* Any No relocation. Encodes dependencies between sections. */ +#define R_ARM_PC24 1 /* ARM B/BL S . P + A */ +#define R_ARM_ABS32 2 /* 32-bit word S + A */ +#define R_ARM_REL32 3 /* 32-bit word S . P + A */ +#define R_ARM_PC13 4 /* ARM LDR r, [pc,…] S . P + A */ +#define R_ARM_ABS16 5 /* 16-bit half-word S + A */ +#define R_ARM_ABS12 6 /* ARM LDR/STR S + A */ +#define R_ARM_THM_ABS5 7 /* Thumb LDR/STR S + A */ +#define R_ARM_ABS8 8 /* 8-bit byte S + A */ +#define R_ARM_SBREL32 9 /* 32-bit word S . B + A */ +#define R_ARM_THM_PC22 10 /* Thumb BL pair S . P+ A */ +#define R_ARM_THM_PC8 11 /* Thumb LDR r, [pc,…] S . P + A */ +#define R_ARM_AMP_VCALL9 12 /* AMP VCALL Obsolete.SA-1500 only. */ +#define R_ARM_SWI24 13 /* ARM SWI S + A */ +#define R_ARM_THM_SWI8 14 /* Thumb SWI S + A */ +#define R_ARM_XPC25 15 /* ARM BLX S . P+ A */ +#define R_ARM_THM_XPC22 16 /* Thumb BLX pair S . P+ A */ + +/* 17-31, reserved to ARM Linux */ +//17-19 Reserved to ARM LINUX +#define R_ARM_COPY 20 /* 32 bit word Copy symbol at dynamic link time. */ +#define R_ARM_GLOB_DAT 21 /* 32 bit word Create GOT entry. */ +#define R_ARM_JUMP_SLOT 22 /* 32 bit word Create PLT entry. */ +#define R_ARM_RELATIVE 23 /* 32 bit word Adjust by program base. */ +#define R_ARM_GOTOFF 24 /* 32 bit word Offset relative to start of GOT. */ +#define R_ARM_GOTPC 25 /* 32 bit word Insert address of GOT. */ +#define R_ARM_GOT32 26 /* 32 bit word Entry in GOT. */ +#define R_ARM_PLT32 27 /* ARM BL Entry in PLT. */ + +/* 28-31 Reserved to ARM LINUX */ +#define R_ARM_ALU_PCREL_7_0 32 /* ARM ADD/SUB (S . P + A) & 0x000000FF */ +#define R_ARM_ALU_PCREL_15_8 33 /* ARM ADD/SUB (S . P + A) & 0x0000FF00 */ +#define R_ARM_ALU_PCREL_23_15 34 /* ARM ADD/SUB (S . P + A) & 0x00FF0000 */ +#define R_ARM_LDR_SBREL_11_0 35 /* ARM LDR/STR (S . B + A) & 0x00000FFF */ +#define R_ARM_ALU_SBREL_19_12 36 /* ARM ADD/SUB (S . B + A) & 0x000FF000 */ +#define R_ARM_ALU_SBREL_27_20 37 /* ARM ADD/SUB (S . B + A) & 0x0FF00000 */ + +#define R_ARM_TARGET1 38 +#define R_ARM_ROSEGREL32 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 + +/* 96-111, reserved to ARM g++ */ +#define R_ARM_GNU_VTENTRY 100 /* 32 bit word Record C++ vtable entry. */ +#define R_ARM_GNU_VTINHERIT 101 /* 32 bit word Record C++ member usage. */ +#define R_ARM_THM_PC11 102 /* Thumb B S . P + A */ +#define R_ARM_THM_PC9 103 /* Thumb B S . P + A */ + +/* 112-127, reserved for private experiments */ + +/* 128-248, reserved to ARM */ +#define R_ARM_RXPC25 249 /* ARM BLX (ΔS . ΔP) + A #define For calls between program segments. */ +#define R_ARM_RSBREL32 250 /* Word (ΔS . ΔSB) + A For an offset from SB, the static base. */ +#define R_ARM_THM_RPC22 251 /* Thumb BL/BLX pair (ΔS . ΔP) + A For calls between program segments. */ +#define R_ARM_RREL32 252 /* Word (ΔS . ΔP) + A For on offset between two segments. */ +#define R_ARM_RABS32 253 /* Word ΔS + A For the address of a location in the target segment. */ +#define R_ARM_RPC24 254 /* ARM B/BL (ΔS . ΔP) + A For calls between program segments. */ +#define R_ARM_RBASE 255 /* None None.Identifies the segment being relocated by the following + relocation directives. The ARM EABI poses two problems for relocating + executables and shared objects encoded in */ + + +// shirait +#define R_ARM_LDR_PC_G0 4 //LDR + +#define R_ARM_ABS12 6 //LDR, STR + +#define R_ARM_THM_CALL 10 //R_ARM_THM_PC22と同じ + +#define R_ARM_CALL 28 //BL/BLX +#define R_ARM_JUMP24 29 //B/BL +#define R_ARM_THM_JUMP24 30 + +#define R_ARM_MOVW_ABS_NC 43 //MOVW +#define R_ARM_MOVT_ABS 44 //MOVT +#define R_ARM_MOVW_PREL_NC 45 //MOVW +#define R_ARM_MOVT_PREL 46 //MOVT + +#define R_ARM_ALU_PC_G0_NC 57 //ADD, SUB +#define R_ARM_ALU_PC_G0 58 //ADD, SUB +#define R_ARM_ALU_PC_G1_NC 59 //ADD, SUB +#define R_ARM_ALU_PC_G1 60 //ADD, SUB +#define R_ARM_ALU_PC_G2 61 //ADD, SUB +#define R_ARM_LDR_PC_G1 62 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_PC_G2 63 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_PC_G0 64 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G1 65 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G2 66 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_PC_G0 67 //LDC, STC +#define R_ARM_LDC_PC_G1 68 //LDC, STC +#define R_ARM_LDC_PC_G2 69 //LDC, STC +#define R_ARM_ALU_SB_G0_NC 70 //ADD, SUB +#define R_ARM_ALU_SB_G0 71 //ADD, SUB +#define R_ARM_ALU_SB_G1_NC 72 //ADD, SUB +#define R_ARM_ALU_SB_G1 73 //ADD, SUB +#define R_ARM_ALU_SB_G2 74 //ADD, SUB +#define R_ARM_LDR_SB_G0 75 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G1 76 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G2 77 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_SB_G0 78 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G1 79 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G2 80 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_SB_G0 81 //LDC, STC +#define R_ARM_LDC_SB_G1 82 //LDC, STC +#define R_ARM_LDC_SB_G2 83 //LDC, STC +#define R_ARM_MOVW_BREL_NC 84 //MOVW +#define R_ARM_MOVT_BREL 85 //MOVT +#define R_ARM_MOVW_BREL 86 //MOVW + +#define R_ARM_GOT_BREL12 97 //LDR +#define R_ARM_GOTOFF12 98 //LDR, STR + +#define R_ARM_TLS_LDO12 109 //LDR, STR +#define R_ARM_TLS_LE12 110 //LDR, STR +#define R_ARM_TLS_TE12GP 111 //LDR + + + +/*--------------------------------------------------------- + Dynamic Section elf_v1.2 + --------------------------------------------------------*/ +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + + + + + + + + + +/*--------------------------------------------------------- + ELFヘッダを読み出す + --------------------------------------------------------*/ +void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr); + + + +#endif /* ELF_H_ */ + diff --git a/build/libraries/el/common/elf_loader.c b/build/libraries/el/common/elf_loader.c new file mode 100644 index 0000000..f254c52 --- /dev/null +++ b/build/libraries/el/common/elf_loader.c @@ -0,0 +1,776 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: elf_loader.c + + Copyright 2006,2007 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. + *---------------------------------------------------------------------------*/ + +#include "el_config.h" + +#if (TARGET_OS_NITRO == 1) +#include +#else +#include +#include +#include +#include +#endif + +#include "elf.h" +#include "elf_loader.h" +#include "arch.h" +#include "loader_subset.h" + +//#if (CTR_DEF_ENVIRONMENT_DSEMU == 1) +#if (TARGET_OS_NITRO == 1) +OSHeapHandle EL_Heap; +#endif +ElAdrEntry* ELAdrEntStart = NULL; +ElUnresolvedEntry* ELUnrEntStart = NULL; + + +/*------------------------------------------------------ + グローバル変数 + -----------------------------------------------------*/ +//#if (TARGET_OS_NITRO == 1) +//#else +ElReadImage i_elReadImage; +ElAlloc i_elAlloc; +ElFree i_elFree; +//#endif + + +/*------------------------------------------------------ + ローカル関数の宣言 + -----------------------------------------------------*/ +static u16 elLoadSegments( ElDesc* elElfDesc); +static u16 elLoadSections( ElDesc* elElfDesc); + +// ELFオブジェクトまたはそのアーカイブをバッファに再配置する +static u16 i_elLoadLibrary( ElDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf); +// ELFオブジェクトをバッファに再配置するコア関数 +static u16 i_elLoadObject( ElDesc* elElfDesc, void* obj_offset, void* buf); +// ELFオブジェクトからデータを読み出すスタブ関数 +static void i_elReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); +static void i_elReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); +static void i_elReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); + + +/*--------------------------------------------------------- + ELFオブジェクトのサイズを求める + + buf : ELFイメージのアドレス + --------------------------------------------------------*/ +u32 elGetElfSize( 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; +} + + +/*------------------------------------------------------ + ダイナミックリンクシステムを初期化する + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +void elInit( void) +{ + void* heap_start; + + /*--- メモリアロケーション関係の設定 ---*/ + 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); + /*--------------------------------------*/ +} +#else +void elInit( ElAlloc alloc, ElFree free) +{ + i_elAlloc = alloc; + i_elFree = free; +} +#endif + +/*------------------------------------------------------ + ElDesc構造体を初期化する + -----------------------------------------------------*/ +BOOL elInitDesc( ElDesc* elElfDesc) +{ + if( elElfDesc == NULL) { /*NULLチェック*/ + return FALSE; + } + + /*初期値の設定*/ + elElfDesc->ShdrEx = NULL; + elElfDesc->SymEx = NULL; + elElfDesc->SymExTbl = NULL; + elElfDesc->SymExTarget = 0xFFFFFFFF; + + elElfDesc->process = EL_INITIALIZED; /*フラグの設定*/ + + return TRUE; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + elElfDesc : ヘッダ構造体 + ObjFile : OBJファイルまたはアーカイブファイルの構造体 + buf : ロードするバッファ + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +u16 elLoadLibraryfromFile( ElDesc* elElfDesc, FSFile* ObjFile, void* buf) +#else +u16 elLoadLibraryfromFile( ElDesc* elElfDesc, int ObjFile, void* buf) +#endif +{ + u16 result; + u32 len; + + /*リード関数の設定*/ + elElfDesc->i_elReadStub = i_elReadFile; + elElfDesc->FileStruct = (int*)ObjFile; + +#if (TARGET_OS_NITRO == 1) + len = FS_GetLength( ObjFile); +#else + len = fsLseek( ObjFile, 0, SEEK_END); + fsLseek( ObjFile, 0, SEEK_SET); +#endif + + result = i_elLoadLibrary( elElfDesc, NULL, len, buf); + + return result; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + elElfDesc : ヘッダ構造体 + readfunc : OBJファイルまたはアーカイブファイルを読み出すユーザ関数 + buf : ロードするバッファ + -----------------------------------------------------*/ +//#if (TARGET_OS_NITRO == 1) +//#else +u16 elLoadLibrary( ElDesc* elElfDesc, ElReadImage readfunc, u32 len, void* buf) +{ + i_elReadImage = readfunc; + elElfDesc->i_elReadStub = i_elReadUsr; + + return( i_elLoadLibrary( elElfDesc, NULL, len, buf)); +} +//#endif + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + elElfDesc : ヘッダ構造体 + obj_image : OBJファイルまたはアーカイブファイルのRAM上イメージアドレス + buf : ロードするバッファ + -----------------------------------------------------*/ +u16 elLoadLibraryfromMem( ElDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf) +{ + u16 result; + + /*リード関数の設定*/ + elElfDesc->i_elReadStub = i_elReadMem; + elElfDesc->FileStruct = NULL; + + result = i_elLoadLibrary( elElfDesc, obj_image, obj_len, buf); + + return result; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + elElfDesc : ヘッダ構造体 + obj_image : OBJファイルまたはアーカイブファイルのRAM上イメージアドレス + buf : ロードするバッファ + -----------------------------------------------------*/ +static u16 i_elLoadLibrary( ElDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf) +{ + u16 result, all_result; + u32 image_pointer; + u32 arch_size; + u32 elf_num = 0; /*ELFオブジェクトの数*/ + ArchHdr ArHdr; + char OBJMAG[8]; + char ELFMAG[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3}; + + all_result = EL_RELOCATED; + elElfDesc->ar_head = obj_image; + image_pointer = 0; + + elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)obj_image, 0, 8); /*OBJの文字列を取得*/ + /*--------------- アーカイブファイルの場合 ---------------*/ + if( OSAPI_STRNCMP( OBJMAG, ARMAG, 8) == 0) { + arch_size = sizeof( ArchHdr); + image_pointer += 8; /*最初のエントリへ*/ + + elElfDesc->buf_current = buf; + while( image_pointer < obj_len) { + elElfDesc->i_elReadStub( OBJMAG, elElfDesc->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4); /*OBJの文字列を取得*/ + if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) { + elf_num++; + result = i_elLoadObject( elElfDesc, (void*)(image_pointer+arch_size), elElfDesc->buf_current); + if( result < all_result) { /*悪い結果のときだけall_resultに反映*/ + all_result = result; + } + /*初期値の設定*/ + elElfDesc->ShdrEx = NULL; + elElfDesc->SymEx = NULL; + elElfDesc->SymExTbl = NULL; + elElfDesc->SymExTarget = 0xFFFFFFFF; + elElfDesc->process = EL_INITIALIZED; /*フラグの設定*/ + }else{ + } + /*次のエントリへ*/ + elElfDesc->i_elReadStub( &ArHdr, elElfDesc->FileStruct, (u32)(obj_image), image_pointer, arch_size); + image_pointer += arch_size + AR_GetEntrySize( &ArHdr); + } + }else{/*--------------- ELFファイルの場合 ---------------*/ + if( OSAPI_STRNCMP( OBJMAG, ELFMAG, 4) == 0) { + elf_num++; + all_result = i_elLoadObject( elElfDesc, 0, buf); + } + } + /*-------------------------------------------------------*/ + + if( elf_num) { + return all_result; + }else{ + return EL_FAILED; + } +} + +/*------------------------------------------------------ + ELFオブジェクトをバッファに再配置する + + elElfDesc : ヘッダ構造体 + obj_offset : OBJファイルのRAM上イメージアドレスからのオフセット + buf : ロードするバッファ(TODO:バッファオーバーフロー対策) + -----------------------------------------------------*/ +static u16 i_elLoadObject( ElDesc* elElfDesc, void* obj_offset, void* buf) +{ + u16 ret_val; + + /* ElDescの初期化チェック */ + if( elElfDesc->process != EL_INITIALIZED) { + return EL_FAILED; + } + /* ELFヘッダの取得 */ + elElfDesc->i_elReadStub( &(elElfDesc->CurrentEhdr), elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr)); + + /* ElDesc構造体の構築 */ + elElfDesc->elf_offset = obj_offset; + elElfDesc->buf_current = buf; + elElfDesc->shentsize = elElfDesc->CurrentEhdr.e_shentsize; + elElfDesc->entry_adr = elElfDesc->CurrentEhdr.e_entry; + + /* ELFファイルタイプ別に処理 */ + switch( elElfDesc->CurrentEhdr.e_type) { + + case ET_NONE: + PRINTDEBUG( "ERROR : Elf type \"ET_NONE\"\n"); + ret_val = EL_FAILED; + break; + + case ET_REL: /* 実行×、再配置○ */ + PRINTDEBUG( "Elf type \"ET_REL\"\n"); + if( buf == NULL) { /* バッファのNULLチェック */ + return EL_FAILED; + } + ret_val = elLoadSections( elElfDesc); + break; + + case ET_EXEC: /* 実行○、再配置× */ + PRINTDEBUG( "Elf type \"ET_EXEC\"\n"); + ret_val = elLoadSegments( elElfDesc); + break; + + case ET_DYN: /* 実行○、再配置○ (TODO:未テスト)*/ + PRINTDEBUG( "Elf type \"ET_DYN\"\n"); + if( buf == NULL) { //ロードアドレスが指定されてないときはET_EXEC扱い + ret_val = elLoadSegments( elElfDesc); + }else{ //ロードアドレスが指定されていればET_REL扱い + ret_val = elLoadSections( elElfDesc); + } + break; + + case ET_CORE: + PRINTDEBUG( "ERROR : Elf type \"ET_CORE\"\n"); + ret_val = EL_FAILED; + break; + + default: + PRINTDEBUG( "ERROR : Invalid Elf type 0x%x\n", + elElfDesc->CurrentEhdr.e_type); + ret_val = EL_FAILED; + break; + } + + return( ret_val); +} + + +/*------------------------------------------------------ + 全セグメントを調べてコピーする + + elElfDesc : ヘッダ構造体 + -----------------------------------------------------*/ +static u16 elLoadSegments( ElDesc* elElfDesc) +{ + u16 i; + //u32 load_start; + Elf32_Phdr CurrentPhdr; + + for( i=0; i<(elElfDesc->CurrentEhdr.e_phnum); i++) { + /*プログラムヘッダをコピー*/ + i_elGetPhdr( elElfDesc, i, &CurrentPhdr); + + if( CurrentPhdr.p_type == PT_LOAD) { + /*ロード可能セグメントならメモリにロード*/ + i_elCopySegmentToBuffer( elElfDesc, &CurrentPhdr); + }else{ + PRINTDEBUG( "WARNING : skip segment (type = 0x%x)\n", + CurrentPhdr.p_type); + } + } + elElfDesc->process = EL_COPIED; + return( elElfDesc->process); +} + + +/*------------------------------------------------------ + 全セクションを調べてコピーする + + elElfDesc : ヘッダ構造体 + -----------------------------------------------------*/ +static u16 elLoadSections( ElDesc* elElfDesc) +{ + u16 i; + ElShdrEx* FwdShdrEx; + ElShdrEx* CurrentShdrEx; + ElShdrEx* InfoShdrEx; //例えばCurrentShdrExがrel.textの場合.textをさす + ElShdrEx DmyShdrEx; +#if (DEBUG_PRINT_ON == 1) + u16 j; + u32 num_of_entry; + char sym_str[128]; //デバッグプリント用 + u32 offset; //デバッグプリント用 +#endif + + /*---------- ElShdrExのリストを作る ----------*/ + CurrentShdrEx = &DmyShdrEx; + for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { + CurrentShdrEx->next = OSAPI_MALLOC( sizeof(ElShdrEx)); + CurrentShdrEx = (ElShdrEx*)(CurrentShdrEx->next); + OSAPI_CPUFILL8( CurrentShdrEx, 0, sizeof(ElShdrEx)); //ゼロクリア + + /*デバッグ情報かどうかを判別してフラグをセット*/ + if( i_elShdrIsDebug( elElfDesc, i) == TRUE) { /*デバッグ情報の場合*/ + CurrentShdrEx->debug_flag = 1; + }else{ /*デバッグ情報でない場合*/ + /*セクションヘッダをコピー*/ + i_elGetShdr( elElfDesc, i, &(CurrentShdrEx->Shdr)); + CurrentShdrEx->debug_flag = 0; + } + } + CurrentShdrEx->next = NULL; + elElfDesc->ShdrEx = DmyShdrEx.next; + /*--------------------------------------------*/ + + /*---------- 全セクションを調べてコピーする ----------*/ + PRINTDEBUG( "\nLoad to RAM:\n"); + for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { + /**/ + CurrentShdrEx = i_elGetShdrExfromList( 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) { /*デバッグ情報の場合*/ + PRINTDEBUG( "skip debug-section %02x\n", i); + }else{ /*デバッグ情報でない場合*/ + /* .text section */ + if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))&& + (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { + //メモリにコピー + CurrentShdrEx->loaded_adr = (u32) + i_elCopySectionToBuffer( elElfDesc, &(CurrentShdrEx->Shdr)); + } + /* .data, .data1 section (初期化済みデータ) */ + else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&& + (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { + //メモリにコピー + CurrentShdrEx->loaded_adr = (u32) + i_elCopySectionToBuffer( elElfDesc, &(CurrentShdrEx->Shdr)); + } + /* .bss section */ + else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&& + (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) { + //コピーしない + CurrentShdrEx->loaded_adr = (u32) + i_elAllocSectionToBuffer( elElfDesc, &(CurrentShdrEx->Shdr)); + } + /* .rodata, .rodata1 section */ + else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&& + (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { + //メモリにコピー + CurrentShdrEx->loaded_adr = (u32) + i_elCopySectionToBuffer( elElfDesc, &(CurrentShdrEx->Shdr)); + } + + PRINTDEBUG( "section %02x relocated at %08x\n", + i, CurrentShdrEx->loaded_adr); + } + } + /* コピー終了後 */ + elElfDesc->process = EL_COPIED; + /*----------------------------------------------------*/ + + /*---------- グローバルシンボルの公開とローカルシンボルの再配置 ----------*/ + PRINTDEBUG( "\nRelocate Symbols:\n"); + for( i=0; i<(elElfDesc->CurrentEhdr.e_shnum); i++) { + /**/ + CurrentShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, i); + + if( CurrentShdrEx->debug_flag == 1) { /*デバッグ情報の場合*/ + }else{ /*デバッグ情報でない場合*/ + + if( CurrentShdrEx->Shdr.sh_type == SHT_REL) { + /*リロケート*/ + InfoShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, + CurrentShdrEx->Shdr.sh_info); + if( InfoShdrEx->loaded_adr != 0) { //対象セクションがロードされていれば内部を再配置 + i_elRelocateSym( elElfDesc, i); + } +#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)); + i_elGetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr)); + i_elGetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym), + (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rel.r_info)), sizeof(Elf32_Sym)); + i_elGetStrAdr( 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"); + /*次のエントリへ*/ + offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); + } +#endif + } + else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) { + /*リロケート*/ + InfoShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, + CurrentShdrEx->Shdr.sh_info); + if( InfoShdrEx->loaded_adr != 0) { //対象セクションがロードされていれば内部を再配置 + i_elRelocateSym( elElfDesc, i); + } + +#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)); + i_elGetShdr( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->SymShdr)); + i_elGetSent( elElfDesc, CurrentShdrEx->Shdr.sh_link, &(elElfDesc->Sym), + (u32)(elElfDesc->SymShdr.sh_entsize * ELF32_R_SYM( elElfDesc->Rela.r_info)), sizeof(Elf32_Sym)); + i_elGetStrAdr( 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"); + /*次のエントリへ*/ + offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); + } +#endif + } + else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) { + /*グローバルシンボルをアドレステーブルに登録*/ + i_elGoPublicGlobalSym( elElfDesc, i); + } + } + } + /*i_elRelocateSymやi_elGoPublicGlobalSym内で作成&使い回したシンボルリストを開放*/ + i_elFreeSymList( elElfDesc); + + /*------- ElShdrExのリストを解放する -------*/ + CurrentShdrEx = elElfDesc->ShdrEx; + if( CurrentShdrEx) { + while( CurrentShdrEx->next != NULL) { + FwdShdrEx = CurrentShdrEx; + CurrentShdrEx = CurrentShdrEx->next; + OSAPI_FREE( FwdShdrEx); + } + elElfDesc->ShdrEx = NULL; + } + /*-----------------------------------------*/ + + /*RAM上のDLLが呼ばれる前にキャッシュをフラッシュ*/ +#if (TARGET_ARM_V5 == 1) + OSAPI_FLUSHCACHEALL(); + OSAPI_WAITCACHEBUF(); +#endif + + return (elElfDesc->process); +} + +/*------------------------------------------------------ + 未解決のシンボルがあればアドレステーブルを使って解決する + -----------------------------------------------------*/ +u16 elResolveAllLibrary( ElDesc* elElfDesc) +{ + ElAdrEntry* AdrEnt; + ElUnresolvedEntry* UnrEnt; + ElUnresolvedEntry* CurrentUnrEnt; + ElUnresolvedEntry* FwdUnrEnt; + BOOL ret_val; + + UnrEnt = ELUnrEntStart; + PRINTDEBUG( "\nResolve all symbols:\n"); + while( UnrEnt != NULL) { + AdrEnt = elGetAdrEntry( UnrEnt->sym_str); /*アドレステーブルから検索*/ + if( AdrEnt) { /*アドレステーブルから見つかった場合*/ + 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 = i_elDoRelocate( elElfDesc, UnrEnt); /*シンボル解決*/ + if( ret_val == FALSE) { + return EL_FAILED; //osPanicの方がいい? + }else{ + UnrEnt->remove_flag = 1; /*解決したというマーキング*/ + } + }else{ /*アドレステーブルから見つからなかった場合*/ + PRINTDEBUG( "\n ERROR! cannot find symbol : %s\n\n", UnrEnt->sym_str); + return EL_FAILED; //osPanicの方がいい? + } + UnrEnt = UnrEnt->next; /*次の未解決エントリへ*/ + } + + /*TODO:ここで解決できなかったUnrEntエントリだけ削除するべき*/ + + /*--- ElUnresolvedEntryのリストを解放する ---*/ + CurrentUnrEnt = ELUnrEntStart; +// if( CurrentUnrEnt) { + while( CurrentUnrEnt != NULL) { + FwdUnrEnt = CurrentUnrEnt; + CurrentUnrEnt = CurrentUnrEnt->next; + OSAPI_FREE( FwdUnrEnt->sym_str); //シンボル名文字列 + OSAPI_FREE( FwdUnrEnt); //構造体自身 + } + ELUnrEntStart = NULL; +// } + /*-------------------------------------------*/ + + /*ベニヤのリンクリストを開放*/ + i_elFreeVenTbl(); + + /*RAM上のDLLが呼ばれる前にキャッシュをフラッシュ*/ +#if (TARGET_ARM_V5 == 1) + OSAPI_FLUSHCACHEALL(); + OSAPI_WAITCACHEBUF(); +#endif + + return EL_RELOCATED; +} + + +/*------------------------------------------------------ + アドレステーブルからエントリを削除する + -----------------------------------------------------*/ +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; + } + } + + /*リンクリストの繋ぎ直し*/ + CurrentAdrEnt->next = AdrEnt->next; + ELAdrEntStart = DmyAdrEnt.next; + + /*開放*/ + OSAPI_FREE( AdrEnt); + + return TRUE; +} + +/*------------------------------------------------------ + アドレステーブルにエントリを追加する + -----------------------------------------------------*/ +void elAddAdrEntry( ElAdrEntry* AdrEnt) +{ + ElAdrEntry DmyAdrEnt; + ElAdrEntry* CurrentAdrEnt; + + if( !ELAdrEntStart) { + ELAdrEntStart = AdrEnt; + }else{ + DmyAdrEnt.next = ELAdrEntStart; + CurrentAdrEnt = &DmyAdrEnt; + + while( CurrentAdrEnt->next != NULL) { + CurrentAdrEnt = (ElAdrEntry*)CurrentAdrEnt->next; + } + CurrentAdrEnt->next = (void*)AdrEnt; + } + AdrEnt->next = NULL; +} + +/*------------------------------------------------------ + アドレステーブルにスタティック側のエントリを追加する + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +__declspec(weak) void elAddStaticSym( void) +#else +SDK_WEAK_SYMBOL void elAddStaticSym( void) +#endif +{ + PRINTDEBUG( "please link file which is generated by \"makelst\".\n"); + while( 1) {}; +} + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ElAdrEntry* elGetAdrEntry( const char* ent_name) +{ + ElAdrEntry* CurrentAdrEnt; + + CurrentAdrEnt = ELAdrEntStart; + if( CurrentAdrEnt == NULL) { + return NULL; + } + while( OSAPI_STRCMP( CurrentAdrEnt->name, ent_name) != 0) { + CurrentAdrEnt = (ElAdrEntry*)CurrentAdrEnt->next; + if( CurrentAdrEnt == NULL) { + break; + } + } + return CurrentAdrEnt; +} + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するアドレスを返す + -----------------------------------------------------*/ +void* elGetGlobalAdr( const char* ent_name) +{ + u32 adr; + ElAdrEntry* CurrentAdrEnt; + + CurrentAdrEnt = elGetAdrEntry( ent_name); + + if( CurrentAdrEnt) { + if( CurrentAdrEnt->thumb_flag) { + adr = (u32)(CurrentAdrEnt->adr) + 1; + }else{ + adr = (u32)(CurrentAdrEnt->adr); + } + }else{ + adr = 0; + } + + return (void*)(adr); +} + + +/*------------------------------------------------------ + アドレステーブルを解放する(アプリケーションが登録したエントリまで削除しようとするのでNG) + -----------------------------------------------------*/ +#if 0 +void* elFreeAdrTbl( void) +{ + ElAdrEntry* FwdAdrEnt; + ElAdrEntry* CurrentAdrEnt; + + /*--- ElAdrEntryのリストを解放する ---*/ + CurrentAdrEnt = ELAdrEntStart; + if( CurrentAdrEnt) { + while( CurrentAdrEnt->next != NULL) { + FwdAdrEnt = CurrentAdrEnt; + CurrentAdrEnt = CurrentAdrEnt->next; + OSAPI_FREE( FwdAdrEnt->name); //シンボル名文字列 + OSAPI_FREE( FwdAdrEnt); //構造体自身 + } + ELAdrEntStart = NULL; + } + /*------------------------------------*/ + + return NULL; +} +#endif + +/*------------------------------------------------------ + ELFオブジェクトからデータを読み出すスタブ + -----------------------------------------------------*/ +static void i_elReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) +{ +#if (TARGET_OS_NITRO == 1) + FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET); + FS_ReadFile( file_struct, buf, (s32)(size)); +#else + fsLseek( (int)file_struct, (s32)(file_offset), SEEK_SET); + fsRead( (int)file_struct, buf, (s32)(size)); +#endif +} + +static void i_elReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) +{ + OSAPI_CPUCOPY8( (void*)(file_base + file_offset), + buf, + size); +} + +//#if (TARGET_OS_NITRO == 1) +//#else +static void i_elReadUsr( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) +{ + i_elReadImage( file_offset, buf, size); +} +//#endif diff --git a/build/libraries/el/common/elf_loader.h b/build/libraries/el/common/elf_loader.h new file mode 100644 index 0000000..1a793b6 --- /dev/null +++ b/build/libraries/el/common/elf_loader.h @@ -0,0 +1,237 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: elf_loader.h + + Copyright 2006,2007 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 _ELF_LOADER_H_ +#define _ELF_LOADER_H_ + +#include "el_config.h" +#if (TARGET_OS_NITRO == 1) +#include +#else +#include +#include +#endif +#include "elf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*------------------------------------------------------ + セクションヘッダ拡張(ロードアドレス等に対応) + -----------------------------------------------------*/ +typedef struct { + void* next; + u16 index; + u16 debug_flag; /*0:デバッグ情報でない、1:デバッグ情報*/ + u32 loaded_adr; + u32 alloc_adr; + u32 loaded_size; + Elf32_Shdr Shdr; +}ElShdrEx; + + +/*------------------------------------------------------ + シンボルエントリ拡張(ロードアドレス等に対応) + -----------------------------------------------------*/ +typedef struct { + void* next; + u16 debug_flag; /*0:デバッグ情報でない、1:デバッグ情報*/ + u16 thumb_flag; + u32 relocation_val; + Elf32_Sym Sym; +}ElSymEx; + + +/*------------------------------------------------------ + ベニヤのリンクリスト(i_elDoRelocateで使用) + -----------------------------------------------------*/ +typedef struct { + void* next; + u32 adr; /* ベニヤコードの先頭アドレス */ + u32 data; /* ベニヤのリテラルプールに格納されている飛び先のアドレス値 */ +}ElVeneer; + + +/*------------------------------------------------------ + ELFオブジェクトの管理 + -----------------------------------------------------*/ +typedef void (*i_elReadFunc)( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); +typedef struct { + void* ar_head; /* ARまたはELFファイルの先頭アドレス */ + void* elf_offset; /* ELFオブジェクトの先頭へのオフセット */ + void* buf_current; /* Loader作業用 */ + u16 shentsize; /* 1セクションヘッダのサイズ */ + u16 process; /* 再配置状況 */ + + ElShdrEx* ShdrEx; /* ShdrExリストの先頭 */ + + Elf32_Ehdr CurrentEhdr; /* ELFヘッダ */ + + Elf32_Rel Rel; /* 再配置エントリ */ + Elf32_Rela Rela; + Elf32_Sym Sym; /* シンボルエントリ */ + Elf32_Shdr SymShdr; + + ElSymEx* SymEx; /* SymExリストの先頭(非デバッグシンボルのみ繋がる) */ + ElSymEx** SymExTbl; /* SymExアドレスのテーブル(全シンボル数ぶん)*/ + u32 SymExTarget; /* SymExリストを構築したシンボルセクションのセクション番号 */ + + ElVeneer* VeneerEx; /* ベニヤのリンクリスト */ + + i_elReadFunc i_elReadStub; /* リードスタブ関数 */ + void* FileStruct; /* ファイル構造体 */ + + u32 entry_adr; /* エントリアドレス */ +}ElDesc; + + + +/*------------------------------------------------------ + アドレステーブル + -----------------------------------------------------*/ +typedef struct { + void* next; /*次のアドレスエントリ*/ + char* name; /*文字列*/ + void* adr; /*アドレス*/ + u16 func_flag; /*0:データ、1:関数*/ + u16 thumb_flag; /*0:armコード、1:thumbコード*/ +}ElAdrEntry; + + +/*------------------------------------------------------ + 未解決の再配置情報テーブル + + 後からアドレステーブルを参照すれば次のように解決する。 + S_ = AdrEntry.adr; + T_ = (u32)(AdrEntry.thumb_flag); + -----------------------------------------------------*/ +typedef struct { + void* next; /*次のエントリ*/ + char* sym_str; /*未解決の外部参照シンボル名*/ + u32 r_type; /*リロケーションタイプ(ELF32_R_TYPE( Rela.r_info))*/ + u32 S_; /*未解決の外部参照シンボルアドレス*/ + s32 A_; /*解決済み*/ + u32 P_; /*解決済み*/ + u32 T_; /*未解決の外部参照シンボルのARM/Thumbフラグ*/ + u32 sh_type; /*SHT_REL or SHT_RELA*/ + u32 remove_flag; /*解決したときにセットする(消しても良いことを識別する)フラグ*/ +}ElUnresolvedEntry; + + + +/* ElDesc の process値 */ +#define EL_FAILED 0x00 +#define EL_INITIALIZED 0x5A +#define EL_COPIED 0xF0 +#define EL_RELOCATED 0xF1 + + + +/* typedef */ +//#if (TARGET_OS_NITRO == 1) +//#else +typedef void *(*ElAlloc)(size_t size); +typedef void (*ElFree)(void* ptr); +typedef u32 (*ElReadImage)( u32 offset, void* buf, u32 size); +//#endif + + +/*--------------------------------------------------------- + ELFオブジェクトのサイズを求める + --------------------------------------------------------*/ +u32 elGetElfSize( const void* buf); + +/*------------------------------------------------------ + ダイナミックリンクシステムを初期化する + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +void elInit( void); +#else +void elInit( ElAlloc alloc, ElFree free); +#endif + +/*------------------------------------------------------ + ElDesc構造体を初期化する + -----------------------------------------------------*/ +BOOL elInitDesc( ElDesc* elElfDesc); + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをファイルからバッファに再配置する + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +u16 elLoadLibraryfromFile( ElDesc* elElfDesc, FSFile* ObjFile, void* buf); +#else +u16 elLoadLibraryfromFile( ElDesc* elElfDesc, int ObjFile, void* buf); +#endif + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをユーザのリードAPIを通して再配置する + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +#else +u16 elLoadLibrary( ElDesc* elElfDesc, ElReadImage readfunc, u32 len, void* buf); +#endif + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをメモリからバッファに再配置する + -----------------------------------------------------*/ +u16 elLoadLibraryfromMem( ElDesc* elElfDesc, void* obj_image, u32 obj_len, void* buf); + +/*------------------------------------------------------ + アドレステーブルを使って未解決のシンボルを解決する + -----------------------------------------------------*/ +u16 elResolveAllLibrary( ElDesc* elElfDesc); + + +/*------------------------------------------------------ + アドレステーブルからエントリを削除する + -----------------------------------------------------*/ +BOOL elRemoveAdrEntry( ElAdrEntry* AdrEnt); + +/*------------------------------------------------------ + アドレステーブルにエントリを追加する + -----------------------------------------------------*/ +void elAddAdrEntry( ElAdrEntry* AdrEnt); + +/*------------------------------------------------------ + アドレステーブルにスタティック側のエントリを追加する + (ELライブラリ内でWEAKシンボルとして定義されており、 + makelstが生成したファイルの定義で上書きされる) + -----------------------------------------------------*/ +void elAddStaticSym( void); + + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ElAdrEntry* elGetAdrEntry( const char* ent_name); + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するアドレスを返す + -----------------------------------------------------*/ +void* elGetGlobalAdr( const char* ent_name); + + + +/*他に必要そうな関数*/ +//ロードに必要なメモリのバイト数を算出する関数 +//elFreeLibrary + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /*_ELF_LOADER_H_*/ diff --git a/build/libraries/el/common/loader_subset.c b/build/libraries/el/common/loader_subset.c new file mode 100644 index 0000000..ce22d6d --- /dev/null +++ b/build/libraries/el/common/loader_subset.c @@ -0,0 +1,1107 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: loader_subset.c + + Copyright 2006,2007 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. + *---------------------------------------------------------------------------*/ + +#include "el_config.h" +#if (TARGET_OS_NITRO == 1) + #include +#else + #include +#endif + +#include "loader_subset.h" + +extern ElUnresolvedEntry* ELUnrEntStart; + +static ElVeneer* ELVenEntStart = NULL; +static ElVeneer* ELV4tVenEntStart = NULL; + + +//ARM7かどうかを判別するときは、 +//#ifdef SDK_ARM7 +//#endif /*SDK_ARM7*/ + +/*------------------------------------------------------ + extern変数 + -----------------------------------------------------*/ +#if (TARGET_OS_NITRO == 1) +#else +extern ElAlloc i_elAlloc; +extern ElFree i_elFree; +#endif + + +/*------------------------------------------------------ + static関数 + -----------------------------------------------------*/ +static u32 el_veneer[3] = { //ARMコード + 0xE59FC000, //(LDR r12,[PC]) + 0xE12FFF1C, //(BX r12) + 0x00000000, //(data) +}; + +static u16 el_veneer_t[10] = { //v4t用Thumbコード + 0xB580, //(PUSH {R7,LR}) + 0x46FE, //(NOP) + 0x46FE, //(MOV LR, PC) + 0x2707, //(MOV R7, 7) + 0x44BE, //(ADD LR,R7) + 0x4F01, //(LDR R7,[PC+4]) + 0x4738, //(BX R7) ---> ARM routine + 0xBD80, //(POP {R7,PC} <---LR(v4tでは無条件でThumb分岐) + 0x0000, //(data) ARM routine address + 0x0000, //(data) +}; + +static void i_elBuildSymList( ElDesc* elElfDesc, u32 symsh_index); +static ElSymEx* i_elGetSymExfromList( ElSymEx* SymExStart, u32 index); +static ElSymEx* i_elGetSymExfromTbl( ElSymEx** SymExTbl, u32 index); +static void i_elUnresolvedInfoInit( ElUnresolvedEntry* UnresolvedInfo); +static void i_elAddUnresolvedEntry( ElUnresolvedEntry* UnrEnt); + +static void i_elAddVeneerEntry( ElVeneer** start, ElVeneer* VenEnt); +static BOOL i_elRemoveVenEntry( ElVeneer** start, ElVeneer* VenEnt); +static ElVeneer* i_elGetVenEntry( ElVeneer** start, u32 data); +static BOOL i_elIsFar( u32 P, u32 S, s32 threshold); + + +/*------------------------------------------------------ + アドレスをアラインメントする + -----------------------------------------------------*/ +#define ALIGN( addr, align_size ) (((addr) & ~((align_size) - 1)) + (align_size)) + +static u32 i_elALIGN( u32 addr, u32 align_size); +u32 i_elALIGN( u32 addr, u32 align_size) +{ + u32 aligned_addr; + + if( (addr % align_size) == 0) { + aligned_addr = addr; + }else{ + aligned_addr = (((addr) & ~((align_size) - 1)) + (align_size)); + } + + return aligned_addr; +} + + +/*------------------------------------------------------ + ベニヤをバッファにコピーする + start : 呼び出し元 + data : 飛び先 + threshold : この範囲内に既にベニヤがあれば使いまわす + -----------------------------------------------------*/ +void* i_elCopyVeneerToBuffer( ElDesc* elElfDesc, u32 start, u32 data, s32 threshold) +{ + u32* el_veneer_dest; + u32 load_start; + Elf32_Addr sh_size; + ElVeneer* elVenEnt; + + /*--- すでにベニヤがあればそれを使う ---*/ + elVenEnt = i_elGetVenEntry( &ELVenEntStart, data); + if( elVenEnt != NULL) { + if( i_elIsFar( start, elVenEnt->adr, threshold) == FALSE) { + PRINTDEBUG( "Veneer Hit!\n"); + return( (void*)elVenEnt->adr); + }else{ + /*ベニヤが遠すぎて使えないのでリンクリストから削除*/ + i_elRemoveVenEntry( &ELVenEntStart, elVenEnt); + } + } + /*--------------------------------------*/ + + /*アラインメントをとる*/ + load_start = i_elALIGN( ((u32)(elElfDesc->buf_current)), 4); + /*サイズ設定*/ + sh_size = 12;//el_veneer + + /*コピー*/ + OSAPI_CPUCOPY8( el_veneer, (u32*)load_start, sh_size); + + /*バッファポインタを移動*/ + elElfDesc->buf_current = (void*)(load_start + sh_size); + el_veneer_dest = (u32*)load_start; + el_veneer_dest[2] = data; + + /*--- ベニヤリストに追加 ---*/ + elVenEnt = OSAPI_MALLOC( sizeof( ElVeneer)); + elVenEnt->adr = load_start; + elVenEnt->data = data; + i_elAddVeneerEntry( &ELVenEntStart, elVenEnt); + /*--------------------------*/ + + /*ロードした先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + ベニヤをバッファにコピーする + start : 呼び出し元 + data : 飛び先 + threshold : この範囲内に既にベニヤがあれば使いまわす + -----------------------------------------------------*/ +void* i_elCopyV4tVeneerToBuffer( ElDesc* elElfDesc, u32 start, u32 data, s32 threshold) +{ + u32* el_veneer_dest; + u32 load_start; + Elf32_Addr sh_size; + ElVeneer* elVenEnt; + + /*--- すでにベニヤがあればそれを使う ---*/ + elVenEnt = i_elGetVenEntry( &ELV4tVenEntStart, data); + if( elVenEnt != NULL) { + if( i_elIsFar( start, elVenEnt->adr, threshold) == FALSE) { + PRINTDEBUG( "Veneer Hit!\n"); + return( (void*)elVenEnt->adr); + }else{ + /*ベニヤが遠すぎて使えないのでリンクリストから削除*/ + i_elRemoveVenEntry( &ELV4tVenEntStart, elVenEnt); + } + } + /*--------------------------------------*/ + + /*アラインメントをとる*/ + load_start = i_elALIGN( ((u32)(elElfDesc->buf_current)), 4); + /*サイズ設定*/ + sh_size = 20;//el_veneer_t + + /*コピー*/ + OSAPI_CPUCOPY8( el_veneer_t, (u32*)load_start, sh_size); + + /*バッファポインタを移動*/ + elElfDesc->buf_current = (void*)(load_start + sh_size); + el_veneer_dest = (u32*)load_start; + el_veneer_dest[4] = data; + + /*--- ベニヤリストに追加 ---*/ + elVenEnt = OSAPI_MALLOC( sizeof( ElVeneer)); + elVenEnt->adr = load_start; + elVenEnt->data = data; + i_elAddVeneerEntry( &ELV4tVenEntStart, elVenEnt); + /*--------------------------*/ + + /*ロードした先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + セグメントをバッファにコピーする + -----------------------------------------------------*/ +void* i_elCopySegmentToBuffer( ElDesc* elElfDesc, Elf32_Phdr* Phdr) +{ + u32 load_start; + + load_start = i_elALIGN( Phdr->p_vaddr, Phdr->p_align); + + elElfDesc->i_elReadStub( (void*)load_start, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset)+(u32)(Phdr->p_offset), + Phdr->p_filesz); + + return( (void*)load_start); +} + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +void* i_elCopySectionToBuffer( ElDesc* elElfDesc, Elf32_Shdr* Shdr) +{ + u32 load_start; + Elf32_Addr sh_size; + + /*アラインメントをとる*/ + load_start = i_elALIGN( ((u32)(elElfDesc->buf_current)), (Shdr->sh_addralign)); + /*サイズ設定*/ + sh_size = Shdr->sh_size; + + /*コピー*/ + elElfDesc->i_elReadStub( (void*)load_start, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset)+(u32)(Shdr->sh_offset), + sh_size); + + /*バッファポインタを移動*/ + elElfDesc->buf_current = (void*)(load_start + sh_size); + + /*ロードした先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + セクションをバッファに確保(コピーしない)し、 + その領域を0で埋める + -----------------------------------------------------*/ +void* i_elAllocSectionToBuffer( ElDesc* elElfDesc, Elf32_Shdr* Shdr) +{ + u32 load_start; + Elf32_Addr sh_size; + + /*アラインメントをとる*/ + load_start = i_elALIGN( ((u32)(elElfDesc->buf_current)), (Shdr->sh_addralign)); + /*サイズ設定*/ + sh_size = Shdr->sh_size; + + /*バッファポインタを移動*/ + elElfDesc->buf_current = (void*)(load_start + sh_size); + + /*0で埋める(.bssセクションを想定しているため)*/ + OSAPI_CPUFILL8( (void*)load_start, 0, sh_size); + + /*確保した先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + 指定インデックスのプログラムヘッダをバッファに取得する + -----------------------------------------------------*/ +void i_elGetPhdr( ElDesc* elElfDesc, u32 index, Elf32_Phdr* Phdr) +{ + u32 offset; + + offset = (elElfDesc->CurrentEhdr.e_phoff) + + ((u32)(elElfDesc->CurrentEhdr.e_phentsize) * index); + + elElfDesc->i_elReadStub( Phdr, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset) + offset, + sizeof( Elf32_Shdr)); +} + +/*------------------------------------------------------ + 指定インデックスのセクションヘッダをバッファに取得する + -----------------------------------------------------*/ +void i_elGetShdr( ElDesc* elElfDesc, u32 index, Elf32_Shdr* Shdr) +{ + u32 offset; + + offset = (elElfDesc->CurrentEhdr.e_shoff) + ((u32)(elElfDesc->shentsize) * index); + + elElfDesc->i_elReadStub( Shdr, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset) + offset, + sizeof( Elf32_Shdr)); +} + +/*------------------------------------------------------ + 指定インデックスのセクションのエントリをバッファに取得する + -----------------------------------------------------*/ +void i_elGetSent( ElDesc* elElfDesc, u32 index, void* entry_buf, u32 offset, u32 size) +{ + Elf32_Shdr Shdr; + + i_elGetShdr( elElfDesc, index, &Shdr); + + elElfDesc->i_elReadStub( entry_buf, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset) + (u32)(Shdr.sh_offset) + offset, + size); +} + + +/*------------------------------------------------------ + 指定セクションヘッダの指定インデックスのエントリをバッファに取得する + (Rel,Rela,Symなどエントリサイズが固定のセクションのみ) + Shdr : 指定セクションヘッダ + index : エントリ番号(0〜) + -----------------------------------------------------*/ +void i_elGetEntry( ElDesc* elElfDesc, Elf32_Shdr* Shdr, u32 index, void* entry_buf) +{ + u32 offset; + + offset = (u32)(Shdr->sh_offset) + ((Shdr->sh_entsize) * index); + + elElfDesc->i_elReadStub( entry_buf, + elElfDesc->FileStruct, + (u32)(elElfDesc->ar_head), + (u32)(elElfDesc->elf_offset) + offset, + Shdr->sh_entsize); +} + +/*------------------------------------------------------ + STRセクションヘッダの指定インデックスの文字列を取得する + + Shdr : 指定セクションヘッダ + index : エントリインデックス(0〜) + -----------------------------------------------------*/ +void i_elGetStrAdr( ElDesc* elElfDesc, u32 strsh_index, u32 ent_index, char* str, u32 len) +{ + /*文字列エントリの先頭アドレス*/ + i_elGetSent( elElfDesc, strsh_index, str, ent_index, len); +} + +/*------------------------------------------------------ + シンボルを再定義する + + + RelShdr->sh_link : シンボルセクション番号 + RelShdr->sh_info : ターゲットセクション番号(例:rel.textの.textを表す) + + + Rel->r_offset : ターゲットセクション内のオフセットアドレス + ELF32_R_SYM( Rel->r_info) : シンボルエントリ番号 + ELF32_R_TYPE( Rel->r_info) : リロケートタイプ + + + SymShdr->sh_link : シンボルの文字列テーブルセクション番号 + + + Sym->st_name : シンボルの文字列エントリ番号 + Sym->st_value : シンボルの所属するセクション内のオフセットアドレス + Sym->st_size : シンボルの所属するセクション内でのサイズ + Sym->st_shndx : シンボルの所属するセクションの番号 + ELF32_ST_BIND( Sym->st_info) : バインド(LOCAL or GLOBAL) + ELF32_ST_TYPE( Sym->st_info) : タイプ(シンボルが関連付けられている対象) + -----------------------------------------------------*/ +void i_elRelocateSym( ElDesc* elElfDesc, u32 relsh_index) +{ + u32 i; + u32 num_of_rel; //再定義すべきシンボルの数 + Elf32_Shdr RelOrRelaShdr; //RELまたはRELAセクションヘッダ + Elf32_Rela CurrentRela; //RELまたはRELAエントリのコピー先 + Elf32_Shdr* SymShdr; + ElSymEx* CurrentSymEx; + ElShdrEx* TargetShdrEx; + ElShdrEx* CurrentShdrEx; + u32 relocation_adr; + char sym_str[128]; + u32 copy_size; + ElAdrEntry* CurrentAdrEntry; + u32 sym_loaded_adr = 0; + u32 thumb_func_flag = 0; + ElUnresolvedEntry UnresolvedInfo; + ElUnresolvedEntry* UnrEnt; + u32 unresolved_num = 0; + + /*REL or RELAセクションヘッダ取得*/ + i_elGetShdr( elElfDesc, relsh_index, &RelOrRelaShdr); + + /*ターゲットセクションのEXヘッダ*/ + TargetShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, RelOrRelaShdr.sh_info); + + num_of_rel = (RelOrRelaShdr.sh_size) / (RelOrRelaShdr.sh_entsize); //再定義すべきシンボルの数 + + /*シンボルリストを作成する*/ + i_elBuildSymList( elElfDesc, RelOrRelaShdr.sh_link); + /*i_elBuildSymListを呼ぶとelElfDesc->SymShdrがセットされる*/ + SymShdr = &(elElfDesc->SymShdr); + PRINTDEBUG( "SymShdr->link:%02x, SymShdr->info:%02x\n", SymShdr->sh_link, SymShdr->sh_info); + + + /*--- 再定義が必要なシンボルの再定義 ---*/ + for( i=0; iSymExTbl[ELF32_R_SYM( CurrentRela.r_info)]); + +// if( CurrentSymEx->debug_flag == 1) { /*デバッグ情報の場合*/ + if( CurrentSymEx == NULL) { + }else{ /*デバッグ情報でない場合*/ + /**/ + i_elUnresolvedInfoInit( &UnresolvedInfo); + /*書き換えるアドレス(仕様書でいう「P」)*/ + relocation_adr = (TargetShdrEx->loaded_adr) + (CurrentRela.r_offset); + UnresolvedInfo.r_type = ELF32_R_TYPE( CurrentRela.r_info); + UnresolvedInfo.A_ = (CurrentRela.r_addend); + UnresolvedInfo.P_ = (relocation_adr); + UnresolvedInfo.sh_type = (RelOrRelaShdr.sh_type); + + /*シンボルのアドレスを突き止める*/ + if( CurrentSymEx->Sym.st_shndx == SHN_UNDEF) { + /*アドレステーブルから検索*/ + i_elGetStrAdr( elElfDesc, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128); + CurrentAdrEntry = elGetAdrEntry( sym_str); + if( CurrentAdrEntry) { + sym_loaded_adr = (u32)(CurrentAdrEntry->adr); + /*THUMB関数フラグ(仕様書でいう「T」)THUMB or ARM の判別*/ + thumb_func_flag = CurrentAdrEntry->thumb_flag; + PRINTDEBUG( "\n symbol found %s : %8x\n", sym_str, sym_loaded_adr); + }else{ + /*見つからなかった時はエラー(S_とT_が解決できない)*/ + copy_size = (u32)OSAPI_STRLEN( sym_str) + 1; + UnresolvedInfo.sym_str = OSAPI_MALLOC( copy_size); + OSAPI_CPUCOPY8( sym_str, UnresolvedInfo.sym_str, copy_size); + + /*グローバルな未解決テーブルに追加*/ + copy_size = sizeof( ElUnresolvedEntry); + UnrEnt = OSAPI_MALLOC( copy_size); + OSAPI_CPUCOPY8( &UnresolvedInfo, UnrEnt, copy_size); + i_elAddUnresolvedEntry( UnrEnt); + + unresolved_num++; /*未解決シンボル数をカウント*/ + PRINTDEBUG( "\n WARNING! cannot find symbol : %s\n", sym_str); + } + }else{ + /*シンボルの所属するセクションのExヘッダ取得*/ + CurrentShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, CurrentSymEx->Sym.st_shndx); + sym_loaded_adr = CurrentShdrEx->loaded_adr; + sym_loaded_adr += CurrentSymEx->Sym.st_value; //sym_loaded_adrは仕様書でいう「S」 + /*THUMB関数フラグ(仕様書でいう「T」)THUMB or ARM の判別*/ + thumb_func_flag = CurrentSymEx->thumb_flag; + } + + if( !UnresolvedInfo.sym_str) { /*sym_strがセットされているときはシンボル解決不可能*/ + /*仕様書と同じ変数名にする*/ + UnresolvedInfo.S_ = (sym_loaded_adr); + UnresolvedInfo.T_ = (thumb_func_flag); + + /*--------------- シンボルの解決(再配置の実行) ---------------*/ + /*CurrentSymEx->relocation_val =*/ i_elDoRelocate( elElfDesc, + &UnresolvedInfo); + /*------------------------------------------------------------*/ + } + } + } + /*-----------------------------------*/ + + + /*シンボルリストを開放する*/ +// i_elFreeSymList( elElfDesc); + + + /* 再配置完了後 */ + if( unresolved_num == 0) { + elElfDesc->process = EL_RELOCATED; + } +} + + +/*------------------------------------------------------ + グローバルシンボルをアドレステーブルに入れる + + + SymShdr->sh_link : シンボルの文字列テーブルセクション番号 + + + Sym->st_name : シンボルの文字列エントリ番号 + Sym->st_value : シンボルの所属するセクション内のオフセットアドレス + Sym->st_size : シンボルの所属するセクション内でのサイズ + Sym->st_shndx : シンボルの所属するセクションの番号 + ELF32_ST_BIND( Sym->st_info) : バインド(LOCAL or GLOBAL) + ELF32_ST_TYPE( Sym->st_info) : タイプ(シンボルが関連付けられている対象) + -----------------------------------------------------*/ +void i_elGoPublicGlobalSym( ElDesc* elElfDesc, u32 symtblsh_index) +{ + Elf32_Shdr SymShdr; + ElSymEx* CurrentSymEx; + ElShdrEx* CurrentShdrEx; + ElAdrEntry* ExportAdrEntry; + char sym_str[128]; + u32 copy_size; + + /*SYMTABセクションヘッダ取得*/ + i_elGetShdr( elElfDesc, symtblsh_index, &SymShdr); + + /*シンボルリストを作成する*/ + i_elBuildSymList( elElfDesc, symtblsh_index); + + /*--- ライブラリ内のGLOBALシンボルをアドレステーブルに公開する ---*/ + CurrentSymEx = elElfDesc->SymEx; //Tblからでなく、ここからたどればdebug情報は含まれない + while( CurrentSymEx != NULL) { +// CurrentSymEx = i_elGetSymExfromList( elElfDesc->SymExTbl, i); +// if( CurrentSymEx != NULL) { + /*GLOBALで、かつ関連するセクションがライブラリ内に存在する場合*/ + if( (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) && + (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) { + + ExportAdrEntry = OSAPI_MALLOC( sizeof(ElAdrEntry)); /*メモリ確保*/ + + ExportAdrEntry->next = NULL; + + i_elGetStrAdr( elElfDesc, SymShdr.sh_link, CurrentSymEx->Sym.st_name, sym_str, 128); + copy_size = (u32)OSAPI_STRLEN( sym_str) + 1; + ExportAdrEntry->name = OSAPI_MALLOC( copy_size); + OSAPI_CPUCOPY8( sym_str, ExportAdrEntry->name, copy_size); + + CurrentShdrEx = i_elGetShdrExfromList( elElfDesc->ShdrEx, CurrentSymEx->Sym.st_shndx); + //Sym.st_valueは偶数/奇数でARM/Thumbを判別できるように調整されている場合があるので、その調整を削除して正味の値を出す + ExportAdrEntry->adr = (void*)(CurrentShdrEx->loaded_adr + ((CurrentSymEx->Sym.st_value)&0xFFFFFFFE)); + ExportAdrEntry->func_flag = (u16)(ELF32_ST_TYPE( CurrentSymEx->Sym.st_info)); + ExportAdrEntry->thumb_flag = CurrentSymEx->thumb_flag; + + if( elGetAdrEntry( ExportAdrEntry->name) == NULL) { //入ってなかったら + elAddAdrEntry( ExportAdrEntry); /*登録*/ + } + } + CurrentSymEx = CurrentSymEx->next; +// } + } + /*----------------------------------------------------------------*/ + + /*シンボルリストを開放する*/ +// i_elFreeSymList( elElfDesc); +} + + +/*------------------------------------------------------ + シンボルリストを作成する + + -----------------------------------------------------*/ +static void i_elBuildSymList( ElDesc* elElfDesc, u32 symsh_index) +{ + u32 i; + u32 num_of_sym; //シンボルの全体数 + u16 debug_flag; + Elf32_Sym TestSym; + ElSymEx* CurrentSymEx; + ElShdrEx* CurrentShdrEx; + Elf32_Shdr* SymShdr; + ElSymEx DmySymEx; + + if( elElfDesc->SymExTarget == symsh_index) { + PRINTDEBUG( "%s skip.\n", __FUNCTION__); + return; //既にリスト作成済み + }else{ + i_elFreeSymList( elElfDesc); /*シンボルリストを開放する*/ + } + + PRINTDEBUG( "%s build\n", __FUNCTION__); + + /*SYMTABセクションヘッダ取得*/ + i_elGetShdr( elElfDesc, symsh_index, &(elElfDesc->SymShdr)); + SymShdr = &(elElfDesc->SymShdr); + + num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize); //シンボルの全体数 + elElfDesc->SymExTbl = OSAPI_MALLOC( num_of_sym * 4); + + /*---------- ElSymExのリストを作る ----------*/ + CurrentSymEx = &DmySymEx; + for( i=0; iShdrEx, TestSym.st_shndx); + if( CurrentShdrEx) { + debug_flag = CurrentShdrEx->debug_flag; + }else{ + debug_flag = 0; + }/*-------------------------------*/ + + if( debug_flag == 1) { + elElfDesc->SymExTbl[i] = NULL; + }else{ + CurrentSymEx->next = OSAPI_MALLOC( sizeof(ElSymEx)); + CurrentSymEx = (ElSymEx*)(CurrentSymEx->next); + + OSAPI_CPUCOPY8( &TestSym, &(CurrentSymEx->Sym), sizeof(TestSym)); + + elElfDesc->SymExTbl[i] = CurrentSymEx; + + PRINTDEBUG( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx); + } + } + + CurrentSymEx->next = NULL; + elElfDesc->SymEx = DmySymEx.next; + /*-------------------------------------------*/ + + + /*-------- ARM or Thumb 判定(i_elCodeIsThumbはSymExが出来てないと動かないため) --------*/ + CurrentSymEx = elElfDesc->SymEx; + while( CurrentSymEx != NULL) { //ここからたどればdebug情報は無い + /*-- ElSymExのThumbフラグをセット(関数シンボルだけ必要)--*/ + if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) { + CurrentSymEx->thumb_flag = (u16)(i_elCodeIsThumb( elElfDesc, + CurrentSymEx->Sym.st_shndx, + CurrentSymEx->Sym.st_value)); + }else{ + CurrentSymEx->thumb_flag = 0; + }/*--------------------------------------------------------*/ + + CurrentSymEx = CurrentSymEx->next; + } + /*-------------------------------------------------------------------------------------*/ + + + elElfDesc->SymExTarget = symsh_index; +} + + +/*------------------------------------------------------ + シンボルリストを開放する + + -----------------------------------------------------*/ +void i_elFreeSymList( ElDesc* elElfDesc) +{ + ElSymEx* CurrentSymEx; + ElSymEx* FwdSymEx; + + if( elElfDesc->SymExTbl != NULL) { + OSAPI_FREE( elElfDesc->SymExTbl); + elElfDesc->SymExTbl = NULL; + } + + /*------- ElSymExのリストを解放する -------*/ + CurrentSymEx = elElfDesc->SymEx; + if( CurrentSymEx) { + while( CurrentSymEx->next != NULL) { + FwdSymEx = CurrentSymEx; + CurrentSymEx = CurrentSymEx->next; + OSAPI_FREE( FwdSymEx); + } + elElfDesc->SymEx = NULL; + } + /*-----------------------------------------*/ + + + elElfDesc->SymExTarget = 0xFFFFFFFF; +} + + +/*------------------------------------------------------ + 未解決情報をもとにシンボルを解決する + + r_type,S_,A_,P_,T_が全て分かっている必要がある。 + -----------------------------------------------------*/ +#define _S_ (UnresolvedInfo->S_) +#define _A_ (UnresolvedInfo->A_) +#define _P_ (UnresolvedInfo->P_) +#define _T_ (UnresolvedInfo->T_) +BOOL i_elDoRelocate( ElDesc* elElfDesc, ElUnresolvedEntry* UnresolvedInfo) +{ + s32 signed_val; + u32 relocation_val = 0; + u32 relocation_adr; + BOOL ret_val; + BOOL veneer_flag = TRUE; + + ret_val = TRUE; + relocation_adr = _P_; + + switch( (UnresolvedInfo->r_type)) { + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_CALL: + case R_ARM_JUMP24: + if( UnresolvedInfo->sh_type == SHT_REL) { + _A_ = (s32)(((*(vu32*)relocation_adr)|0xFF800000) << 2); //一般的には-8になっているはず + } + /*----------------- veneer -----------------*/ + veneer_flag = i_elIsFar( _P_, _S_|_T_, 0x2000000); //+-32MBytes内か? +#if (TARGET_ARM_V5 == 1) + if( veneer_flag == TRUE) { +#else //(TARGET_ARM_V4 == 1) + //ARM->ThumbおよびARM->ARMでロングブランチのときは veneer 使用 + if( (_T_) || (veneer_flag == TRUE)) { +#endif + //_A_はPC相対分岐のときの調整値なので、絶対分岐の場合は関係ない + _S_ = (u32)i_elCopyVeneerToBuffer( elElfDesc, _P_, + (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)), + 0x2000000); + _T_ = 0; //veneerはARMコードのため + }/*-----------------------------------------*/ + signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_); + if( _T_) { /*BLX命令でARMからThumbに飛ぶ(v5未満だとBL→ベニアでBXという仕組みが必要)*/ + relocation_val = (0xFA000000) | ((signed_val>>2) & 0x00FFFFFF) | (((signed_val>>1) & 0x1)<<24); + }else{ /*BL命令でARMからARMに飛ぶ*/ + signed_val >>= 2; + relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF); + } + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_ABS32: + relocation_val = (( _S_ + _A_) | _T_); + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_REL32: + case R_ARM_PREL31: + relocation_val = (( _S_ + _A_) | _T_) - _P_; + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_LDR_PC_G0: + /*----------------- veneer -----------------*/ + veneer_flag = i_elIsFar( _P_, _S_|_T_, 0x2000000); //+-32MBytes内か? +#if (TARGET_ARM_V5 == 1) + if( veneer_flag == TRUE) { +#else //(TARGET_ARM_V4 == 1) + //ARM->ThumbおよびARM->ARMでロングブランチのときは veneer 使用 + if( (_T_) || (veneer_flag == TRUE)) { +#endif + //_A_はPC相対分岐のときの調整値なので、絶対分岐の場合は関係ない + _S_ = (u32)i_elCopyVeneerToBuffer( elElfDesc, _P_, + (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)), + 0x2000000); + _T_ = 0; //veneerはARMコードのため + }/*-----------------------------------------*/ + signed_val = ( (s32)(_S_) + _A_) - (s32)(_P_); + signed_val >>= 2; + relocation_val = (*(vu32*)relocation_adr & 0xFF000000) | (signed_val & 0x00FFFFFF); + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_ABS16: + case R_ARM_ABS12: + case R_ARM_THM_ABS5: + case R_ARM_ABS8: + relocation_val = _S_ + _A_; + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_THM_PC22:/*別名:R_ARM_THM_CALL*/ + if( UnresolvedInfo->sh_type == SHT_REL) { + _A_ = (s32)(((*(vu16*)relocation_adr & 0x07FF)<<11) + ((*((vu16*)(relocation_adr)+1)) & 0x07FF)); + _A_ = (s32)((_A_ | 0xFFC00000) << 1); //一般的には-4になっているはず(PCは現命令アドレス+4なので) + } + /*----------------- veneer -----------------*/ + veneer_flag = i_elIsFar( _P_, _S_|_T_, 0x400000); //+-4MBytes内か? +#if (TARGET_ARM_V5 == 1) + if( veneer_flag == TRUE) { + //_A_はPC相対分岐のときの調整値なので、絶対分岐の場合は関係ない + _S_ = (u32)i_elCopyVeneerToBuffer( elElfDesc, _P_, + (u32)(( (s32)(_S_) /*+ _A_*/) | (s32)(_T_)), + 0x400000); + _T_ = 0; //veneerはARMコードのため + }/*-----------------------------------------*/ +#else //(TARGET_ARM_V4 == 1) + /*----------------- v4t veneer -----------------*/ + //Thumb->ARMおよびThumb->Thumbでロングブランチのときは v4T veneer 使用 + if( (_T_ == 0) || (veneer_flag == TRUE)) { + _S_ = (u32)i_elCopyV4tVeneerToBuffer( elElfDesc, _P_, + (u32)(( (s32)(_S_)) | (s32)(_T_)), + 0x400000); + _T_ = 1; //v4t veneerはThumbコードのため + } + /*---------------------------------------------*/ +#endif + signed_val = (( (s32)(_S_) + _A_) | (s32)(_T_)) - (s32)(_P_); + signed_val >>= 1; + if( _T_) { /*BL命令でThumbからThumbに飛ぶ*/ + relocation_val = (*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF) + + ((((*((vu16*)(relocation_adr)+1)) & 0xF800) | (signed_val & 0x07FF)) << 16); + }else{ /*BLX命令でThumbからARMに飛ぶ(v5未満だとBL→ベニアでBXという仕組みが必要)*/ + if( (signed_val & 0x1)) { //_P_が4バイトアラインされていないとここに来る + signed_val += 1; + } + relocation_val = (*(vu16*)relocation_adr & 0xF800) | ((signed_val>>11) & 0x07FF) + + ((((*((vu16*)(relocation_adr)+1)) & 0xE800) | (signed_val & 0x07FF)) << 16); + } + *(vu16*)relocation_adr = (vu16)relocation_val; + *((vu16*)relocation_adr+1) = (vu16)((u32)(relocation_val) >> 16); + break; + case R_ARM_NONE: + /*R_ARM_NONEはターゲットのシンボルを保持し、リンカにデッドストリップ + されないようにします*/ + break; + case R_ARM_THM_JUMP24: + default: + ret_val = FALSE; + PRINTDEBUG( "ERROR! : unsupported relocation type (0x%x)!\n", (UnresolvedInfo->r_type)); + PRINTDEBUG( "S = 0x%x\n", _S_); + PRINTDEBUG( "A = 0x%x\n", _A_); + PRINTDEBUG( "P = 0x%x\n", _P_); + PRINTDEBUG( "T = 0x%x\n", _T_); + break; + } + + return ret_val;//relocation_val; +} +#undef _S_ +#undef _A_ +#undef _P_ +#undef _T_ + +/*------------------------------------------------------ + リストから指定インデックスのElSymExを取り出す + -----------------------------------------------------*/ +static ElSymEx* i_elGetSymExfromList( ElSymEx* SymExStart, u32 index) +{ + u32 i; + ElSymEx* SymEx; + + SymEx = SymExStart; + for( i=0; inext); + if( SymEx == NULL) { + break; + } + } + return SymEx; +} + +/*------------------------------------------------------ + テーブルから指定インデックスのElSymExを取り出す + -----------------------------------------------------*/ +static ElSymEx* i_elGetSymExfromTbl( ElSymEx** SymExTbl, u32 index) +{ + return( (ElSymEx*)(SymExTbl[index])); +} + +/*------------------------------------------------------ + リストから指定インデックスのElShdrExを取り出す + -----------------------------------------------------*/ +ElShdrEx* i_elGetShdrExfromList( ElShdrEx* ShdrExStart, u32 index) +{ + u32 i; + ElShdrEx* ShdrEx; + + ShdrEx = ShdrExStart; + for( i=0; inext); + if( ShdrEx == NULL) { + break; + } + } + return ShdrEx; +} + + + +/*------------------------------------------------------ + 指定インデックスのセクションがデバッグ情報かどうか判定する + +<デバッグ情報の定義> +・セクション名が".debug"から始まるセクション + +・.rel.debug〜 セクションなど、sh_info がデバッグ情報セクション番号を + 示しているセクション + -----------------------------------------------------*/ +BOOL i_elShdrIsDebug( ElDesc* elElfDesc, u32 index) +{ + Elf32_Shdr TmpShdr; + char shstr[6]; + + /*-- セクション名の文字列を6文字取得 --*/ + i_elGetShdr( elElfDesc, index, &TmpShdr); + i_elGetStrAdr( elElfDesc, elElfDesc->CurrentEhdr.e_shstrndx, + TmpShdr.sh_name, shstr, 6); + /*-------------------------------------*/ + + if( OSAPI_STRNCMP( shstr, ".debug", 6) == 0) { /*デバッグセクションの場合*/ + return TRUE; + }else{ /*デバッグセクションに関する再配置セクションの場合*/ + if( (TmpShdr.sh_type == SHT_REL) || (TmpShdr.sh_type == SHT_RELA)) { + if( i_elShdrIsDebug( elElfDesc, TmpShdr.sh_info) == TRUE) { + return TRUE; + } + } + } + + return FALSE; +} + + + +/*------------------------------------------------------ + elElfDescのSymExテーブルを調べ、指定インデックスの + 指定オフセットにあるコードがARMかTHUMBかを判定する。 + (予め elElfDesc->SymShdr と elElfDesc->SymEx を設定しておくこと) + + sh_index : 調べたいセクションインデックス + offset : 調べたいセクション内のオフセット + -----------------------------------------------------*/ +u32 i_elCodeIsThumb( ElDesc* elElfDesc, u16 sh_index, u32 offset) +{ + u32 i; + u32 thumb_flag; + Elf32_Shdr* SymShdr; + char str_adr[3]; + ElSymEx* CurrentSymEx; + + /*シンボルのセクションヘッダとSymExリスト取得*/ + SymShdr = &(elElfDesc->SymShdr); + CurrentSymEx = elElfDesc->SymEx; + + i = 0; + thumb_flag = 0; + while( CurrentSymEx != NULL) { + + if( CurrentSymEx->Sym.st_shndx == sh_index) { + i_elGetStrAdr( elElfDesc, SymShdr->sh_link, CurrentSymEx->Sym.st_name, str_adr, 3); + if( OSAPI_STRNCMP( str_adr, "$a\0", OSAPI_STRLEN("$a\0")) == 0) { + thumb_flag = 0; + }else if( OSAPI_STRNCMP( str_adr, "$t\0", OSAPI_STRLEN("$t\0")) == 0) { + thumb_flag = 1; + } + if( CurrentSymEx->Sym.st_value > offset) { + break; + } + } + + CurrentSymEx = CurrentSymEx->next; + i++; + } + + return thumb_flag; +} + + +/*--------------------------------------------------------- + 未解決情報エントリを初期化する + --------------------------------------------------------*/ +static void i_elUnresolvedInfoInit( ElUnresolvedEntry* UnresolvedInfo) +{ + UnresolvedInfo->sym_str = NULL; + UnresolvedInfo->r_type = 0; + UnresolvedInfo->S_ = 0; + UnresolvedInfo->A_ = 0; + UnresolvedInfo->P_ = 0; + UnresolvedInfo->T_ = 0; + UnresolvedInfo->remove_flag = 0; +} + +/*--------------------------------------------------------- + 未解決情報テーブルにエントリを追加する + --------------------------------------------------------*/ +static void i_elAddUnresolvedEntry( ElUnresolvedEntry* UnrEnt) +{ + ElUnresolvedEntry DmyUnrEnt; + ElUnresolvedEntry* CurrentUnrEnt; + + if( !ELUnrEntStart) { + ELUnrEntStart = UnrEnt; + }else{ + DmyUnrEnt.next = ELUnrEntStart; + CurrentUnrEnt = &DmyUnrEnt; + + while( CurrentUnrEnt->next != NULL) { + CurrentUnrEnt = CurrentUnrEnt->next; + } + CurrentUnrEnt->next = (void*)UnrEnt; + } + UnrEnt->next = NULL; +} + + +/*--------------------------------------------------------- + ベニヤテーブルにエントリを追加する + --------------------------------------------------------*/ +static void i_elAddVeneerEntry( ElVeneer** start, ElVeneer* VenEnt) +{ + ElVeneer DmyVenEnt; + ElVeneer* CurrentVenEnt; + + if( !(*start)) { + (*start) = VenEnt; + }else{ + DmyVenEnt.next = (*start); + CurrentVenEnt = &DmyVenEnt; + + while( CurrentVenEnt->next != NULL) { + CurrentVenEnt = CurrentVenEnt->next; + } + CurrentVenEnt->next = (void*)VenEnt; + } + VenEnt->next = NULL; +} + +/*------------------------------------------------------ + ベニヤテーブルからエントリを削除する + -----------------------------------------------------*/ +static BOOL i_elRemoveVenEntry( ElVeneer** start, ElVeneer* VenEnt) +{ + ElVeneer DmyVenEnt; + ElVeneer* CurrentVenEnt; + + DmyVenEnt.next = (*start); + CurrentVenEnt = &DmyVenEnt; + + while( CurrentVenEnt->next != VenEnt) { + if( CurrentVenEnt->next == NULL) { + return FALSE; + }else{ + CurrentVenEnt = (ElVeneer*)CurrentVenEnt->next; + } + } + + /*リンクリストの繋ぎ直し*/ + CurrentVenEnt->next = VenEnt->next; + (*start) = DmyVenEnt.next; + + /*開放*/ + OSAPI_FREE( VenEnt); + + return TRUE; +} + +/*------------------------------------------------------ + ベニヤテーブルから指定データに該当するエントリを探す + -----------------------------------------------------*/ +static ElVeneer* i_elGetVenEntry( ElVeneer** start, u32 data) +{ + ElVeneer* CurrentVenEnt; + + CurrentVenEnt = (*start); + if( CurrentVenEnt == NULL) { + return NULL; + } + while( CurrentVenEnt->data != data) { + CurrentVenEnt = (ElVeneer*)CurrentVenEnt->next; + if( CurrentVenEnt == NULL) { + break; + } + } + return CurrentVenEnt; +} + +/*------------------------------------------------------ + ベニヤテーブルを解放する + -----------------------------------------------------*/ +void* i_elFreeVenTbl( void) +{ + ElVeneer* FwdVenEnt; + ElVeneer* CurrentVenEnt; + + /*--- ElVenEntryのリストを解放する ---*/ + CurrentVenEnt = ELVenEntStart; + while( CurrentVenEnt != NULL) { + FwdVenEnt = CurrentVenEnt; + CurrentVenEnt = CurrentVenEnt->next; + OSAPI_FREE( FwdVenEnt); //構造体自身 + } + ELVenEntStart = NULL; + /*------------------------------------*/ + + /*--- ElVenEntryのリストを解放する ---*/ + CurrentVenEnt = ELV4tVenEntStart; + while( CurrentVenEnt != NULL) { + FwdVenEnt = CurrentVenEnt; + CurrentVenEnt = CurrentVenEnt->next; + OSAPI_FREE( FwdVenEnt); //構造体自身 + } + ELV4tVenEntStart = NULL; + /*------------------------------------*/ + + return NULL; +} + +/*------------------------------------------------------ + 2つのアドレス値の差が (+threshold)〜(-threshold)内に + 収まっているかを調べる + -----------------------------------------------------*/ +static BOOL i_elIsFar( u32 P, u32 S, s32 threshold) +{ + s32 diff; + + diff = (s32)S - (s32)(P); + if( (diff < threshold)&&( diff > -threshold)) { + return( FALSE); //Near + }else{ + return( TRUE); //Far + } +} + diff --git a/build/libraries/el/common/loader_subset.h b/build/libraries/el/common/loader_subset.h new file mode 100644 index 0000000..4a02dcd --- /dev/null +++ b/build/libraries/el/common/loader_subset.h @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: loader_subset.h + + Copyright 2006,2007 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 _LOADER_SUBSET_H_ +#define _LOADER_SUBSET_H_ + +#include "elf.h" +#include "elf_loader.h" + + +/*------------------------------------------------------ + ベニヤをバッファにコピーする + start : 呼び出し元アドレス + data : 飛び先アドレス + -----------------------------------------------------*/ +void* i_elCopyVeneerToBuffer( ElDesc* elElfDesc, u32 start, u32 data, s32 threshold); + + +/*------------------------------------------------------ + ベニヤをバッファにコピーする + start : 呼び出し元 + data : 飛び先 + threshold : この範囲内に既にベニヤがあれば使いまわす + -----------------------------------------------------*/ +void* i_elCopyV4tVeneerToBuffer( ElDesc* elElfDesc, u32 start, u32 data, s32 threshold); + + +/*------------------------------------------------------ + セグメントをバッファにコピーする + -----------------------------------------------------*/ +void* i_elCopySegmentToBuffer( ElDesc* elElfDesc, Elf32_Phdr* Phdr); + + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +void* i_elCopySectionToBuffer( ElDesc* elElfDesc, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + セクションをバッファに確保する(コピーしない) + -----------------------------------------------------*/ +void* i_elAllocSectionToBuffer( ElDesc* elElfDesc, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + 指定インデックスのプログラムヘッダをバッファに取得する + -----------------------------------------------------*/ +void i_elGetPhdr( ElDesc* elElfDesc, u32 index, Elf32_Phdr* Phdr); + + +/*------------------------------------------------------ + 指定インデックスのセクションヘッダをバッファに取得する + -----------------------------------------------------*/ +void i_elGetShdr( ElDesc* elElfDesc, u32 index, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + 指定インデックスのセクションのエントリをバッファに取得する + -----------------------------------------------------*/ +void i_elGetSent( ElDesc* elElfDesc, u32 index, void* entry_buf, u32 offset, u32 size); + + +/*------------------------------------------------------ + 指定セクションヘッダの指定インデックスのエントリをバッファに取得する + (エントリサイズが固定のセクションのみ) + -----------------------------------------------------*/ +void i_elGetEntry( ElDesc* elElfDesc, Elf32_Shdr* Shdr, u32 index, void* entry_buf); + + +/*------------------------------------------------------ + STRセクションヘッダの指定インデックスの文字列を取得する + -----------------------------------------------------*/ +void i_elGetStrAdr( ElDesc* elElfDesc, u32 strsh_index, u32 ent_index, char* str, u32 len); + + +/*------------------------------------------------------ + シンボルを再定義する + -----------------------------------------------------*/ +void i_elRelocateSym( ElDesc* elElfDesc, u32 relsh_index); + +/*------------------------------------------------------ + グローバルシンボルをアドレステーブルに入れる + -----------------------------------------------------*/ +void i_elGoPublicGlobalSym( ElDesc* elElfDesc, u32 symtblsh_index); + +/*------------------------------------------------------ + i_elRelocateSymやi_elGoPublicGlobalSymの中で作成したシンボルリストを + 開放する(どちらも呼び終わったら最後にこのAPIを呼んでください) + -----------------------------------------------------*/ +void i_elFreeSymList( ElDesc* elElfDesc); + +/*------------------------------------------------------ + 未解決情報をもとにシンボルを解決する + -----------------------------------------------------*/ +BOOL i_elDoRelocate( ElDesc* elElfDesc, ElUnresolvedEntry* UnresolvedInfo); + + +/*------------------------------------------------------ + リストから指定インデックスのElSymExを取り出す + -----------------------------------------------------*/ +//ElSymEx* i_elGetSymExfromList( ElSymEx* SymExStart, u32 index); + + +/*------------------------------------------------------ + リストから指定インデックスのElShdrExを取り出す + -----------------------------------------------------*/ +ElShdrEx* i_elGetShdrExfromList( ElShdrEx* ShdrExStart, u32 index); + + +/*------------------------------------------------------ + 指定インデックスのセクションがデバッグ情報かどうか判定する + -----------------------------------------------------*/ +BOOL i_elShdrIsDebug( ElDesc* elElfDesc, u32 index); + + +/*------------------------------------------------------ + elElfDescのSymExテーブルを調べ、指定インデックスの + 指定オフセットにあるコードがARMかTHUMBかを判定する + -----------------------------------------------------*/ +u32 i_elCodeIsThumb( ElDesc* elElfDesc, u16 sh_index, u32 offset); + + +/*--------------------------------------------------------- + 未解決情報エントリを初期化する + --------------------------------------------------------*/ +//void i_elUnresolvedInfoInit( ElUnresolvedEntry* UnresolvedInfo); + + +/*--------------------------------------------------------- + 未解決情報テーブルにエントリを追加する + --------------------------------------------------------*/ +//void i_elAddUnresolvedEntry( ElUnresolvedEntry* UnrEnt); + + +void* i_elFreeVenTbl( void); + + +#endif /*_LOADER_SUBSET_H_*/ diff --git a/build/tests/el/Makefile b/build/tests/el/Makefile new file mode 100644 index 0000000..be00512 --- /dev/null +++ b/build/tests/el/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - tests - camera +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = el-1 \ + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tests/el/el-1/ARM7/Makefile b/build/tests/el/el-1/ARM7/Makefile new file mode 100644 index 0000000..307675c --- /dev/null +++ b/build/tests/el/el-1/ARM7/Makefile @@ -0,0 +1,54 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - CAMERA - demos - camera-1 +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LCFILE_SPEC = main.lsf + +#---------------------------------------------------------------------------- + +#TWL_CODEGEN = THUMB +TWL_PROC = ARM7 + +TARGET_BIN = main.axf + +SRCS = sample1.c staticsymlist.c \ + +INCDIR += $(TWLSDK_ROOT)/include/twl \ + $(TWLSDK_ROOT)/include/twl/devices/sdmc/ARM7 \ + $(TWLSDK_ROOT)/include/twl/fatfs/ARM7 \ + +LLIBRARY_DIRS = $(TWLSDK_ROOT)/lib/ARM-BB/Release +LLIBRARIES = libfatfs_sp.twl.a \ + libsd_sp.twl.a \ + libel_sp.twl.a \ + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tests/el/el-1/ARM7/main.lsf b/build/tests/el/el-1/ARM7/main.lsf new file mode 100644 index 0000000..9eac241 --- /dev/null +++ b/build/tests/el/el-1/ARM7/main.lsf @@ -0,0 +1,40 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM7-BB.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- +# +# Nitro LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x02004000 + Library crt0.o + StackSize 1024 512 +} + +#Objects on MAIN RAM # nothing for elf2bin +#Autoload MAIN +#{ +# Address 0x027e0000 +# Library +#} + +Autoload MAIN +{ + Address 0x02020000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.wram) +} diff --git a/build/tests/el/el-1/ARM7/src/dlltest.h b/build/tests/el/el-1/ARM7/src/dlltest.h new file mode 100644 index 0000000..0fab3ec --- /dev/null +++ b/build/tests/el/el-1/ARM7/src/dlltest.h @@ -0,0 +1,8 @@ + +#ifndef __AR_DL_TEST_H__ +#define __AR_DL_TEST_H__ + +typedef void (*global_func_p)( void); //test_api1.c +typedef void (*g_func_p)( void); //test_api2.c + +#endif /*__AR_DL_TEST_H__*/ diff --git a/build/tests/el/el-1/ARM7/src/kernel_cfg.c b/build/tests/el/el-1/ARM7/src/kernel_cfg.c new file mode 100644 index 0000000..5114c17 --- /dev/null +++ b/build/tests/el/el-1/ARM7/src/kernel_cfg.c @@ -0,0 +1,434 @@ +#include "kernel_cfg.h" +#ifndef ATTRIBUTE_ALIGN +#define ATTRIBUTE_ALIGN(n) __attribute__ ((aligned(n))) +#endif + +#define MAIN_TASK 1 + +#define TNUM_TSKID 32 +#define TNUM_SEMID 32 +#define TNUM_FLGID 32 +#define TNUM_DTQID 32 +#define TNUM_MBXID 32 +#define TNUM_MPFID 32 +#define TNUM_CYCID 32 +#define TNUM_INHNO 32 +#define TNUM_EXCNO 0 +#define TNUM_MPLID 32 +#define TNUM_ALMID 32 +#define TNUM_ATTACHED_ISRNO 0 +#define TNUM_ISRID 0 +#define TNUM_MBFID 32 +#define TNUM_MTXID 32 +#define TNUM_PORID 0 +#define TNUM_SVCNO 0 +#if (CTR_DEF_SYSTEM_IOP == 1) +#define TSIZE_KERNEL_BUFFER (256*1024) /* 256KByte */ +#define TSIZE_MAIN_STACK (32*1024) /* 32KByte */ +#else +#define TSIZE_KERNEL_BUFFER (1024*1024) /* 1MByte */ +#define TSIZE_MAIN_STACK (128*1024) /* 128KByte */ +#endif +#define KERNEL_MAGIC_NUMBER 0x01234567 + + +#if TKERNEL_PRVER >= 0x1040 +#define CFG_INTHDR_ENTRY(inthdr) INTHDR_ENTRY(inthdr) +#define CFG_EXCHDR_ENTRY(exchdr) EXCHDR_ENTRY(exchdr) +#define CFG_INT_ENTRY(inthdr) INT_ENTRY(inthdr) +#define CFG_EXC_ENTRY(exchdr) EXC_ENTRY(exchdr) +#else +#error "This configuration file has no compatibility with TOPPERS/JSP rel 1.3 or earlier." +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define __ZERO(x,y) _declspec(naked) void y(void){} +#else +#define __ZERO(x,y) x y[1] +#endif + + /* User specified include files*/ +#include "sample1.h" +#include "hw_timer.h" +#include "timer.h" +#include "logtask.h" + + +/********* Object initializer [task] *********/ + +const ID _kernel_tmax_tskid = (TMIN_TSKID + TNUM_TSKID - 1); + +static VP __stack_MAIN_TASK[TSIZE_MAIN_STACK/sizeof(VP)] ATTRIBUTE_ALIGN(32); + +#define TNUM_TINIA (1) +const UINT _kernel_tnum_tinia = TNUM_TINIA; +const TINIA _kernel_tinia_table[TNUM_TINIA] = { + {MAIN_TASK, {0x00u | 0x02u, (VP_INT)(0), (FP)(main_task), INT_PRIORITY(5), sizeof(__stack_MAIN_TASK), __stack_MAIN_TASK, TA_NULL, (FP)(NULL)}}}; + +const ID _kernel_torder_table[TNUM_TINIA] = {1}; + +TCB _kernel_tcb_table[TNUM_TSKID] ATTRIBUTE_ALIGN(32); +TINIB _kernel_tinib_table[TNUM_TSKID]; + +#define TNUM_TSK_RID (0) /* 予約IDの設定 */ +const UINT _kernel_tnum_trid = TNUM_TSK_RID; +__ZERO(const ID, _kernel_trid_table); + + +/************** Object initializer [semaphore] ****************/ +//miya #define TNUM_SEMID 4 + +const ID _kernel_tmax_semid = (TMIN_SEMID + TNUM_SEMID - 1); + +#define TNUM_SEMINIA (0) +const UINT _kernel_tnum_seminia = TNUM_SEMINIA; +__ZERO(const SEMINIA, _kernel_seminia_table); + + +SEMCB _kernel_semcb_table[TNUM_SEMID] ATTRIBUTE_ALIGN(32); +SEMINIB _kernel_seminib_table[TNUM_SEMID]; + +#define TNUM_SEM_RID (0) +const UINT _kernel_tnum_semrid = TNUM_SEM_RID; +__ZERO(const ID, _kernel_semrid_table); + + +/********** Object initializer [eventflag] *********/ + +// miya #define TNUM_FLGID 0 + +const ID _kernel_tmax_flgid = (TMIN_FLGID + TNUM_FLGID - 1); + +#define TNUM_FLGINIA (0) +const UINT _kernel_tnum_flginia = TNUM_FLGINIA; +__ZERO(const FLGINIA,_kernel_flginia_table); + +FLGCB _kernel_flgcb_table[TNUM_FLGID] ATTRIBUTE_ALIGN(32); +FLGINIB _kernel_flginib_table[TNUM_FLGID]; + + +#define TNUM_FLG_RID (0) +const UINT _kernel_tnum_flgrid = TNUM_FLG_RID; +__ZERO(const ID, _kernel_flgrid_table); + + +/******** Object initializer [dataqueue] ********/ + +// miya #define TNUM_DTQID 0 + +const ID _kernel_tmax_dtqid = (TMIN_DTQID + TNUM_DTQID - 1); + +#define TNUM_DTQINIA (0) +const UINT _kernel_tnum_dtqinia = TNUM_DTQINIA; +__ZERO(const DTQINIA,_kernel_dtqinia_table); + +DTQCB _kernel_dtqcb_table[TNUM_DTQID] ATTRIBUTE_ALIGN(32); +DTQINIB _kernel_dtqinib_table[TNUM_DTQID]; + +#define TNUM_DTQ_RID (0) +const UINT _kernel_tnum_dtqrid = TNUM_DTQ_RID; +__ZERO(const ID, _kernel_dtqrid_table); + + +/******** Object initializer [mailbox] ********/ + +// miya #define TNUM_MBXID 0 + +const ID _kernel_tmax_mbxid = (TMIN_MBXID + TNUM_MBXID - 1); + +#define TNUM_MBXINIA (0) +const UINT _kernel_tnum_mbxinia = TNUM_MBXINIA; +__ZERO(const MBXINIA,_kernel_mbxinia_table); +MBXCB _kernel_mbxcb_table[TNUM_MBXID] ATTRIBUTE_ALIGN(32); +MBXINIB _kernel_mbxinib_table[TNUM_MBXID]; + +#define TNUM_MBX_RID (0) +const UINT _kernel_tnum_mbxrid = TNUM_MBX_RID; +__ZERO(const ID, _kernel_mbxrid_table); + + +/******** Object initializer [mempfix] *******/ + +// miya #define TNUM_MPFID 0 + +const ID _kernel_tmax_mpfid = (TMIN_MPFID + TNUM_MPFID - 1); + +#define TNUM_MPFINIA (0) +const UINT _kernel_tnum_mpfinia = TNUM_MPFINIA; +__ZERO(const MPFINIA,_kernel_mpfinia_table); + +MPFCB _kernel_mpfcb_table[TNUM_MPFID] ATTRIBUTE_ALIGN(32); +MPFINIB _kernel_mpfinib_table[TNUM_MPFID]; + +#define TNUM_MPF_RID (0) +const UINT _kernel_tnum_mpfrid = TNUM_MPF_RID; +__ZERO(const ID, _kernel_mpfrid_table); + + +/************* Object initializer [cyclic] ***********/ + +// miya #define TNUM_CYCID 1 + +const ID _kernel_tmax_cycid = (TMIN_CYCID + TNUM_CYCID - 1); + +#define TNUM_CYCINIA (0) +const UINT _kernel_tnum_cycinia = TNUM_CYCINIA; +__ZERO(const CYCINIA, _kernel_cycinia_table); + +CYCCB _kernel_cyccb_table[TNUM_CYCID] ATTRIBUTE_ALIGN(32); +CYCINIB _kernel_cycinib_table[TNUM_CYCID]; + +#define TNUM_CYC_RID (0) +const UINT _kernel_tnum_cycrid = TNUM_CYC_RID; +__ZERO(const ID, _kernel_cycrid_table); + + +/******* Object initializer [interrupt] *********/ + +// miya #define TNUM_INHNO 1 + +const UINT _kernel_tnum_inhno = TNUM_INHNO; + +#if (CTR_DEF_SYSTEM_IOP == 1) +CFG_INTHDR_ENTRY(timer_handler); + +const INHINIB _kernel_inhinib_table[TNUM_INHNO] = { + {OS_INTR_ID_TIMER1,0,(FP)CFG_INT_ENTRY(timer_handler)}}; +#else +__ZERO(const INHINIB, _kernel_inhinib_table); +#endif + +/******** Object initializer [exception] **********/ + + +/********** Object initializer [mempvar] ***********/ + +// miya #define TNUM_MPLID 0 + +const ID _kernel_tmax_mplid = (TMIN_MPLID + TNUM_MPLID - 1); + +#define TNUM_MPLINIA (0) +const UINT _kernel_tnum_mplinia = TNUM_MPLINIA; +__ZERO(const MPLINIA,_kernel_mplinia_table); +MPLCB _kernel_mplcb_table[TNUM_MPLID] ATTRIBUTE_ALIGN(32); +MPLINIB _kernel_mplinib_table[TNUM_MPLID]; + + +#define TNUM_MPL_RID (0) +const UINT _kernel_tnum_mplrid = TNUM_MPL_RID; +__ZERO(const ID, _kernel_mplrid_table); + + +/******* Object initializer [alarm] ********/ + +// miya #define TNUM_ALMID 0 + +const ID _kernel_tmax_almid = (TMIN_ALMID + TNUM_ALMID - 1); + +#define TNUM_ALMINIA (0) +const UINT _kernel_tnum_alminia = TNUM_ALMINIA; +__ZERO(const ALMINIA,_kernel_alminia_table); +__ZERO(ALMCB, _kernel_almcb_table) ATTRIBUTE_ALIGN(32); +__ZERO(ALMINIB, _kernel_alminib_table); + +#define TNUM_ALM_RID (0) +const UINT _kernel_tnum_almrid = TNUM_ALM_RID; +__ZERO(const ID, _kernel_almrid_table); + +/* Overrun handler */ + +void (null)(ID tskid, VP_INT exinf); +FP _kernel_overrun_handler_function = (FP)NULL; + + + +/******** Object initializer [attached_isr] ********/ + +// miya #define TNUM_ATTACHED_ISRNO 0 + +const UINT _kernel_tnum_attached_isrno = TNUM_ATTACHED_ISRNO; + +__ZERO(const ATTACHED_ISRINIB,_kernel_attached_isrinib_table); + + +/******* Object initializer [interrupt_service] ********/ + +// miya #define TNUM_ISRID 0 + +const ID _kernel_tmax_isrid = (TMIN_ISRID + TNUM_ISRID - 1); + +#define TNUM_ISRINIA (0) +const UINT _kernel_tnum_isrinia = TNUM_ISRINIA; +__ZERO(const ISRINIA,_kernel_isrinia_table); +__ZERO(ISRCB, _kernel_isrcb_table) ATTRIBUTE_ALIGN(32); +__ZERO(ISRINIB, _kernel_isrinib_table); + +#define TNUM_ISR_RID (0) +const UINT _kernel_tnum_isrrid = TNUM_ISR_RID; +__ZERO(const ID, _kernel_isrrid_table); + + +/******** Object initializer [messagebuffer] ********/ + +// miya #define TNUM_MBFID 0 + +const ID _kernel_tmax_mbfid = (TMIN_MBFID + TNUM_MBFID - 1); + +#define TNUM_MBFINIA (0) +const UINT _kernel_tnum_mbfinia = TNUM_MBFINIA; +__ZERO(const MBFINIA,_kernel_mbfinia_table); +MBFCB _kernel_mbfcb_table[TNUM_MBFID] ATTRIBUTE_ALIGN(32); +MBFINIB _kernel_mbfinib_table[TNUM_MBFID]; + +#define TNUM_MBF_RID (0) +const UINT _kernel_tnum_mbfrid = TNUM_MBF_RID; +__ZERO(const ID, _kernel_mbfrid_table); + + +/********* Object initializer [mutex] ************/ + +// miya #define TNUM_MTXID 0 + +const ID _kernel_tmax_mtxid = (TMIN_MTXID + TNUM_MTXID - 1); + +#define TNUM_MTXINIA (0) +const UINT _kernel_tnum_mtxinia = TNUM_MTXINIA; +__ZERO(const MTXINIA,_kernel_mtxinia_table); +MTXCB _kernel_mtxcb_table[TNUM_MTXID] ATTRIBUTE_ALIGN(32); +MTXINIB _kernel_mtxinib_table[TNUM_MTXID]; + +#define TNUM_MTX_RID (0) +const UINT _kernel_tnum_mtxrid = TNUM_MTX_RID; +__ZERO(const ID, _kernel_mtxrid_table); + + +/******** Object initializer [rendezvous] ********/ + +// miya #define TNUM_PORID 0 + +const ID _kernel_tmax_porid = (TMIN_PORID + TNUM_PORID - 1); + +#define TNUM_PORINIA (0) +const UINT _kernel_tnum_porinia = TNUM_PORINIA; +__ZERO(const PORINIA,_kernel_porinia_table); +__ZERO(PORCB, _kernel_porcb_table) ATTRIBUTE_ALIGN(32); +__ZERO(PORINIB, _kernel_porinib_table); + +#define TNUM_POR_RID (0) +const UINT _kernel_tnum_porrid = TNUM_POR_RID; +__ZERO(const ID, _kernel_porrid_table); + + +/***** Object initializer [exservicecall] *****/ + +// miya #define TNUM_SVCNO 0 + +const UINT _kernel_tnum_svcno = TNUM_SVCNO; + +__ZERO(const SVCINIB,_kernel_svcinib_table); +__ZERO(SVCCB, _kernel_svccb_table) ATTRIBUTE_ALIGN(32); + +#define TNUM_SVC_RID (0) +const UINT _kernel_tnum_svcrid = TNUM_SVC_RID; +__ZERO(const ID, _kernel_svcrid_table); + +/******* Kernel buffer ********/ + +// miya #define TSIZE_KERNEL_BUFFER (1024*1024) + +VP __kernel_bufmgr_buffer[TSIZE_KERNEL_BUFFER/sizeof(VP)] ATTRIBUTE_ALIGN(32); +const SIZE __kernel_bufmgr_buffer_size = TSIZE_KERNEL_BUFFER; + +TMEVTN _kernel_tmevt_heap[TNUM_TSKID + TNUM_CYCID + TNUM_ALMID]; + + +/******** Variables for kernel checker ********/ +#if (CTR_DEF_SYSTEM_IOP == 1) +static const UW _checker_magic_number = KERNEL_MAGIC_NUMBER; +#endif +/************************************************************/ + +// miya #define TNUM_EXCNO 0 + +const UINT _kernel_tnum_excno = TNUM_EXCNO; + +__ZERO(const EXCINIB,_kernel_excinib_table); + /* Initialization handler */ + +void +_kernel_call_inirtn(void) +{ + timer_initialize( (VP_INT)(0) ); + // serial_initialize( (VP_INT)(0) ); +} + +void +_kernel_call_terrtn(void) +{ + timer_terminate( (VP_INT)(0) ); +} + + /* Object initialization routine */ + +void +_kernel_object_initialize(void) +{ + _kernel_bufmgr_initialize(); + + if( _kernel_tmax_tskid ) { + _kernel_task_initialize(); + } + if( _kernel_tmax_semid ) { + _kernel_semaphore_initialize(); + } + if( _kernel_tmax_flgid ) { + _kernel_eventflag_initialize(); + } + if( _kernel_tmax_dtqid ) { + _kernel_dataqueue_initialize(); + } + + if( _kernel_tmax_mtxid ) { + _kernel_mutex_initialize(); + } + if( _kernel_tmax_mbxid ) { + _kernel_mailbox_initialize(); + } + if( _kernel_tmax_mpfid ) { + _kernel_mempfix_initialize(); + } + + if( _kernel_tmax_mplid ) { + _kernel_mempvar_initialize(); + } + + if( _kernel_tmax_cycid ) { + _kernel_cyclic_initialize(); + } + if( _kernel_tmax_mbfid ) { + _kernel_messagebuffer_initialize(); + } + if( _kernel_tmax_almid ) { + _kernel_alarm_initialize(); + } + if( _kernel_tmax_porid ) { + _kernel_rendezvous_initialize(); + } +#if 0 + + if( _kernel_tmax_isrid ) + //_kernel_svchash_initialize(); + + task_overrun.c:overrun_initialize(); + exception.c:exception_initialize(); + interrupt.c:attached_isr_initialize(); + interrupt.c:interrupt_service_initialize(); + servicecall.c:_kernel_svchash_initialize(); + servicecall.c:exservicecall_initialize(); +#endif + +#if (CTR_DEF_SYSTEM_IOP == 1) + _kernel_interrupt_initialize(); +#endif +} + diff --git a/build/tests/el/el-1/ARM7/src/sample1.c b/build/tests/el/el-1/ARM7/src/sample1.c new file mode 100644 index 0000000..87667fd --- /dev/null +++ b/build/tests/el/el-1/ARM7/src/sample1.c @@ -0,0 +1,208 @@ +#include + +#include +#include +#include + +#include "sample1.h" +#include "dlltest.h" + + #define PRINTDEBUG( ...) ((void)0) + + +#define _DLL_LINK_DYNAMIC_ (1) + + +/*---------------------------------------------------------------------------* + static変数 + *---------------------------------------------------------------------------*/ +static u32 lib_buf[8192]; +int fd; +u32 alloc_total_size = 0; +u32 alloc_max_size = 0; + +#if (_DLL_LINK_DYNAMIC_ == 1) +global_func_p global_func; +g_func_p g_func; +#endif + +/*---------------------------------------------------------------------------* + static関数 + *---------------------------------------------------------------------------*/ +static void display_entries( void); +u32 readlib( u32 offset, void* buf, u32 size); + +int no_data; + +// +//ストリームAPI用関数 (FILE構造体を使いたいなら必要) +//実際にはmalloc/freeなどが使えるようにするためのものなので、 +//間違って使ったらサイズが足りなくなるかも +// +/* +#define MY_HEAP_SIZE (8192*6)//65536 +static u8 myHeap[MY_HEAP_SIZE/sizeof(u8)] ATTRIBUTE_ALIGN(32); +static ID myMplID; + +static void myInitHeap(void) +{ + T_CMPL cmpl = { TA_TFIFO, MY_HEAP_SIZE, NULL }; + myMplID = acre_mpl(&cmpl); +} +static void *myAlloc(size_t size) +{ + void *ptr; + ER ercd = pget_mpl(myMplID, size, &ptr); + if (ercd == E_OK) { +T_RMPL rmpl; +ref_mpl(myMplID, &rmpl); + alloc_total_size += size; + if( alloc_total_size > alloc_max_size) { + alloc_max_size = alloc_total_size; + } + return ptr; + } + return NULL; +} +static void myFree(void *ptr) +{ + rel_mpl(myMplID, ptr); +} +*/ + +static void *myAlloc(size_t size) +{ + return( OS_Alloc( size)); +} +static void myFree(void *ptr) +{ + OS_Free( ptr); +} + + +int main(void) +{ + extern void _uitron_start(void); + _uitron_start(); + return 0; +} + +/* + * メインタスク + */ +void TwlSpMain( void) +{ + ElDesc dll_desc; + u32 i; + u32 free_bytes, free_blocks, total_blocks; + u8 rslt; + u32 len; + int result; + + // vmsk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)) ; + PRINTDEBUG( "Sample program starts (exinf = %d).\n", (INT) exinf); + PRINTDEBUG( "printf test 0.03 = %f\n", 0.03); + + + /**/ + PRINTDEBUG("Sample program starts.\n"); + { + OSHeapHandle hh; + OS_SetSubPrivArenaLo( OS_InitAlloc( OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), OS_GetSubPrivArenaHi(), 1)); + hh = OS_CreateHeap( OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), OS_GetSubPrivArenaHi()); + OS_SetCurrentHeap( OS_ARENA_MAIN_SUBPRIV, hh); + if( rtfs_init() == FALSE) { + PRINTDEBUG( "rtfs_init failed.\n"); + }else{ + PRINTDEBUG( "rtfs_init success.\n"); + } + } + OS_Alloc( 32); + + + /*SDドライバ初期化*/ + result = sdmcInit( SDMC_NOUSE_DMA, NULL, NULL); + if( result != SDMC_NORMAL) { + PRINTDEBUG( "sdmcInit : failed\n"); + while( 1) {}; + }else{ + PRINTDEBUG( "sdmcInit : success\n"); + } + + + /*デバイスドライバの登録*/ + if( sdmcRtfsAttach( 4) == FALSE) { //sdmcをEドライブにする + PRINTDEBUG( "sdmcRtfsAttach failed.\n"); + }else{ + PRINTDEBUG( "sdmcRtfsAttach success.\n"); + } + + if( !rtfs_pc_set_default_drive( (unsigned char*)"E:")) { + PRINTDEBUG( "pc_set_default_drive (E) failed\n"); + while( 1){}; + } + + + /*----------*/ + fd = po_open( (byte*)"\\libdlltest.a", (PO_CREAT|PO_BINARY|PO_WRONLY), PS_IREAD); + if( fd < 0) { + PRINTDEBUG( "po_open failed.\n"); + while( 1) {}; + } + PRINTDEBUG( "po_open success.\n"); + /*----------*/ + + elInit( myAlloc, myFree);//OS_Alloc, OS_Free); + PRINTDEBUG( "%s, %d\n", __FUNCTION__, __LINE__); + + elInitDesc( &dll_desc); + PRINTDEBUG( "%s, %d\n", __FUNCTION__, __LINE__); + +// elLoadLibraryfromFile( &dll_desc, fd, lib_buf); + len = po_lseek( fd, 0, PSEEK_END); + po_lseek( fd, 0, PSEEK_SET); + elLoadLibrary( &dll_desc, (ElReadImage)readlib, len, lib_buf); + PRINTDEBUG( "%s, %d\n", __FUNCTION__, __LINE__); + PRINTDEBUG( "alloc size : 0x%x\n", alloc_max_size); + + elAddStaticSym(); + PRINTDEBUG( "%s, %d\n", __FUNCTION__, __LINE__); + + elResolveAllLibrary( &dll_desc); + PRINTDEBUG( "%s, %d\n", __FUNCTION__, __LINE__); + +#if (_DLL_LINK_DYNAMIC_ == 1) + PRINTDEBUG( "LINK : dynamic\n"); + global_func = (global_func_p)elGetGlobalAdr( "global_func\0"); + PRINTDEBUG( "0x%x\n", global_func); + g_func = (g_func_p)elGetGlobalAdr( "g_func\0"); + PRINTDEBUG( "0x%x\n", g_func); +#endif + + PRINTDEBUG( "----- dll-func1 execution -----\n"); +#if (_DLL_LINK_DYNAMIC_ == 1) + (*global_func)(); +#else + global_func(); +#endif + + PRINTDEBUG( "----- dll-func2 execution -----\n"); +#if (_DLL_LINK_DYNAMIC_ == 1) + (*g_func)(); +#else + g_func(); +#endif + + PRINTDEBUG( "----- dll execution end -----\n"); + + + PRINTDEBUG( "Sample program ends.\n"); +// kernel_exit(); + while( 1 ) {}; +} + +u32 readlib( u32 offset, void* buf, u32 size) +{ + po_lseek( fd, offset, PSEEK_SET); + return( po_read( fd, buf, size)); +} diff --git a/build/tests/el/el-1/ARM7/src/sample1.h b/build/tests/el/el-1/ARM7/src/sample1.h new file mode 100644 index 0000000..6dc1468 --- /dev/null +++ b/build/tests/el/el-1/ARM7/src/sample1.h @@ -0,0 +1,27 @@ + +/* + * ウニ・ソ・ケ・ッ、ホヘ・タ霰ル、ホトオチ + */ + +#define MAIN_PRIORITY 5 /* ・皈、・・ソ・ケ・ッ、ホヘ・タ霰ル */ + /* HIGH_PRIORITY 、隍ケ筅ッ、ケ、、ウ、ネ */ +#define HIGH_PRIORITY 9 /* ハツホ、ヒシツケヤ、オ、、・ソ・ケ・ッ、ホヘ・タ霰ル */ +#define MID_PRIORITY 10 +#define LOW_PRIORITY 11 + +/* + * ・ソ。シ・イ・テ・ネーヘツク、ホトオチ。ハCPUホ羌ー・マ・・ノ・鬢ホオッニーハヒ。、ハ、ノ。ヒ + */ + +#ifndef STACK_SIZE +#define STACK_SIZE (8192) /* ・ソ・ケ・ッ、ホ・ケ・ソ・テ・ッ・オ・、・コ */ +#endif /* STACK_SIZE */ + +/* + * エリソ、ホ・ラ・・ネ・ソ・、・ラタクタ + */ +#ifndef _MACRO_ONLY + +//extern void main_task(VP_INT exinf); + +#endif /* _MACRO_ONLY */ diff --git a/build/tests/el/el-1/ARM7/src/staticsymlist.c b/build/tests/el/el-1/ARM7/src/staticsymlist.c new file mode 100644 index 0000000..1e288df --- /dev/null +++ b/build/tests/el/el-1/ARM7/src/staticsymlist.c @@ -0,0 +1,44 @@ +/*This file generated automatically by the "makelst".*/ + +#ifndef __STATIC_SYM_LIST__ +#define __STATIC_SYM_LIST__ + +#include +#include + +/*-------------------------------- + extern symbol + --------------------------------*/ +extern int no_data; +extern void __aeabi_unwind_cpp_pr0( void); +//extern void Lib$$Request$$armlib( void); + +/*-------------------------------- + symbol structure + --------------------------------*/ +ElAdrEntry AdrEnt_no_data = { + (void*)NULL, + (char*)"no_data\0", + (void*)&no_data, + 0, + 0, +}; +/* +ElAdrEntry AdrEnt_Lib$$Request$$armlib = { + (void*)NULL, + (char*)"Lib$$Request$$armlib\0", + (void*)Lib$$Request$$armlib, + 1, + 0, +};*/ + +/*-------------------------------- + API + --------------------------------*/ +void elAddStaticSym( void) +{ + elAddAdrEntry( &AdrEnt_no_data); +// elAddAdrEntry( &AdrEnt_Lib$$Request$$armlib); +} + +#endif /*__STATIC_SYM_LIST__*/ diff --git a/build/tests/el/el-1/ARM9/Makefile b/build/tests/el/el-1/ARM9/Makefile new file mode 100644 index 0000000..c5404f3 --- /dev/null +++ b/build/tests/el/el-1/ARM9/Makefile @@ -0,0 +1,41 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - CAMERA - demos - camera-1 +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: Makefile,v $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +#TWL_CODEGEN = THUMB + +TARGET_BIN = main.axf + +SRCS = main.c + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/tests/el/el-1/ARM9/src/main.c b/build/tests/el/el-1/ARM9/src/main.c new file mode 100644 index 0000000..7a100f1 --- /dev/null +++ b/build/tests/el/el-1/ARM9/src/main.c @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - SND - demos - capture + File: main.c + + Copyright 2007 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. + + $Log: main.c,v $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#include + +static void VBlankIntr(void); + +/*---------------------------------------------------------------------------* + Name: TwlMain + + Description: main + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void TwlMain() +{ + // 初期化 + OS_Init(); + GX_Init(); + OS_InitTick(); + + // Vブランク割り込み設定 + OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)OS_EnableIrq(); + (void)GX_VBlankIntr(TRUE); + { + u16 bg_color = GX_RGB(31, 0, 0); + GX_LoadBGPltt(&bg_color, 0, sizeof(u16)); + } + + while (1) + { + OS_WaitVBlankIntr(); + } +} + +//-------------------------------------------------------------------------------- +// Vブランク割り込み処理 +// +void VBlankIntr(void) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); // checking VBlank interrupt +} diff --git a/build/tests/el/el-1/Makefile b/build/tests/el/el-1/Makefile new file mode 100644 index 0000000..078ec37 --- /dev/null +++ b/build/tests/el/el-1/Makefile @@ -0,0 +1,32 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - build +# File: Makefile +# +# Copyright 2007 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. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + ARM7 \ + ARM9 \ + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile =====