From 0c34a21d355af15e8314f8cbb98669ad77a48b74 Mon Sep 17 00:00:00 2001 From: shirait Date: Mon, 2 Jul 2007 09:42:44 +0000 Subject: [PATCH] add makelst(tentative) git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@155 4ee2a332-4b2b-5046-8439-1ba90f034370 --- tools/makelst/Makefile | 48 ++ tools/makelst/arch.c | 39 ++ tools/makelst/arch.h | 38 ++ tools/makelst/elf.c | 341 ++++++++++++++ tools/makelst/elf.h | 412 +++++++++++++++++ tools/makelst/elf_loader.c | 775 ++++++++++++++++++++++++++++++++ tools/makelst/elf_loader.h | 192 ++++++++ tools/makelst/loader_subset.c | 819 ++++++++++++++++++++++++++++++++++ tools/makelst/loader_subset.h | 128 ++++++ tools/makelst/makelst.c | 279 ++++++++++++ tools/makelst/readme.txt | 7 + tools/makelst/searcharg.c | 190 ++++++++ tools/makelst/searcharg.h | 55 +++ tools/makelst/types.h | 228 ++++++++++ tools/makelst/version.h | 1 + 15 files changed, 3552 insertions(+) create mode 100644 tools/makelst/Makefile create mode 100644 tools/makelst/arch.c create mode 100644 tools/makelst/arch.h create mode 100644 tools/makelst/elf.c create mode 100644 tools/makelst/elf.h create mode 100644 tools/makelst/elf_loader.c create mode 100644 tools/makelst/elf_loader.h create mode 100644 tools/makelst/loader_subset.c create mode 100644 tools/makelst/loader_subset.h create mode 100644 tools/makelst/makelst.c create mode 100644 tools/makelst/readme.txt create mode 100644 tools/makelst/searcharg.c create mode 100644 tools/makelst/searcharg.h create mode 100644 tools/makelst/types.h create mode 100644 tools/makelst/version.h diff --git a/tools/makelst/Makefile b/tools/makelst/Makefile new file mode 100644 index 0000000..f68375a --- /dev/null +++ b/tools/makelst/Makefile @@ -0,0 +1,48 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: NitroSDK - tools - makelst +# File: Makefile +# +# 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 $(NITROSDK_ROOT)/build/buildtools/commondefs + +TARGETS = makelst.exe + +SOURCES_C = makelst.c arch.c elf.c loader_subset.c elf_loader.c searcharg.c + +SOURCES = $(SOURCES_C) + +OBJECTS = $(SOURCES_C:.c=.o) + +HEADERS = + +INSTALL_DIR = . +INSTALL_TARGETS = $(TARGETS) + +LDIRT_CLEAN = $(OBJECTS) $(TARGETS) + +include $(NITROSDK_ROOT)/build/buildtools/modulerules.x86 + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(OBJECTS) + $(CC_X86) $+ -o $@ + +makelcf.o: makelcf.c makelcf.h version.h + +version.h: $(SOURCES) $(HEADERS) $(MAKEFILE) + @for i in $^ ; \ + do \ + date -r $$i +'#define SDK_DATE_OF_LATEST_FILE %Y%m%dUL'; \ + done | sort | tail -1 > $@ diff --git a/tools/makelst/arch.c b/tools/makelst/arch.c new file mode 100644 index 0000000..99f7457 --- /dev/null +++ b/tools/makelst/arch.c @@ -0,0 +1,39 @@ + +#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/tools/makelst/arch.h b/tools/makelst/arch.h new file mode 100644 index 0000000..e853787 --- /dev/null +++ b/tools/makelst/arch.h @@ -0,0 +1,38 @@ +#ifndef ARCH_H_ +#define ARCH_H_ + +#include "types.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/tools/makelst/elf.c b/tools/makelst/elf.c new file mode 100644 index 0000000..fed91f0 --- /dev/null +++ b/tools/makelst/elf.c @@ -0,0 +1,341 @@ + +#include + +#include "types.h" + +#include "elf.h" +#include "stdio.h" +#include "stdlib.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; + + /* バッファにコピー */ + //MI_CpuCopy8( (void*)file_ptr, ehdr->e_ident, EI_NIDENT); + memcpy( (void*)(ehdr->e_ident), (void*)file_ptr, 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ヘッダ表示 ----------*/ +/* printf( "\nELF Header:\n"); + file_ptr = load_elf32_half(&(ehdr->e_machine), file_ptr, endian); + printf("e_machine = %d\n",ehdr->e_machine); + + file_ptr = load_elf32_word(&(ehdr->e_version), file_ptr, endian); + printf("e_version = %d\n",ehdr->e_version); + + file_ptr = load_elf32_word(&(ehdr->e_entry), file_ptr, endian); + printf("e_entry(entry point) = 0x%08x\n",ehdr->e_entry); + + file_ptr = load_elf32_word(&(ehdr->e_phoff), file_ptr, endian); + printf("e_phoff(program header offset) = 0x%08x\n",ehdr->e_phoff); + + file_ptr = load_elf32_word(&(ehdr->e_shoff), file_ptr, endian); + printf("e_shoff(section header offset) = 0x%08x\n",ehdr->e_shoff); + + file_ptr = load_elf32_word(&(ehdr->e_flags), file_ptr, endian); + printf("e_flags = 0x%08x\n",ehdr->e_flags); + if( ehdr->e_flags & EF_ARM_HASENTRY ) { + printf("has entry\n"); + } + if( ehdr->e_flags & EF_ARM_SYMSARESORTED ) { + printf("symbols are sorted\n"); + } + if( ehdr->e_flags & EF_ARM_DYNSYMSUSESEGIDX ) { + printf("dynamic symbols use segmnet index\n"); + } + if( ehdr->e_flags & EF_ARM_MAPSYMSFIRST ) { + printf("map symbols first\n"); + } + printf("EABI version %x \n", (ehdr->e_flags & EF_ARM_EABIMASK) >> 24 ); + + + file_ptr = load_elf32_half(&(ehdr->e_ehsize), file_ptr, endian); + printf("e_ehsize = %d\n",ehdr->e_ehsize); + + file_ptr = load_elf32_half(&(ehdr->e_phentsize), file_ptr, endian); + printf("e_phentsize = %d\n",ehdr->e_phentsize); + + file_ptr = load_elf32_half(&(ehdr->e_phnum), file_ptr, endian); + printf("e_phnum = %d\n",ehdr->e_phnum); + + file_ptr = load_elf32_half(&(ehdr->e_shentsize), file_ptr, endian); + printf("e_shentsize = %d\n",ehdr->e_shentsize); + + file_ptr = load_elf32_half(&(ehdr->e_shnum), file_ptr, endian); + printf("e_shnum = %d\n",ehdr->e_shnum); + + file_ptr = load_elf32_half(&(ehdr->e_shstrndx), file_ptr, endian); + printf("e_shstrndx(section index no. of the section header string table section = %d\n",ehdr->e_shstrndx); + printf( "\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/tools/makelst/elf.h b/tools/makelst/elf.h new file mode 100644 index 0000000..e69cef6 --- /dev/null +++ b/tools/makelst/elf.h @@ -0,0 +1,412 @@ +#ifndef ELF_H_ +#define ELF_H_ + +#include "types.h" + +/*--------------------------------------------------------- + 型定義 + --------------------------------------------------------*/ +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; + +/* */ +enum { + PT_NULL, /* 使われないエントリで、他のメンバの値の意味は未定義 */ + PT_LOAD, /* 実行時にロードされるセグメント */ + PT_DYNAMIC, /* 動的構造体配列を保持するセグメント */ + PT_INTERP, /* ファイルの解釈に使われるインタプリタのパスを保持するセグメント */ + PT_NOTE, /* ファイルの解釈には使われない情報を保持するセグメント */ + PT_SHLIB, /* 予約 */ + PT_PHDR, /* プログラムヘッダテーブル(プログラムのメモリイメージの一部である場合のみ存在) */ + PT_TLS, /* スレッド局所記憶領域のテンプレート */ + + PT_LOOS = 0x60000000, + /* OS固有のセマンティクスの為に予約された領域 */ + PT_HIOS = 0x6fffffff, + + PT_LOPROC = 0x70000000, + /* プロセッサ固有のセマンティクスの為に予約された領域 */ + PT_HIPROC = 0x7fffffff +}; + + +/*--------------------------------------------------------- + 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. */ + +/*セクションインデックス*/ +//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_MW_SPECIFIC 14 /*NITROアプリで出てくる(例:OS_TPrintf)*/ +#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/tools/makelst/elf_loader.c b/tools/makelst/elf_loader.c new file mode 100644 index 0000000..24a0180 --- /dev/null +++ b/tools/makelst/elf_loader.c @@ -0,0 +1,775 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +#include "types.h" +#include "elf.h" +#include "elf_loader.h" +#include "arch.h" +#include "loader_subset.h" + +//OSHeapHandle EL_Heap; +ELAdrEntry* ELAdrEntStart = NULL; +ELUnresolvedEntry* ELUnrEntStart = NULL; + +extern u16 dbg_print_flag; +extern u32 unresolved_table_block_flag; + +#define MAKELST_DS_API " elAddAdrEntry" //DS上でアドレステーブルに追加するAPI関数名 + +extern char c_source_line_str[256]; +extern FILE* CSourceFilep; + + +/*------------------------------------------------------ + ローカル関数の宣言 + -----------------------------------------------------*/ +// ELFオブジェクトまたはそのアーカイブをバッファに再配置する +u16 ELi_LoadLibrary( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf); +// ELFオブジェクトをバッファに再配置するコア関数 +u16 ELi_LoadObject( ELHandle* ElfHandle, void* obj_offset, void* buf); +// ELFオブジェクトからデータを読み出すスタブ関数 +void ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); +void ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size); + + + + +/*--------------------------------------------------------- + ELFオブジェクトのサイズを求める + + buf : ELFイメージのアドレス + --------------------------------------------------------*/ +u32 EL_GetElfSize( const void* buf) +{ + Elf32_Ehdr Ehdr; + u32 size; + + if( ELF_LoadELFHeader( buf, &Ehdr) == NULL) { + return 0; + } + size = (u32)(Ehdr.e_shoff + (Ehdr.e_shentsize * Ehdr.e_shnum)); + return size; +} + + +/*------------------------------------------------------ + ダイナミックリンクシステムを初期化する + -----------------------------------------------------*/ +void EL_Init( void) +{ +// void* heap_start; + printf( "\n"); + /*--- メモリアロケーション関係の設定 ---*/ +/* 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);*/ + /*--------------------------------------*/ +} + +/*------------------------------------------------------ + ELHandle構造体を初期化する + -----------------------------------------------------*/ +BOOL EL_InitHandle( ELHandle* ElfHandle) +{ + if( ElfHandle == NULL) { /*NULLチェック*/ + return FALSE; + } + + /*初期値の設定*/ + ElfHandle->ShdrEx = NULL; + ElfHandle->SymEx = NULL; + + ElfHandle->process = EL_INITIALIZED; /*フラグの設定*/ + + return TRUE; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + ElfHandle : ヘッダ構造体 + ObjFile : OBJファイルまたはアーカイブファイルの構造体 + buf : ロードするバッファ + -----------------------------------------------------*/ +u16 EL_LoadLibraryfromFile( ELHandle* ElfHandle, FILE* ObjFile, void* buf) +{ + u16 result; + u32 len; + + /*リード関数の設定*/ + ElfHandle->ELi_ReadStub = ELi_ReadFile; + ElfHandle->FileStruct = ObjFile; + + fseek( ObjFile, 0, SEEK_END); + len = ftell( ObjFile); + fseek( ObjFile, 0, SEEK_SET); + result = ELi_LoadLibrary( ElfHandle, NULL, len, buf); + + return result; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + ElfHandle : ヘッダ構造体 + obj_image : OBJファイルまたはアーカイブファイルのRAM上イメージアドレス + buf : ロードするバッファ + -----------------------------------------------------*/ +u16 EL_LoadLibraryfromMem( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf) +{ + u16 result; + + /*リード関数の設定*/ + ElfHandle->ELi_ReadStub = ELi_ReadMem; + ElfHandle->FileStruct = NULL; + + result = ELi_LoadLibrary( ElfHandle, obj_image, obj_len, buf); + + return result; +} + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをバッファに再配置する + + ElfHandle : ヘッダ構造体 + obj_image : OBJファイルまたはアーカイブファイルのRAM上イメージアドレス + buf : ロードするバッファ + -----------------------------------------------------*/ +u16 ELi_LoadLibrary( ELHandle* ElfHandle, 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; + ElfHandle->ar_head = obj_image; + image_pointer = 0; + + ElfHandle->ELi_ReadStub( OBJMAG, ElfHandle->FileStruct, (u32)obj_image, 0, 8); /*OBJの文字列を取得*/ + /*--------------- アーカイブファイルの場合 ---------------*/ + if( strncmp( OBJMAG, ARMAG, 8) == 0) { + arch_size = sizeof( ArchHdr); + image_pointer += 8; /*最初のエントリへ*/ + + ElfHandle->buf_current = buf; + while( image_pointer < obj_len) { + ElfHandle->ELi_ReadStub( OBJMAG, ElfHandle->FileStruct, (u32)(obj_image), (image_pointer+arch_size), 4); /*OBJの文字列を取得*/ + if( strncmp( OBJMAG, ELFMAG, 4) == 0) { + elf_num++; + result = ELi_LoadObject( ElfHandle, (void*)(image_pointer+arch_size), ElfHandle->buf_current); + if( result < all_result) { /*悪い結果のときだけall_resultに反映*/ + all_result = result; + } + /*初期値の設定*/ + ElfHandle->ShdrEx = NULL; + ElfHandle->SymEx = NULL; + ElfHandle->process = EL_INITIALIZED; /*フラグの設定*/ + }else{ + } + /*次のエントリへ*/ + ElfHandle->ELi_ReadStub( &ArHdr, ElfHandle->FileStruct, (u32)(obj_image), image_pointer, arch_size); + image_pointer += arch_size + AR_GetEntrySize( &ArHdr); + } + }else{/*--------------- ELFファイルの場合 ---------------*/ + if( strncmp( OBJMAG, ELFMAG, 4) == 0) { + elf_num++; + all_result = ELi_LoadObject( ElfHandle, 0, buf); + } + } + /*-------------------------------------------------------*/ + + if( elf_num) { + return all_result; + }else{ + return EL_FAILED; + } +} + +/*------------------------------------------------------ + ELFオブジェクトをバッファに再配置する + + ElfHandle : ヘッダ構造体 + obj_offset : OBJファイルのRAM上イメージアドレスからのオフセット + buf : ロードするバッファ + -----------------------------------------------------*/ +u16 ELi_LoadObject( ELHandle* ElfHandle, void* obj_offset, void* buf) +{ + u16 i, j; + u32 num_of_entry; + ELShdrEx* FwdShdrEx; + ELShdrEx* CurrentShdrEx; + ELShdrEx DmyShdrEx; + char sym_str[128]; //デバッグプリント用 + u32 offset; //デバッグプリント用 + + /* ELHandleの初期化チェック */ + if( ElfHandle->process != EL_INITIALIZED) { + return EL_FAILED; + } + /* バッファのNULLチェック */ + if( buf == NULL) { + return EL_FAILED; + } + /* ELFヘッダの取得 */ + ElfHandle->ELi_ReadStub( &(ElfHandle->CurrentEhdr), ElfHandle->FileStruct, + (u32)(ElfHandle->ar_head), (u32)(obj_offset), sizeof( Elf32_Ehdr)); + + /* セクションハンドル構築 */ + ElfHandle->elf_offset = obj_offset; + ElfHandle->buf_current = buf; + ElfHandle->shentsize = ElfHandle->CurrentEhdr.e_shentsize; + + /*---------- ELShdrExのリストを作る ----------*/ + CurrentShdrEx = &DmyShdrEx; + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + CurrentShdrEx->next = (void*)(malloc( sizeof(ELShdrEx))); + CurrentShdrEx = (ELShdrEx*)(CurrentShdrEx->next); + memset( CurrentShdrEx, 0, sizeof(ELShdrEx)); //ゼロクリア + + /*デバッグ情報かどうかを判別してフラグをセット*/ + if( ELi_ShdrIsDebug( ElfHandle, i) == TRUE) { /*デバッグ情報の場合*/ + CurrentShdrEx->debug_flag = 1; + }else{ /*デバッグ情報でない場合*/ + /*セクションヘッダをコピー*/ + ELi_GetShdr( ElfHandle, i, &(CurrentShdrEx->Shdr)); + CurrentShdrEx->debug_flag = 0; + } + } + CurrentShdrEx->next = NULL; + ElfHandle->ShdrEx = DmyShdrEx.next; + /*--------------------------------------------*/ + + /*---------- 全セクションを調べてコピーする ----------*/ +/* printf( "\nLoad to RAM:\n"); + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + // + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + + if( CurrentShdrEx->debug_flag == 1) { //デバッグ情報の場合 + printf( "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) + ELi_CopySectionToBuffer( ElfHandle, &(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) + ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + } + // .bss section + else if( (CurrentShdrEx->Shdr.sh_flags == (SHF_ALLOC | SHF_WRITE))&& + (CurrentShdrEx->Shdr.sh_type == SHT_NOBITS)) { + //コピーしない + CurrentShdrEx->loaded_adr = (u32) + ELi_AllocSectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + } + // .rodata, .rodata1 section + else if( (CurrentShdrEx->Shdr.sh_flags == SHF_ALLOC)&& + (CurrentShdrEx->Shdr.sh_type == SHT_PROGBITS)) { + //メモリにコピー + CurrentShdrEx->loaded_adr = (u32) + ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + } + + printf( "section %02x relocated at %08x\n", + i, CurrentShdrEx->loaded_adr); + } + } + // コピー終了後 + ElfHandle->process = EL_COPIED;*/ + /*----------------------------------------------------*/ + + /*---------- 再配置 ----------*/ + if( unresolved_table_block_flag == 0) { + if( dbg_print_flag == 1) { + printf( "\nRelocate Symbols:\n"); + } + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + /**/ + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + + if( CurrentShdrEx->debug_flag == 1) { /*デバッグ情報の場合*/ + }else{ /*デバッグ情報でない場合*/ + + if( CurrentShdrEx->Shdr.sh_type == SHT_REL) { + num_of_entry = (CurrentShdrEx->Shdr.sh_size) / + (CurrentShdrEx->Shdr.sh_entsize); + if( dbg_print_flag == 1) { + printf( "num of REL = %x\n", (int)(num_of_entry)); + printf( "Section Header Info.\n"); + printf( "link : %x\n", (int)(CurrentShdrEx->Shdr.sh_link)); + printf( "info : %x\n", (int)(CurrentShdrEx->Shdr.sh_info)); + printf( " Offset Info Type Sym.Value Sym.Name\n"); + } + offset = 0; + for( j=0; jRel), offset, sizeof(Elf32_Rel)); + ELi_GetShdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->SymShdr)); + ELi_GetSent( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->Sym), + (u32)(ElfHandle->SymShdr.sh_entsize * ELF32_R_SYM( ElfHandle->Rel.r_info)), sizeof(Elf32_Sym)); + ELi_GetStrAdr( ElfHandle, ElfHandle->SymShdr.sh_link, ElfHandle->Sym.st_name, sym_str, 128); + + if( dbg_print_flag == 1) { + printf( "%08x ", (int)(ElfHandle->Rel.r_offset)); + printf( "%08x ", (int)(ElfHandle->Rel.r_info)); + printf( " "); + printf( "%08x ", (int)(ElfHandle->Sym.st_value)); + printf( sym_str); + printf( "\n"); + } + /*次のエントリへ*/ + offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); + } + if( dbg_print_flag == 1) { + printf( "\n"); + } + /*リロケート*/ + ELi_RelocateSym( ElfHandle, i); + if( dbg_print_flag == 1) { + printf( "\n"); + } + } + else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) { + + num_of_entry = (CurrentShdrEx->Shdr.sh_size) / + (CurrentShdrEx->Shdr.sh_entsize); + if( dbg_print_flag == 1) { + printf( "num of RELA = %x\n", (int)(num_of_entry)); + printf( "Section Header Info.\n"); + printf( "link : %x\n", (int)(CurrentShdrEx->Shdr.sh_link)); + printf( "info : %x\n", (int)(CurrentShdrEx->Shdr.sh_info)); + printf( " Offset Info Type Sym.Value Sym.Name\n"); + } + offset = 0; + for( j=0; jRela), offset, sizeof(Elf32_Rel)); + ELi_GetShdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->SymShdr)); + ELi_GetSent( ElfHandle, CurrentShdrEx->Shdr.sh_link, &(ElfHandle->Sym), + (u32)(ElfHandle->SymShdr.sh_entsize * ELF32_R_SYM( ElfHandle->Rela.r_info)), sizeof(Elf32_Sym)); + ELi_GetStrAdr( ElfHandle, ElfHandle->SymShdr.sh_link, ElfHandle->Sym.st_name, sym_str, 128); + + if( dbg_print_flag == 1) { + printf( "%08x ", (int)(ElfHandle->Rela.r_offset)); + printf( "%08x ", (int)(ElfHandle->Rela.r_info)); + printf( " "); + printf( "%08x ", (int)(ElfHandle->Sym.st_value)); + printf( sym_str); + printf( "\n"); + } + /*次のエントリへ*/ + offset += (u32)(CurrentShdrEx->Shdr.sh_entsize); + } + if( dbg_print_flag == 1) { + printf( "\n"); + } + /*リロケート*/ + ELi_RelocateSym( ElfHandle, i); + if( dbg_print_flag == 1) { + printf( "\n"); + } + } + } + } + }else{ /*dllでなくてstaticモジュールの場合*/ + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + if( CurrentShdrEx->debug_flag == 1) { /*デバッグ情報の場合*/ + }else{ + if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) { + ELi_DiscriminateGlobalSym( ElfHandle, i); + } + } + } + } + + /*------- ELShdrExのリストを解放する -------*/ + CurrentShdrEx = ElfHandle->ShdrEx; + if( CurrentShdrEx) { + while( CurrentShdrEx->next != NULL) { + FwdShdrEx = CurrentShdrEx; + CurrentShdrEx = CurrentShdrEx->next; + free( FwdShdrEx); + } + ElfHandle->ShdrEx = NULL; + } + /*-----------------------------------------*/ + + /*RAM上のDLLが呼ばれる前にキャッシュをフラッシュ*/ +// DC_FlushAll(); +// DC_WaitWriteBufferEmpty(); + + return (ElfHandle->process); +} + +/*------------------------------------------------------ + 未解決のシンボルがあればアドレステーブルを使って解決する + -----------------------------------------------------*/ +u16 EL_ResolveAllLibrary( void) +{ + ELAdrEntry* AdrEnt; + ELUnresolvedEntry* RemoveUnrEnt; + ELUnresolvedEntry* UnrEnt; +// ELUnresolvedEntry* CurrentUnrEnt; +// ELUnresolvedEntry* FwdUnrEnt; +// u32 relocation_val; +// ELAdrEntry AddAdrEnt; + char sym_str[128]; + + UnrEnt = ELUnrEntStart; + if( dbg_print_flag == 1) { + printf( "\nResolve all symbols:\n"); + } + while( UnrEnt != NULL) { + if( UnrEnt->remove_flag == 0) { + AdrEnt = EL_GetAdrEntry( UnrEnt->sym_str); /*アドレステーブルから検索*/ + if( AdrEnt) { /*アドレステーブルから見つかった場合*/ + UnrEnt->S_ = (u32)(AdrEnt->adr); + UnrEnt->T_ = (u32)(AdrEnt->thumb_flag); + if( unresolved_table_block_flag == 0) { + if( dbg_print_flag == 1) { + printf( "\n symbol found %s : %8x\n", UnrEnt->sym_str, (int)(UnrEnt->S_)); + } + UnrEnt->remove_flag = 1; + // ELi_RemoveUnresolvedEntry( UnrEnt); //解決したので未解決リストから削除 + }else{ + if( dbg_print_flag == 1) { + printf( "\n static symbol found %s : %8x\n", UnrEnt->sym_str, (int)(UnrEnt->S_)); + } + UnrEnt->AdrEnt = AdrEnt; //見つけたアドレスエントリをセット + UnrEnt->remove_flag = 2; //マーキング(makelstだけで使用する特別な値) + strcpy( sym_str, UnrEnt->sym_str); + while( 1) { + RemoveUnrEnt = ELi_GetUnresolvedEntry( sym_str); + if( RemoveUnrEnt == NULL) { + break; + }else{ + RemoveUnrEnt->remove_flag = 1; + } + } + } + /* relocation_val = ELi_DoRelocate( UnrEnt); //シンボル解決 + if( !relocation_val) { + return EL_FAILED; + }*/ + + }else{ /*アドレステーブルから見つからなかった場合*/ + if( unresolved_table_block_flag == 0) { + if( dbg_print_flag == 1) { + printf( "ERROR! cannot find symbol : %s\n", UnrEnt->sym_str); + } + }else{ + if( dbg_print_flag == 1) { + printf( "ERROR! cannot find static symbol : %s\n", UnrEnt->sym_str); + } + } + /* AddAdrEnt.next = NULL; + AddAdrEnt.name = UnrEnt->sym_str; + AddAdrEnt. + EL_AddAdrEntry( */ + // return EL_FAILED; + } + } + UnrEnt = (ELUnresolvedEntry*)(UnrEnt->next); /*次の未解決エントリへ*/ + } + + /*--- ELUnresolvedEntryのリストを解放する ---*/ +/* CurrentUnrEnt = ELUnrEntStart; + if( CurrentUnrEnt) { + while( CurrentUnrEnt->next != NULL) { + FwdUnrEnt = CurrentUnrEnt; + CurrentUnrEnt = CurrentUnrEnt->next; + free( FwdUnrEnt->sym_str); //シンボル名文字列 + free( FwdUnrEnt); //構造体自身 + } + ELUnrEntStart = NULL; + }*/ + /*-------------------------------------------*/ + + /*RAM上のDLLが呼ばれる前にキャッシュをフラッシュ*/ +// DC_FlushAll(); +// DC_WaitWriteBufferEmpty(); + + return EL_RELOCATED; +} + + + +/*------------------------------------------------------ + マーキングされたシンボルを公開用ファイルに構造体として書き出す + -----------------------------------------------------*/ +u16 EL_ExtractStaticSym1( void) +{ +// ELAdrEntry* AdrEnt; +// ELUnresolvedEntry* RemoveUnrEnt; + ELUnresolvedEntry* UnrEnt; +// ELUnresolvedEntry* CurrentUnrEnt; +// ELUnresolvedEntry* FwdUnrEnt; +// u32 relocation_val; +// ELAdrEntry AddAdrEnt; + char sym_str[256]; + + + UnrEnt = ELUnrEntStart; + + + file_write( "/*--------------------------------\n", CSourceFilep); + file_write( " extern symbol\n", CSourceFilep); + file_write( " --------------------------------*/\n", CSourceFilep); + + while( UnrEnt != NULL) { + if( UnrEnt->remove_flag == 2) {//マーキング(makelstだけで使用する特別な値) + if( (UnrEnt->AdrEnt->func_flag) != STT_FUNC) { + memset( sym_str, 0, 128); + strcpy( sym_str, "extern u8 "); + strcat( sym_str, UnrEnt->sym_str); + strcat( sym_str, ";\n"); + file_write( sym_str, CSourceFilep); + } + } + UnrEnt = (ELUnresolvedEntry*)(UnrEnt->next); /*次の未解決エントリへ*/ + } + + file_write( "\n\n", CSourceFilep); + + + file_write( "/*--------------------------------\n", CSourceFilep); + file_write( " symbol structure\n", CSourceFilep); + file_write( " --------------------------------*/\n", CSourceFilep); + + UnrEnt = ELUnrEntStart; + + while( UnrEnt != NULL) { + if( UnrEnt->remove_flag == 2) {//マーキング(makelstだけで使用する特別な値) + memset( sym_str, 0, 128); + strcpy( sym_str, "ElAdrEntry AdrEnt_"); + strcat( sym_str, UnrEnt->sym_str); + strcat( sym_str, " = {\n"); + file_write( sym_str, CSourceFilep); + + file_write( " (void*)NULL,\n", CSourceFilep); + + strcpy( sym_str, " (char*)\""); + strcat( sym_str, UnrEnt->sym_str); + strcat( sym_str, "\\0\", \n"); + file_write( sym_str, CSourceFilep); + + if( (UnrEnt->AdrEnt->func_flag) == STT_FUNC) { + strcpy( sym_str, " (void*)"); + }else{ + strcpy( sym_str, " (void*)&"); + } + strcat( sym_str, UnrEnt->sym_str); + strcat( sym_str, ",\n"); + file_write( sym_str, CSourceFilep); + + if( (UnrEnt->AdrEnt->func_flag) == 1) { + file_write( " 0,\n", CSourceFilep); + }else{ + file_write( " 1,\n", CSourceFilep); + } + if( (UnrEnt->AdrEnt->thumb_flag) == 0) { + file_write( " 0,\n", CSourceFilep); + }else{ + file_write( " 1,\n", CSourceFilep); + } + file_write( "};\n", CSourceFilep); + +// printf( "\n static symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_); + } + UnrEnt = (ELUnresolvedEntry*)(UnrEnt->next); /*次の未解決エントリへ*/ + } +} + +/*------------------------------------------------------ + マーキングされたシンボルを公開用ファイルにAPIとして書き出す + -----------------------------------------------------*/ +u16 EL_ExtractStaticSym2( void) +{ +// ELAdrEntry* AdrEnt; +// ELUnresolvedEntry* RemoveUnrEnt; + ELUnresolvedEntry* UnrEnt; +// ELUnresolvedEntry* CurrentUnrEnt; +// ELUnresolvedEntry* FwdUnrEnt; +// u32 relocation_val; +// ELAdrEntry AddAdrEnt; + char sym_str[256]; + + UnrEnt = ELUnrEntStart; + + while( UnrEnt != NULL) { + if( UnrEnt->remove_flag == 2) {//マーキング(makelstだけで使用する特別な値) + memset( sym_str, 0, 128); + strcpy( sym_str, MAKELST_DS_API); + strcat( sym_str, "( &AdrEnt_"); + strcat( sym_str, UnrEnt->sym_str); + strcat( sym_str, ");\n"); + file_write( sym_str, CSourceFilep); + +// printf( "\n static symbol found %s : %8x\n", UnrEnt->sym_str, UnrEnt->S_); + } + UnrEnt = (ELUnresolvedEntry*)(UnrEnt->next); /*次の未解決エントリへ*/ + } +} + + +/*------------------------------------------------------ + アドレステーブルからエントリを削除する + -----------------------------------------------------*/ +BOOL EL_RemoveAdrEntry( 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; + + return TRUE; +} + +/*------------------------------------------------------ + アドレステーブルにエントリを追加する + -----------------------------------------------------*/ +void EL_AddAdrEntry( 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; +} + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ELAdrEntry* EL_GetAdrEntry( char* ent_name) +{ + ELAdrEntry* CurrentAdrEnt; + + CurrentAdrEnt = ELAdrEntStart; + if( CurrentAdrEnt == NULL) { + return NULL; + } + while( strcmp( CurrentAdrEnt->name, ent_name) != 0) { + CurrentAdrEnt = (ELAdrEntry*)CurrentAdrEnt->next; + if( CurrentAdrEnt == NULL) { + break; + } + } + return CurrentAdrEnt; +} + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するアドレスを返す + -----------------------------------------------------*/ +void* EL_GetGlobalAdr( char* ent_name) +{ + u32 adr; + ELAdrEntry* CurrentAdrEnt; + + CurrentAdrEnt = EL_GetAdrEntry( 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* EL_FreeAdrTbl( void) +{ + ELAdrEntry* FwdAdrEnt; + ELAdrEntry* CurrentAdrEnt; + + /*--- ELAdrEntryのリストを解放する ---*/ + CurrentAdrEnt = ELAdrEntStart; + if( CurrentAdrEnt) { + while( CurrentAdrEnt->next != NULL) { + FwdAdrEnt = CurrentAdrEnt; + CurrentAdrEnt = CurrentAdrEnt->next; + free( FwdAdrEnt->name); //シンボル名文字列 + free( FwdAdrEnt); //構造体自身 + } + ELAdrEntStart = NULL; + } + /*------------------------------------*/ +} +#endif + +/*------------------------------------------------------ + ELFオブジェクトからデータを読み出すスタブ + -----------------------------------------------------*/ +void ELi_ReadFile( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) +{ + fseek( file_struct, file_offset, SEEK_SET); + fread( buf, 1, size, file_struct); + +/* FS_SeekFile( file_struct, (s32)(file_offset), FS_SEEK_SET); + FS_ReadFile( file_struct, buf, (s32)(size));*/ +} + +void ELi_ReadMem( void* buf, void* file_struct, u32 file_base, u32 file_offset, u32 size) +{ +/* MI_CpuCopy8( (void*)(file_base + file_offset), + buf, + size);*/ + memcpy( buf, + (void*)(file_base + file_offset), + size); +} diff --git a/tools/makelst/elf_loader.h b/tools/makelst/elf_loader.h new file mode 100644 index 0000000..8fa895a --- /dev/null +++ b/tools/makelst/elf_loader.h @@ -0,0 +1,192 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: elf_loader.h + + Copyright 2006 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 "types.h" +#include "elf.h" +#include "stdio.h" + + +/*------------------------------------------------------ + セクションヘッダ拡張(ロードアドレス等に対応) + -----------------------------------------------------*/ +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; + + + +/*------------------------------------------------------ + ELFオブジェクトの管理 + -----------------------------------------------------*/ +typedef void (*ELi_ReadFunc)( 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リストの先頭 */ + + ELi_ReadFunc ELi_ReadStub; /* リードスタブ関数 */ + void* FileStruct; /* ファイル構造体 */ + + u32 mem_adr; /*最初にロードされたセクションのsh_addrが入る(DSのROMヘッダ用パラメータ)*/ +}ELHandle; + + + +/*------------------------------------------------------ + アドレステーブル + -----------------------------------------------------*/ +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; /*解決したときにセットする(消しても良いことを識別する)フラグ*/ + ELAdrEntry* AdrEnt; /*アドレステーブルから探し出したエントリの場所*/ +}ELUnresolvedEntry; + + + +/* ELHandle の process値 */ +#define EL_FAILED 0x00 +#define EL_INITIALIZED 0x5A +#define EL_COPIED 0xF0 +#define EL_RELOCATED 0xF1 + + + +/*--------------------------------------------------------- + ELFオブジェクトのサイズを求める + --------------------------------------------------------*/ +u32 EL_GetElfSize( const void* buf); + +/*------------------------------------------------------ + ダイナミックリンクシステムを初期化する + -----------------------------------------------------*/ +void EL_Init( void); + +/*------------------------------------------------------ + ELHandle構造体を初期化する + -----------------------------------------------------*/ +BOOL EL_InitHandle( ELHandle* ElfHandle); + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをファイルからバッファに再配置する + -----------------------------------------------------*/ +u16 EL_LoadLibraryfromFile( ELHandle* ElfHandle, FILE* ObjFile, void* buf); + +/*------------------------------------------------------ + ELFオブジェクトまたはそのアーカイブをメモリからバッファに再配置する + -----------------------------------------------------*/ +u16 EL_LoadLibraryfromMem( ELHandle* ElfHandle, void* obj_image, u32 obj_len, void* buf); + +/*------------------------------------------------------ + アドレステーブルを使って未解決のシンボルを解決する + -----------------------------------------------------*/ +u16 EL_ResolveAllLibrary( void); + + +/*------------------------------------------------------ + マーキングされたシンボルを公開用ファイルに構造体として書き出す + -----------------------------------------------------*/ +u16 EL_ExtractStaticSym1( void); +/*------------------------------------------------------ + マーキングされたシンボルを公開用ファイルにAPIとして書き出す + -----------------------------------------------------*/ +u16 EL_ExtractStaticSym2( void); + + +/*------------------------------------------------------ + アドレステーブルからエントリを削除する + -----------------------------------------------------*/ +BOOL EL_RemoveAdrEntry( ELAdrEntry* AdrEnt); + +/*------------------------------------------------------ + アドレステーブルにエントリを追加する + -----------------------------------------------------*/ +void EL_AddAdrEntry( ELAdrEntry* AdrEnt); + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ELAdrEntry* EL_GetAdrEntry( char* ent_name); + +/*------------------------------------------------------ + アドレステーブルから指定文字列に該当するアドレスを返す + -----------------------------------------------------*/ +void* EL_GetGlobalAdr( char* ent_name); + + + + + +/*他に必要そうな関数*/ +//ロードに必要なメモリのバイト数を算出する関数 +//EL_FreeLibrary + +#endif /*_ELF_LOADER_H_*/ + + + diff --git a/tools/makelst/loader_subset.c b/tools/makelst/loader_subset.c new file mode 100644 index 0000000..c9ffb36 --- /dev/null +++ b/tools/makelst/loader_subset.c @@ -0,0 +1,819 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +#include "loader_subset.h" + + +extern ELUnresolvedEntry* ELUnrEntStart; + +extern u16 dbg_print_flag; +extern u32 unresolved_table_block_flag; + + +//ARM7かどうかを判別するときは、 +//#ifdef SDK_ARM7 +//#endif /*SDK_ARM7*/ + + +/*------------------------------------------------------ + アドレスをアラインメントする + -----------------------------------------------------*/ +#define ALIGN( addr, align_size ) (((addr) & ~((align_size) - 1)) + (align_size)) + +static u32 ELi_ALIGN( u32 addr, u32 align_size); +u32 ELi_ALIGN( 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; +} + + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopySectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr) +{ + u32 load_start; + Elf32_Addr sh_size; + + /*アラインメントをとる*/ +// load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign)); + load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); + /*サイズ設定*/ + sh_size = Shdr->sh_size; + + /*コピー*/ + ElfHandle->ELi_ReadStub( (void*)load_start, + ElfHandle->FileStruct, + (u32)(ElfHandle->ar_head), + (u32)(ElfHandle->elf_offset)+(u32)(Shdr->sh_offset), + sh_size); + + /*バッファポインタを移動*/ + ElfHandle->buf_current = (void*)(load_start + sh_size); + + /*ロードした先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + セクションをバッファに確保(コピーしない)し、 + その領域を0で埋める + -----------------------------------------------------*/ +void* ELi_AllocSectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr) +{ + u32 load_start; + Elf32_Addr sh_size; + + /*アラインメントをとる*/ +// load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign)); + load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); + /*サイズ設定*/ + sh_size = Shdr->sh_size; + + /*バッファポインタを移動*/ + ElfHandle->buf_current = (void*)(load_start + sh_size); + + /*0で埋める(.bssセクションを想定しているため)*/ + memset( (void*)load_start, 0, sh_size); + + /*確保した先頭アドレスを返す*/ + return (void*)load_start; +} + + +/*------------------------------------------------------ + 指定インデックスのセクションヘッダをバッファに取得する + -----------------------------------------------------*/ +void ELi_GetShdr( ELHandle* ElfHandle, u32 index, Elf32_Shdr* Shdr) +{ + u32 offset; + + offset = (ElfHandle->CurrentEhdr.e_shoff) + ((u32)(ElfHandle->shentsize) * index); + + ElfHandle->ELi_ReadStub( Shdr, + ElfHandle->FileStruct, + (u32)(ElfHandle->ar_head), + (u32)(ElfHandle->elf_offset) + offset, + sizeof( Elf32_Shdr)); +} + +/*------------------------------------------------------ + 指定インデックスのセクションのエントリをバッファに取得する + -----------------------------------------------------*/ +void ELi_GetSent( ELHandle* ElfHandle, u32 index, void* entry_buf, u32 offset, u32 size) +{ + Elf32_Shdr Shdr; + //u32 entry_adr; + + ELi_GetShdr( ElfHandle, index, &Shdr); + + ElfHandle->ELi_ReadStub( entry_buf, + ElfHandle->FileStruct, + (u32)(ElfHandle->ar_head), + (u32)(ElfHandle->elf_offset) + (u32)(Shdr.sh_offset) + offset, + size); +} + + +/*------------------------------------------------------ + 指定セクションヘッダの指定インデックスのエントリをバッファに取得する + (Rel,Rela,Symなどエントリサイズが固定のセクションのみ) + Shdr : 指定セクションヘッダ + index : エントリ番号(0〜) + -----------------------------------------------------*/ +void ELi_GetEntry( ELHandle* ElfHandle, Elf32_Shdr* Shdr, u32 index, void* entry_buf) +{ + u32 offset; + + offset = (u32)(Shdr->sh_offset) + ((Shdr->sh_entsize) * index); + + ElfHandle->ELi_ReadStub( entry_buf, + ElfHandle->FileStruct, + (u32)(ElfHandle->ar_head), + (u32)(ElfHandle->elf_offset) + offset, + Shdr->sh_entsize); +} + +/*------------------------------------------------------ + STRセクションヘッダの指定インデックスの文字列を取得する + + Shdr : 指定セクションヘッダ + index : エントリインデックス(0〜) + -----------------------------------------------------*/ +void ELi_GetStrAdr( ELHandle* ElfHandle, u32 strsh_index, u32 ent_index, char* str, u32 len) +{ + /*文字列エントリの先頭アドレス*/ + ELi_GetSent( ElfHandle, 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 ELi_RelocateSym( ELHandle* ElfHandle, u32 relsh_index) +{ + u32 i; + u32 num_of_sym; //シンボルの全体数 + u32 num_of_rel; //再定義すべきシンボルの数 + Elf32_Shdr RelOrRelaShdr; //RELまたはRELAセクションヘッダ + Elf32_Rela CurrentRela; //RELまたはRELAエントリのコピー先 + Elf32_Shdr* SymShdr; + ELSymEx* CurrentSymEx; + ELSymEx* FwdSymEx; + ELSymEx DmySymEx; + ELShdrEx* TargetShdrEx; + ELShdrEx* CurrentShdrEx; + u32 relocation_adr; + char sym_str[128]; + u32 copy_size; + ELAdrEntry* CurrentAdrEntry; + u32 sym_loaded_adr; + ELAdrEntry* ExportAdrEntry; + u32 thumb_func_flag; + ELUnresolvedEntry UnresolvedInfo; + ELUnresolvedEntry* UnrEnt; + u32 unresolved_num = 0; + + /*REL or RELAセクションヘッダ取得*/ + ELi_GetShdr( ElfHandle, relsh_index, &RelOrRelaShdr); + + /*RELセクションとSYMセクションは1対1対応*/ + ELi_GetShdr( ElfHandle, RelOrRelaShdr.sh_link, &(ElfHandle->SymShdr)); + SymShdr = &(ElfHandle->SymShdr); + if( dbg_print_flag == 1) { + printf( "SymShdr->link:%02x, SymShdr->info:%02x\n", + (int)(SymShdr->sh_link), (int)(SymShdr->sh_info)); + } + + /*ターゲットセクションのEXヘッダ*/ + TargetShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, RelOrRelaShdr.sh_info); + + num_of_rel = (RelOrRelaShdr.sh_size) / (RelOrRelaShdr.sh_entsize); //再定義すべきシンボルの数 + num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize); //シンボルの全体数 + + /*---------- ELSymExのリストを作る ----------*/ + CurrentSymEx = &DmySymEx; + for( i=0; inext = (void*)(malloc( sizeof(ELSymEx))); + CurrentSymEx = (ELSymEx*)(CurrentSymEx->next); + + /*シンボルエントリをコピー*/ + ELi_GetEntry( ElfHandle, SymShdr, i, &(CurrentSymEx->Sym)); + + /*デバッグ情報フラグをセット*/ + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx); + if( CurrentShdrEx) { + CurrentSymEx->debug_flag = CurrentShdrEx->debug_flag; + }else{ + CurrentSymEx->debug_flag = 0; + } + +// printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx); + } + CurrentSymEx->next = NULL; + ElfHandle->SymEx = DmySymEx.next; + /*-------------------------------------------*/ + + /*----- ELSymExのThumbフラグをセット(関数シンボルだけ必要)-----*/ + CurrentSymEx = ElfHandle->SymEx; + for( i=0; iSym.st_info) == STT_FUNC) { + CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( ElfHandle, CurrentSymEx->Sym.st_shndx, + CurrentSymEx->Sym.st_value)); + }else{ + CurrentSymEx->thumb_flag = 0; + } + CurrentSymEx = CurrentSymEx->next; + } + /*---------------------------------------------------------------*/ + + /*--- 再定義が必要なシンボルの再定義 ---*/ + for( i=0; iSymEx, + ELF32_R_SYM( CurrentRela.r_info)); + + if( CurrentSymEx->debug_flag == 1) { /*デバッグ情報の場合*/ + }else{ /*デバッグ情報でない場合*/ + /**/ + ELi_UnresolvedInfoInit( &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) { + /*アドレステーブルから検索*/ + ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128); + CurrentAdrEntry = EL_GetAdrEntry( sym_str); + if( CurrentAdrEntry) { + sym_loaded_adr = (u32)(CurrentAdrEntry->adr); + /*THUMB関数フラグ(仕様書でいう「T」)THUMB or ARM の判別*/ + thumb_func_flag = CurrentAdrEntry->thumb_flag; + if( dbg_print_flag == 1) { + printf( "\n symbol found %s : %8x\n", sym_str, (int)(sym_loaded_adr)); + } + }else{ + /*見つからなかった時はエラー(S_とT_が解決できない)*/ + copy_size = (u32)strlen( sym_str) + 1; + UnresolvedInfo.sym_str = (char*)(malloc( copy_size)); + //MI_CpuCopy8( sym_str, UnresolvedInfo.sym_str, copy_size); + memcpy( UnresolvedInfo.sym_str, sym_str, copy_size); + + /*グローバルな未解決テーブルに追加*/ + copy_size = sizeof( ELUnresolvedEntry); + UnrEnt = (ELUnresolvedEntry*)(malloc( copy_size)); + //MI_CpuCopy8( &UnresolvedInfo, UnrEnt, copy_size); + memcpy( UnrEnt, &UnresolvedInfo, copy_size); + + if( unresolved_table_block_flag == 0) { //テーブルへの追加が禁止されていなければ + ELi_AddUnresolvedEntry( UnrEnt); + } + + unresolved_num++; /*未解決シンボル数をカウント*/ + if( dbg_print_flag == 1) { + printf( "WARNING! cannot find symbol : %s\n", sym_str); + } + } + }else{ + /*シンボルの所属するセクションのExヘッダ取得*/ + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->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 = ELi_DoRelocate( &UnresolvedInfo); + /*------------------------------------------------------------*/ + } + } + } + /*-----------------------------------*/ + /*--- ライブラリ内のGLOBALシンボルをアドレステーブルに公開する ---*/ + for( i=0; iSymEx, i); + /*GLOBALで、かつ関連するセクションがライブラリ内に存在する場合*/ + if( ((ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) || + (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_WEAK) || + (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_MW_SPECIFIC))&& + (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) { + + ExportAdrEntry = (ELAdrEntry*)(malloc( sizeof(ELAdrEntry))); /*メモリ確保*/ + + ExportAdrEntry->next = NULL; + + ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128); + copy_size = (u32)strlen( sym_str) + 1; + ExportAdrEntry->name = (char*)(malloc( copy_size)); + //MI_CpuCopy8( sym_str, ExportAdrEntry->name, copy_size); + memcpy( ExportAdrEntry->name, sym_str, copy_size); + + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->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( EL_GetAdrEntry( ExportAdrEntry->name) == NULL) { //入ってなかったら + if( dbg_print_flag == 1) { + printf( "Add Entry : %s(0x%x), func=%d, thumb=%d\n", + ExportAdrEntry->name, + (int)(ExportAdrEntry->adr), + ExportAdrEntry->func_flag, + ExportAdrEntry->thumb_flag); + } + EL_AddAdrEntry( ExportAdrEntry); //登録 + } + } + } + /*----------------------------------------------------------------*/ + + /*------- ELSymExのリストを解放する -------*/ + CurrentSymEx = ElfHandle->SymEx; + if( CurrentSymEx) { + while( CurrentSymEx->next != NULL) { + FwdSymEx = CurrentSymEx; + CurrentSymEx = CurrentSymEx->next; + free( FwdSymEx); + } + ElfHandle->SymEx = NULL; + } + /*-----------------------------------------*/ + + /* 再配置完了後 */ + if( unresolved_num == 0) { + ElfHandle->process = EL_RELOCATED; + } +} + +/*------------------------------------------------------ + makelst専用関数 + シンボルセクションの中からGLOBALなものを + アドレステーブルに登録する + -----------------------------------------------------*/ +void ELi_DiscriminateGlobalSym( ELHandle* ElfHandle, u32 symsh_index) +{ + u32 i; + u32 num_of_sym; + Elf32_Shdr CurrentSymShdr; + Elf32_Shdr* SymShdr; //SYMセクションヘッダ + ELSymEx* CurrentSymEx; + ELSymEx* FwdSymEx; + ELSymEx DmySymEx; + ELShdrEx* CurrentShdrEx; + ELAdrEntry* ExportAdrEntry; + char sym_str[128]; + u32 copy_size; + + /*SYMセクションヘッダ取得*/ + ELi_GetShdr( ElfHandle, symsh_index, &CurrentSymShdr); + SymShdr = &CurrentSymShdr; + + num_of_sym = (SymShdr->sh_size) / (SymShdr->sh_entsize); //シンボルの全体数 + + /*---------- ELSymExのリストを作る ----------*/ + CurrentSymEx = &DmySymEx; + for( i=0; inext = (void*)(malloc( sizeof(ELSymEx))); + CurrentSymEx = (ELSymEx*)(CurrentSymEx->next); + + /*シンボルエントリをコピー*/ + ELi_GetEntry( ElfHandle, SymShdr, i, &(CurrentSymEx->Sym)); + + /*デバッグ情報フラグをセット*/ + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, CurrentSymEx->Sym.st_shndx); + if( CurrentShdrEx) { + CurrentSymEx->debug_flag = CurrentShdrEx->debug_flag; + }else{ + CurrentSymEx->debug_flag = 0; + } + +// printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx); + } + CurrentSymEx->next = NULL; + ElfHandle->SymEx = DmySymEx.next; + /*-------------------------------------------*/ + + /*----- ELSymExのThumbフラグをセット(関数シンボルだけ必要)-----*/ + CurrentSymEx = ElfHandle->SymEx; + for( i=0; iSym.st_info) == STT_FUNC) { + CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( ElfHandle, CurrentSymEx->Sym.st_shndx, + CurrentSymEx->Sym.st_value)); + }else{ + CurrentSymEx->thumb_flag = 0; + } + CurrentSymEx = CurrentSymEx->next; + } + /*---------------------------------------------------------------*/ + /*--- ライブラリ内のGLOBALシンボルをアドレステーブルに公開する ---*/ + for( i=0; iSymEx, i); + /*GLOBALで、かつ関連するセクションがライブラリ内に存在する場合*/ + if( ((ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_GLOBAL) || + (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_WEAK) || + (ELF32_ST_BIND( CurrentSymEx->Sym.st_info) == STB_MW_SPECIFIC))&& + (CurrentSymEx->Sym.st_shndx != SHN_UNDEF)) { + + ExportAdrEntry = (ELAdrEntry*)(malloc( sizeof(ELAdrEntry))); /*メモリ確保*/ + + ExportAdrEntry->next = NULL; + + ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, sym_str, 128); + copy_size = (u32)strlen( sym_str) + 1; + ExportAdrEntry->name = (char*)(malloc( copy_size)); + //MI_CpuCopy8( sym_str, ExportAdrEntry->name, copy_size); + memcpy( ExportAdrEntry->name, sym_str, copy_size); + + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->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( EL_GetAdrEntry( ExportAdrEntry->name) == NULL) { //入ってなかったら + if( dbg_print_flag == 1) { + printf( "Add Entry : %s(0x%x), func=%d, thumb=%d\n", + ExportAdrEntry->name, + (int)(ExportAdrEntry->adr), + ExportAdrEntry->func_flag, + ExportAdrEntry->thumb_flag); + } + EL_AddAdrEntry( ExportAdrEntry); //登録 + } + } + } + /*----------------------------------------------------------------*/ + + /*------- ELSymExのリストを解放する -------*/ + CurrentSymEx = ElfHandle->SymEx; + if( CurrentSymEx) { + while( CurrentSymEx->next != NULL) { + FwdSymEx = CurrentSymEx; + CurrentSymEx = CurrentSymEx->next; + free( FwdSymEx); + } + ElfHandle->SymEx = NULL; + } + /*-----------------------------------------*/ +} + + +/*------------------------------------------------------ + 未解決情報をもとにシンボルを解決する + + r_type,S_,A_,P_,T_が全て分かっている必要がある。 + -----------------------------------------------------*/ +#define _S_ (UnresolvedInfo->S_) +#define _A_ (UnresolvedInfo->A_) +#define _P_ (UnresolvedInfo->P_) +#define _T_ (UnresolvedInfo->T_) +u32 ELi_DoRelocate( ELUnresolvedEntry* UnresolvedInfo) +{ + s32 signed_val; + u32 relocation_val = 0; + u32 relocation_adr; + + 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_ = (((*(vu32*)relocation_adr)|0xFF800000) << 2); //一般的には-8になっているはず + } + 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: + relocation_val = (( _S_ + _A_) | _T_) - _P_; + *(vu32*)relocation_adr = relocation_val; + break; + case R_ARM_LDR_PC_G0: + 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_ = (((*(vu16*)relocation_adr & 0x07FF)<<11) + ((*((vu16*)(relocation_adr)+1)) & 0x07FF)); + _A_ = (_A_ | 0xFFC00000) << 1; //一般的には-4になっているはず(PCは現命令アドレス+4なので) + } + 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_THM_JUMP24: + break; + default: + if( dbg_print_flag == 1) { + printf( "ERROR! : unsupported relocation type!\n"); + } + break; + } + + return relocation_val; +} +#undef _S_ +#undef _A_ +#undef _P_ +#undef _T_ + +/*------------------------------------------------------ + リストから指定インデックスのELSymExを取り出す + -----------------------------------------------------*/ +ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index) +{ + u32 i; + ELSymEx* SymEx; + + SymEx = SymExStart; + for( i=0; inext); + if( SymEx == NULL) { + break; + } + } + return SymEx; +} + +/*------------------------------------------------------ + リストから指定インデックスのELShdrExを取り出す + -----------------------------------------------------*/ +ELShdrEx* ELi_GetShdrExfromList( 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 ELi_ShdrIsDebug( ELHandle* ElfHandle, u32 index) +{ + Elf32_Shdr TmpShdr; + char shstr[6]; + + /*-- セクション名の文字列を6文字取得 --*/ + ELi_GetShdr( ElfHandle, index, &TmpShdr); + ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx, + TmpShdr.sh_name, shstr, 6); + /*-------------------------------------*/ + + if( strncmp( shstr, ".debug", 6) == 0) { /*デバッグセクションの場合*/ + return TRUE; + }else{ /*デバッグセクションに関する再配置セクションの場合*/ + if( (TmpShdr.sh_type == SHT_REL) || (TmpShdr.sh_type == SHT_RELA)) { + if( ELi_ShdrIsDebug( ElfHandle, TmpShdr.sh_info) == TRUE) { + return TRUE; + } + } + } + + return FALSE; +} + + + +/*------------------------------------------------------ + ElfHandleのSymExテーブルを調べ、指定インデックスの + 指定オフセットにあるコードがARMかTHUMBかを判定する。 + (予め ElfHandle->SymShdr と ElfHandle->SymEx を設定しておくこと) + + sh_index : 調べたいセクションインデックス + offset : 調べたいセクション内のオフセット + -----------------------------------------------------*/ +u32 ELi_CodeIsThumb( ELHandle* ElfHandle, u16 sh_index, u32 offset) +{ + u32 i; + u32 thumb_flag; + Elf32_Shdr* SymShdr; + char str_adr[3]; + ELSymEx* CurrentSymEx; + + /*シンボルのセクションヘッダとSymExリスト取得*/ + SymShdr = &(ElfHandle->SymShdr); + CurrentSymEx = ElfHandle->SymEx; + + i = 0; + thumb_flag = 0; + while( CurrentSymEx != NULL) { + + if( CurrentSymEx->Sym.st_shndx == sh_index) { + ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, str_adr, 3); + if( strncmp( str_adr, "$a\0", strlen("$a\0")) == 0) { + thumb_flag = 0; + }else if( strncmp( str_adr, "$t\0", strlen("$t\0")) == 0) { + thumb_flag = 1; + } + if( CurrentSymEx->Sym.st_value > offset) { + break; + } + } + + CurrentSymEx = CurrentSymEx->next; + i++; + } + + return thumb_flag; +} + + +/*--------------------------------------------------------- + 未解決情報エントリを初期化する + --------------------------------------------------------*/ +void ELi_UnresolvedInfoInit( 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; +} + +/*------------------------------------------------------ + 未解決情報テーブルからエントリを削除する + -----------------------------------------------------*/ +BOOL ELi_RemoveUnresolvedEntry( ELUnresolvedEntry* UnrEnt) +{ + ELUnresolvedEntry DmyUnrEnt; + ELUnresolvedEntry* CurrentUnrEnt; + + if( UnrEnt == NULL) { + return FALSE; + } + + DmyUnrEnt.next = ELUnrEntStart; + CurrentUnrEnt = &DmyUnrEnt; + + while( CurrentUnrEnt->next != UnrEnt) { + if( CurrentUnrEnt->next == NULL) { + return FALSE; + }else{ + CurrentUnrEnt = (ELUnresolvedEntry*)(CurrentUnrEnt->next); + } + } + + CurrentUnrEnt->next = UnrEnt->next; + free( UnrEnt->sym_str); + free( UnrEnt); + ELUnrEntStart = DmyUnrEnt.next; + + return TRUE; +} + +/*--------------------------------------------------------- + 未解決情報テーブルにエントリを追加する + --------------------------------------------------------*/ +void ELi_AddUnresolvedEntry( 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; +} + +/*------------------------------------------------------ + 未解決情報テーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ELUnresolvedEntry* ELi_GetUnresolvedEntry( char* ent_name) +{ + ELUnresolvedEntry* CurrentUnrEnt; + + CurrentUnrEnt = ELUnrEntStart; + if( CurrentUnrEnt == NULL) { + return NULL; + } + while( 1) { + if( (strcmp( CurrentUnrEnt->sym_str, ent_name) == 0)&& + (CurrentUnrEnt->remove_flag == 0)) { + break; + } + CurrentUnrEnt = (ELUnresolvedEntry*)CurrentUnrEnt->next; + if( CurrentUnrEnt == NULL) { + break; + } + } + return CurrentUnrEnt; +} diff --git a/tools/makelst/loader_subset.h b/tools/makelst/loader_subset.h new file mode 100644 index 0000000..e1f91f7 --- /dev/null +++ b/tools/makelst/loader_subset.h @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------* + Project: CTR - ELF Loader + File: loader_subset.h + + Copyright 2006 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 "types.h" +#include "elf.h" +#include "elf_loader.h" + + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopySectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + セクションをバッファに確保する(コピーしない) + -----------------------------------------------------*/ +void* ELi_AllocSectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + 指定インデックスのセクションヘッダをバッファに取得する + -----------------------------------------------------*/ +void ELi_GetShdr( ELHandle* ElfHandle, u32 index, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + 指定インデックスのセクションのエントリをバッファに取得する + -----------------------------------------------------*/ +void ELi_GetSent( ELHandle* ElfHandle, u32 index, void* entry_buf, u32 offset, u32 size); + + +/*------------------------------------------------------ + 指定セクションヘッダの指定インデックスのエントリをバッファに取得する + (エントリサイズが固定のセクションのみ) + -----------------------------------------------------*/ +void ELi_GetEntry( ELHandle* ElfHandle, Elf32_Shdr* Shdr, u32 index, void* entry_buf); + + +/*------------------------------------------------------ + STRセクションヘッダの指定インデックスの文字列を取得する + -----------------------------------------------------*/ +void ELi_GetStrAdr( ELHandle* ElfHandle, u32 strsh_index, u32 ent_index, char* str, u32 len); + + +/*------------------------------------------------------ + シンボルを再定義する + -----------------------------------------------------*/ +void ELi_RelocateSym( ELHandle* ElfHandle, u32 relsh_index); + + +/*------------------------------------------------------ + makelst専用関数 + シンボルセクションの中からGLOBALなものを + アドレステーブルに登録する + -----------------------------------------------------*/ +void ELi_DiscriminateGlobalSym( ELHandle* ElfHandle, u32 symsh_index); + + +/*------------------------------------------------------ + 未解決情報をもとにシンボルを解決する + -----------------------------------------------------*/ +u32 ELi_DoRelocate( ELUnresolvedEntry* UnresolvedInfo); + + +/*------------------------------------------------------ + リストから指定インデックスのELSymExを取り出す + -----------------------------------------------------*/ +ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index); + + +/*------------------------------------------------------ + リストから指定インデックスのELShdrExを取り出す + -----------------------------------------------------*/ +ELShdrEx* ELi_GetShdrExfromList( ELShdrEx* ShdrExStart, u32 index); + + +/*------------------------------------------------------ + 指定インデックスのセクションがデバッグ情報かどうか判定する + -----------------------------------------------------*/ +BOOL ELi_ShdrIsDebug( ELHandle* ElfHandle, u32 index); + + +/*------------------------------------------------------ + ElfHandleのSymExテーブルを調べ、指定インデックスの + 指定オフセットにあるコードがARMかTHUMBかを判定する + -----------------------------------------------------*/ +u32 ELi_CodeIsThumb( ELHandle* ElfHandle, u16 sh_index, u32 offset); + + +/*--------------------------------------------------------- + 未解決情報エントリを初期化する + --------------------------------------------------------*/ +void ELi_UnresolvedInfoInit( ELUnresolvedEntry* UnresolvedInfo); + + +/*------------------------------------------------------ + 未解決情報テーブルからエントリを削除する + -----------------------------------------------------*/ +BOOL ELi_RemoveUnresolvedEntry( ELUnresolvedEntry* UnrEnt); + + +/*--------------------------------------------------------- + 未解決情報テーブルにエントリを追加する + --------------------------------------------------------*/ +void ELi_AddUnresolvedEntry( ELUnresolvedEntry* UnrEnt); + + +/*------------------------------------------------------ + 未解決情報テーブルから指定文字列に該当するエントリを探す + -----------------------------------------------------*/ +ELUnresolvedEntry* ELi_GetUnresolvedEntry( char* ent_name); + + +#endif /*_LOADER_SUBSET_H_*/ diff --git a/tools/makelst/makelst.c b/tools/makelst/makelst.c new file mode 100644 index 0000000..10b43b5 --- /dev/null +++ b/tools/makelst/makelst.c @@ -0,0 +1,279 @@ +/*---------------------------------------------------------------------------* + Project: tools - makedsrom + File: makesdrom.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. + + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include +#include +#include // getopt() +#include "version.h" +#include "types.h" +#include "elf.h" +#include "elf_loader.h" +#include "searcharg.h" + + + +#define DS_ROM_HEADER_SIZE 0x4000 + +char c_source_line_str[256]; + +#define C_SOURCE_FILENAME "staticsymlist.c" +FILE* CSourceFilep; + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +u32 adr_ALIGN( u32 addr, u32 align_size); +void file_write( char* c_str, FILE* Fp); + + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +u16 dbg_print_flag; +u16 unresolved_table_block_flag = 0; + +/*---------------------------------------------------------------------------* + * MAIN + *---------------------------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + int i; + FILE *FHp; + u32 binbuf[4]; + ELHandle ElfH; + char* c_filename; + SAArgInfo ArgInfo; + u16 result; + +// printf( "binbuf : %x\n", binbuf); +/* + for( i=0; iNameList->name); + exit( 0); + } + + /*不正オプションチェック*/ + CurrentOptList = ArgInfo.OptList; + for( i=0; i<(ArgInfo.opt_num); i++) { + if( ( strcmp(CurrentOptList->opt_name, "\0" ) != 0) && + ( strcmp(CurrentOptList->opt_name, "-d\0" ) != 0) && + ( strcmp(CurrentOptList->opt_name, "-o\0" ) != 0) && + ( strcmp(CurrentOptList->opt_name, "-dll\0" ) != 0) && + ( strcmp(CurrentOptList->opt_name, "-static\0") != 0)) { + printf( "invalid option (%s)\n", CurrentOptList->opt_name); + exit( 0); + } + CurrentOptList = CurrentOptList->next; + } + } + /*--------------------------------------*/ + + EL_Init(); + unresolved_table_block_flag = 0; //Unresolvedテーブルへの追加禁止を解除 + /*----------- -dllオプション解析 ----------------*/ + { + SAOptList* CurrentOptList; + SANameList* CurrentNameList; + CurrentOptList = SA_IsThereOpt( &ArgInfo, "-dll\0"); + + if( CurrentOptList) { + + if( CurrentOptList->name_num == 0) { + printf( "no input dll file(s).\n"); + exit( 0); + } + + CurrentNameList = CurrentOptList->NameList; + for( i=0; i<(CurrentOptList->name_num); i++) { + FHp = fopen( CurrentNameList->name, "rb"); + if( FHp == NULL) { + printf( "cannot open file \"%s\".\n", CurrentNameList->name); + exit( 1); + } + EL_InitHandle( &ElfH); + result = EL_LoadLibraryfromFile( &ElfH, FHp, binbuf); + fclose( FHp); + + CurrentNameList = CurrentNameList->next; + } + }else{ + printf( "no input dll file(s).\n"); + exit( 0); + } + } + /*-----------------------------------------------*/ + + EL_ResolveAllLibrary(); + + + /*------------- -sオプション解析 --------------*/ + unresolved_table_block_flag = 1; //Unresolvedテーブルに追加しないようにする + { + SAOptList* CurrentOptList; + SANameList* CurrentNameList; + CurrentOptList = SA_IsThereOpt( &ArgInfo, "-static\0"); + + if( CurrentOptList) { + + if( CurrentOptList->name_num == 0) { + printf( "no input static file(s).\n"); + exit( 0); + } + + CurrentNameList = CurrentOptList->NameList; + for( i=0; i<(CurrentOptList->name_num); i++) { + FHp = fopen( CurrentNameList->name, "rb"); + if( FHp == NULL) { + printf( "cannot open file \"%s\".\n", CurrentNameList->name); + exit( 1); + } + EL_InitHandle( &ElfH); + result = EL_LoadLibraryfromFile( &ElfH, FHp, binbuf); + fclose( FHp); + + CurrentNameList = CurrentNameList->next; + } + }else{ + printf( "no input static file(s).\n"); + exit( 0); + } + } + /*---------------------------------------------*/ + + + /*仮のCソースファイル名生成*/ + c_filename = malloc( strlen( C_SOURCE_FILENAME)); + strcpy( c_filename, C_SOURCE_FILENAME); + /*-o オプションがあれば指定ファイル名に変更*/ + { + SAOptList* CurrentOptList; + SANameList* CurrentNameList; + CurrentOptList = SA_IsThereOpt( &ArgInfo, "-o\0"); + + if( CurrentOptList) { + if( CurrentOptList->name_num != 0) { + CurrentNameList = CurrentOptList->NameList; + c_filename = CurrentNameList->name; + }else{ + printf( "error : no filename after \"-o\" option.\n\n"); + exit( 1); + } + } + } + + CSourceFilep = fopen( c_filename, "w"); + if( !CSourceFilep) { + printf( "error : cannot create file \"%s\".\n\n", c_filename); + exit( 1); + } + file_write( "/*This file generated automatically by the \"makelst\".*/\n", CSourceFilep); + file_write( "\n", CSourceFilep); + file_write( "#ifndef __STATIC_SYM_LIST__\n", CSourceFilep); + file_write( "#define __STATIC_SYM_LIST__\n", CSourceFilep); + file_write( "\n", CSourceFilep); + file_write( "#include \n", CSourceFilep); + file_write( "#include \n", CSourceFilep); + file_write( "\n", CSourceFilep); + + EL_ResolveAllLibrary(); //抽出シンボルのマーキング + EL_ExtractStaticSym1(); //構造体設定部分 + file_write( "\n\n", CSourceFilep); + + file_write( "/*--------------------------------\n", CSourceFilep); + file_write( " API\n", CSourceFilep); + file_write( " --------------------------------*/\n", CSourceFilep); + file_write( "void elAddStaticSym( void)\n", CSourceFilep); + file_write( "{\n", CSourceFilep); + EL_ExtractStaticSym2(); //API呼び出し部分 + file_write( "}\n", CSourceFilep); + + unresolved_table_block_flag = 0; //Unresolvedテーブルへの追加禁止を解除 + + file_write( "\n", CSourceFilep); + file_write( "#endif /*__STATIC_SYM_LIST__*/\n", CSourceFilep); + fclose( CSourceFilep); + /*---------------------------------------------*/ + + printf( "\"C\" source file \"%s\" is generated.\n\n", c_filename); + exit( 0); + + /*-----------------------------------------------------*/ + + return 0; +} + +/*---------------------------------------------------------------------------* + * アドレスのアラインメント + *---------------------------------------------------------------------------*/ +u32 adr_ALIGN( 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; +} + +/*---------------------------------------------------------------------------* + * ファイルに文字列を書き込み + *---------------------------------------------------------------------------*/ +void file_write( char* c_str, FILE* Fp) +{ + fwrite( c_str, 1, strlen( c_str), Fp); +} diff --git a/tools/makelst/readme.txt b/tools/makelst/readme.txt new file mode 100644 index 0000000..c317a4f --- /dev/null +++ b/tools/makelst/readme.txt @@ -0,0 +1,7 @@ + +・makelst + +DLL側とstatic側のelfファイルを入力すると、 +static側シンボルをDLLローダーに渡すAPIをCソースとして生成します。 +このCソースファイルはstatic側に含めてリンクしてください。 + diff --git a/tools/makelst/searcharg.c b/tools/makelst/searcharg.c new file mode 100644 index 0000000..a2c0dea --- /dev/null +++ b/tools/makelst/searcharg.c @@ -0,0 +1,190 @@ + +#include +#include +#include + +#include "searcharg.h" + +/* +char* opt[7]; +char* opt_arg[7]; +char* arg[7]; + +int opt_num; +int arg_num; +*/ +char opt_name_null[1] = { '\0'}; + +static void SA_insertOpt( SAArgInfo* ArgInfo, char* opt_name); +static void SA_insertName( SAArgInfo* ArgInfo, char* name); + + +/*引数を解析する*/ +void SA_searchopt( SAArgInfo* ArgInfo, int argc, char* argv[]) +{ + int i; + + /* 0で初期化 */ + memset( ArgInfo, 0, sizeof( SAArgInfo)); + + for( i=1; iOptList; + for( i=0; i<(ArgInfo->opt_num); i++) { + if( strcmp( CurrentOptList->opt_name, opt_name) == 0) { + return( CurrentOptList); + } + CurrentOptList = CurrentOptList->next; + } + return( NULL); +} + +/*引数の解析結果を表示する*/ +void SA_printf( SAArgInfo* ArgInfo) +{ + int i, j; + SAOptList* CurrentOptList; + SANameList* CurrentNameList; + + CurrentOptList = (SAOptList*)(ArgInfo->OptList); + printf( "opt_num = %d\n", ArgInfo->opt_num); + + for( i=0; i<(ArgInfo->opt_num); i++) { + + CurrentNameList = (SANameList*)(CurrentOptList->NameList); + printf( "option[%s] ...", CurrentOptList->opt_name); + + for( j=0; j<(CurrentOptList->name_num); j++) { + printf( " %s", CurrentNameList->name); + CurrentNameList = CurrentNameList->next; + } + printf( "\n"); + + CurrentOptList = CurrentOptList->next; + } +} + +/**/ +static void SA_insertOpt( SAArgInfo* ArgInfo, char* opt_name) +{ + SAOptList DmyOptList; + SAOptList* CurrentOptList; + + DmyOptList.next = ArgInfo->OptList; + CurrentOptList = &DmyOptList; + while( (CurrentOptList->next) != NULL) { + CurrentOptList = (SAOptList*)(CurrentOptList->next); + } + CurrentOptList->next = (SAOptList*)malloc( sizeof( SAOptList)); + CurrentOptList = CurrentOptList->next; + /*--- 構築 ---*/ + CurrentOptList->opt_name = opt_name; + CurrentOptList->name_num = 0; + CurrentOptList->NameList = NULL; + CurrentOptList->next = NULL; + /*------------*/ + ArgInfo->opt_num++; + + if( ArgInfo->OptList == NULL) { + ArgInfo->OptList = CurrentOptList; + } +} + +/**/ +static void SA_insertName( SAArgInfo* ArgInfo, char* name) +{ + SAOptList DmyOptList; + SAOptList* CurrentOptList; + SANameList DmyNameList; + SANameList* CurrentNameList; + + /*単独で見つかった場合はNULL文字のオプションに属させる*/ + if( ArgInfo->OptList == NULL) { + SA_insertOpt( ArgInfo, opt_name_null); + } + + DmyOptList.next = ArgInfo->OptList; + CurrentOptList = &DmyOptList; + while( (CurrentOptList->next) != NULL) { + CurrentOptList = (SAOptList*)(CurrentOptList->next); + } + + DmyNameList.next = CurrentOptList->NameList; + CurrentNameList = &(DmyNameList); + while( (CurrentNameList->next) != NULL) { + CurrentNameList = (SANameList*)(CurrentNameList->next); + } + + CurrentNameList->next = (SANameList*)malloc( sizeof( SANameList)); + CurrentNameList = CurrentNameList->next; + CurrentNameList->name = name; + CurrentNameList->next = NULL; + CurrentOptList->name_num++; + + if( CurrentOptList->NameList == NULL) { + CurrentOptList->NameList = CurrentNameList; + } +} + + +/* +void SA_searchopt( SAArgList* ArgList, int argc, char* argv[]) +{ + int i, j, k; + + j = 0; + k = 0; + for( i=1; iopt[j] = malloc( strlen( argv[i])+1); + strcpy( ArgList->opt[j], argv[i]); + if( i+1 == argc) { + j++; + break; + } + if( strncmp( argv[i+1], "-", 1) != 0) { + i++; + ArgList->opt_arg[j] = malloc( strlen( argv[i])+1); + strcpy( ArgList->opt_arg[j], argv[i]); + } + j++; + }else{ + ArgList->arg[k] = malloc( strlen( argv[i])+1); + strcpy( ArgList->arg[k], argv[i]); + k++; + } + } + ArgList->opt_num = j; + ArgList->arg_num = k; + + printf( "argc num : %x\n", argc); + printf( "opt num : %x, arg num : %x\n", j, k); + for( i=0; iopt[i], ArgList->opt_arg[i]); + } + for( i=0; iarg[i]); + } +} +*/ +void portoption( void) +{ +// if( k != 2) { + printf( "error : too few input files.\n\n"); +// } +} diff --git a/tools/makelst/searcharg.h b/tools/makelst/searcharg.h new file mode 100644 index 0000000..1cdaadd --- /dev/null +++ b/tools/makelst/searcharg.h @@ -0,0 +1,55 @@ + +#ifndef __SEARCH_ARG__ +#define __SEARCH_ARG__ + + + +typedef struct +{ + char* opt[7]; + char* opt_arg[7]; + char* arg[7]; + int opt_num; + int arg_num; +}SAArgList; + + +/**/ +typedef struct +{ + void* next; + char* name; +}SANameList; + +typedef struct +{ + void* next; + char* opt_name; + SANameList* NameList; + int name_num; +}SAOptList; + + +typedef struct +{ + SAOptList* OptList; + int opt_num; +}SAArgInfo; + + + +/*引数を解析する*/ +void SA_searchopt( SAArgInfo* ArgInfo, int argc, char* argv[]); + +/*オプション文字列が存在すれば構造体のアドレスを返す*/ +SAOptList* SA_IsThereOpt( SAArgInfo* ArgInfo, char* opt_name); + +/*引数の解析結果を表示する*/ +void SA_printf( SAArgInfo* ArgInfo); + + + +//void SA_searchopt( SAArgList* ArgList, int argc, char* argv[]); + + +#endif /*__SEARCH_ARG__*/ diff --git a/tools/makelst/types.h b/tools/makelst/types.h new file mode 100644 index 0000000..298be7f --- /dev/null +++ b/tools/makelst/types.h @@ -0,0 +1,228 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - - types definition + File: types.h + + Copyright 2003-2006 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: types.h,v $ + Revision 1.38 2006/03/17 00:33:54 yosizaki + support SDK_FORCE_EXPORT + + Revision 1.37 2006/02/24 00:53:29 yosizaki + move position of SDK_INLINE definition. + + Revision 1.36 2006/01/18 02:12:28 kitase_hirotake + do-indent + + Revision 1.35 2005/11/14 05:17:25 okubata_ryoma + 微修正 + + Revision 1.33 2005/09/05 01:39:14 yasu + SDK_BOOL_ALREADY_DEFINED_ の追加 + + Revision 1.32 2005/06/23 12:16:27 yasu + SDK_LITTLE_ENDIAN 定義の追加 + + Revision 1.31 2005/03/04 10:13:03 yasu + コンパイラ依存部分を条件分け + + Revision 1.30 2005/03/01 01:57:00 yosizaki + copyright の年を修正. + + Revision 1.29 2005/02/28 05:26:02 yosizaki + do-indent. + + Revision 1.28 2004/08/03 03:14:29 yasu + Fix comment + + Revision 1.27 2004/05/14 11:57:44 takano_makoto + Add option SDK_HAS_NO_LONG_LONG_INT_ for environment of VC or BCB. + + Revision 1.26 2004/04/23 04:24:14 yada + add comment for ATTRIBUTE_ALIGN + + Revision 1.25 2004/04/23 04:14:31 yada + add ATTRIBUTE_ALIGN + + Revision 1.24 2004/02/05 07:09:03 yasu + change SDK prefix iris -> nitro + + Revision 1.23 2004/01/29 08:47:04 nishida_kenji + Change typedefs for better type check. + s32: signed int -> signed long + u32: unsigned int -> unsigned long + BOOL: s32 -> int + + Revision 1.22 2004/01/05 04:11:16 nishida_kenji + add f32, vf32 + + Revision 1.21 2003/12/02 12:09:22 yasu + アセンブラの組み込みプリプロセッサが # をコメント視してしまうことの対処 + + Revision 1.20 2003/11/27 06:35:17 yada + comment訂正 + + Revision 1.19 2003/11/11 09:14:41 nishida_kenji + RegTypeNNv型をtypedef + + Revision 1.18 2003/11/11 06:10:18 nishida_kenji + 固定小数や行列をgx/gxcommon.hに移動 + + Revision 1.17 2003/11/11 05:46:19 yada + BOOL, TRUE, FALSE を追加。INLINE, SDK_ASSERT() を分離。 + + Revision 1.16 2003/11/11 04:12:52 nishida_kenji + fx16rsの追加 + + Revision 1.15 2003/11/05 07:40:40 yasu + VecFx16 の padding 警告を黙らせた + + Revision 1.14 2003/11/04 12:04:59 yasu + aligned の追加 ただし CW のみ + + Revision 1.13 2003/11/04 11:45:20 yasu + NULL などの追加 + + Revision 1.12 2003/11/04 09:37:03 yada + REG_BASE 外しました。 + + Revision 1.11 2003/11/04 04:52:20 Nishida_Kenji + ビットフィールドを止める + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef NITRO_TYPES_H_ +#define NITRO_TYPES_H_ + +// Endian +#define SDK_LITTLE_ENDIAN +#define SDK_IS_LITTLE_ENDIAN 1 +#define SDK_IS_BIG_ENDIAN 0 + +#ifdef SDK_ASM +#else //SDK_ASM + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long u32; + +#ifdef SDK_HAS_NO_LONG_LONG_INT_ +typedef unsigned __int64 u64; +#else +typedef unsigned long long int u64; +#endif + +typedef signed char s8; +typedef signed short int s16; +typedef signed long s32; + +#ifdef SDK_HAS_NO_LONG_LONG_INT_ +typedef signed __int64 s64; +#else +typedef signed long long int s64; +#endif + +typedef volatile u8 vu8; +typedef volatile u16 vu16; +typedef volatile u32 vu32; +typedef volatile u64 vu64; + +typedef volatile s8 vs8; +typedef volatile s16 vs16; +typedef volatile s32 vs32; +typedef volatile s64 vs64; + +typedef float f32; +typedef volatile f32 vf32; + +/* + io_register_list_XX.hで使用するマクロと型 + */ + +typedef u8 REGType8; +typedef u16 REGType16; +typedef u32 REGType32; +typedef u64 REGType64; + +typedef vu8 REGType8v; +typedef vu16 REGType16v; +typedef vu32 REGType32v; +typedef vu64 REGType64v; + + +#ifndef SDK_BOOL_ALREADY_DEFINED_ +#ifndef BOOL +typedef int BOOL; +#endif //BOOL +#endif //SDK_ALREAD_DEFINE_BOOL_ + +#ifndef TRUE +// Any non zero value is considered TRUE +#define TRUE 1 +#endif //TRUE + +#ifndef FALSE +#define FALSE 0 +#endif // FALSE + + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else // __cplusplus +#define NULL ((void *)0) +#endif // __cplusplus +#endif // NULL + +// for compatibility with GAMECUBE +#if defined(SDK_CW) || defined(__MWERKS__) +#ifndef ATTRIBUTE_ALIGN +#define ATTRIBUTE_ALIGN(num) __attribute__ ((aligned(num))) +#endif +#endif + +// Weak symbol +#if defined(SDK_CW) || defined(__MWERKS__) +#define SDK_WEAK_SYMBOL __declspec(weak) +#elif defined(SDK_PRODG) +#define SDK_WEAK_SYMBOL +#endif + +/* option for the compiler which deals dead-strip */ +#ifdef SDK_CW_FORCE_EXPORT_SUPPORT +#define SDK_FORCE_EXPORT __declspec(force_export) +#else +#define SDK_FORCE_EXPORT +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif //SDK_ASM + + +/* static inline を inline にして、コードサイズを削減したい場合は、マクロ SDK_INLINE を変更してください。 + (static inline を inline にした関数に宣言がある場合は、SDK_DECL_INLINE も変更してください。) + 変更した場合はライブラリを再ビルドしてください。 + + ただし、inline 関数の実体化の不具合が修正されたバージョンのコンパイラを使用していて + その不具合を回避するために inline を static inline にしていた関数の場合のみ + このマクロを使用して static inline を inline に変更するとコードサイズを削減することができます。 + + 注意:このマクロは現段階では、FX_, VEC_, MTX_ シリーズのみ有効となっています。*/ +#define SDK_INLINE static inline +#define SDK_DECL_INLINE static + + +/* NITRO_TYPES_H_ */ +#endif diff --git a/tools/makelst/version.h b/tools/makelst/version.h new file mode 100644 index 0000000..155e84d --- /dev/null +++ b/tools/makelst/version.h @@ -0,0 +1 @@ +#define SDK_DATE_OF_LATEST_FILE 20060905UL