diff --git a/tools/stripdebug/Makefile b/tools/stripdebug/Makefile new file mode 100644 index 0000000..fcd26dd --- /dev/null +++ b/tools/stripdebug/Makefile @@ -0,0 +1,48 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: NitroSDK - tools - stripdebug +# 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 = stripdebug.exe + +SOURCES_C = stripdebug.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/stripdebug/arch.c b/tools/stripdebug/arch.c new file mode 100644 index 0000000..99f7457 --- /dev/null +++ b/tools/stripdebug/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/stripdebug/arch.h b/tools/stripdebug/arch.h new file mode 100644 index 0000000..e853787 --- /dev/null +++ b/tools/stripdebug/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/stripdebug/elf.c b/tools/stripdebug/elf.c new file mode 100644 index 0000000..bf8348e --- /dev/null +++ b/tools/stripdebug/elf.c @@ -0,0 +1,340 @@ + +#include "types.h" + +#include "elf.h" +#include +#include +#include + +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/stripdebug/elf.h b/tools/stripdebug/elf.h new file mode 100644 index 0000000..6bdc904 --- /dev/null +++ b/tools/stripdebug/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/stripdebug/elf_loader.c b/tools/stripdebug/elf_loader.c new file mode 100644 index 0000000..8991495 --- /dev/null +++ b/tools/stripdebug/elf_loader.c @@ -0,0 +1,882 @@ +/*---------------------------------------------------------------------------* + Project: TWL - 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 "types.h" +#include "elf.h" +#include "elf_loader.h" +#include "arch.h" +#include "loader_subset.h" +#include +#include + + +//OSHeapHandle EL_Heap; +ELAdrEntry* ELAdrEntStart = NULL; +ELUnresolvedEntry* ELUnrEntStart = NULL; + +extern u16 dbg_print_flag; +extern u32 unresolved_table_block_flag; +extern u32 ELi_ALIGN( u32 addr, u32 align_size); + +#define MAKELST_DS_API " elAddAdrEntry" //DS上でアドレステーブルに追加するAPI関数名 + +extern char c_source_line_str[256]; +extern FILE* NewElfFilep; + + +/*------------------------------------------------------ + ローカル関数の宣言 + -----------------------------------------------------*/ +// 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); + + + +/*hex値を10進の文字列で表現する*/ +void ELi_SetDecSize( char* dec, u32 hex) +{ + u16 i; + u32 tmp = 1000000000; + u16 ptr = 0; + + memset( dec, 0x20, 10); + for( i=0; i<10; i++) { + if( ((hex / tmp) != 0) || (ptr != 0)) { + dec[ptr++] = 0x30 + (hex/tmp); + hex -= (hex/tmp) * tmp; + } + tmp /= 10; + } +} + + + +/*--------------------------------------------------------- + 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 new_image_pointer; + u32 arch_size; + u32 elf_num = 0; /*ELFオブジェクトの数*/ + u32 newarch_size = 0; + 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; /*最初のエントリへ*/ + + + new_image_pointer = (u32)buf; + memcpy( buf, OBJMAG, 8); //stripped elfにコピー + new_image_pointer += 8; + newarch_size += 8; + + + ElfHandle->buf_current = new_image_pointer; + 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++; + ElfHandle->ELi_ReadStub( new_image_pointer, ElfHandle->FileStruct, (u32)(obj_image), + image_pointer, arch_size); //arヘッダをstripped elfにコピー + result = ELi_LoadObject( ElfHandle, (void*)(image_pointer+arch_size), + new_image_pointer + arch_size); +// (ElfHandle->buf_current + arch_size)); + + ELi_SetDecSize( (char*)(((ArchHdr*)new_image_pointer)->ar_size), ElfHandle->newelf_size); //archヘッダのサイズ更新 + new_image_pointer += (ElfHandle->newelf_size + arch_size); + newarch_size += (ElfHandle->newelf_size + arch_size); + + if( result < all_result) { /*悪い結果のときだけall_resultに反映*/ + all_result = result; + } + /*初期値の設定*/ + ElfHandle->ShdrEx = NULL; + ElfHandle->SymEx = NULL; + ElfHandle->process = EL_INITIALIZED; /*フラグの設定*/ + }else{ + ElfHandle->ELi_ReadStub( new_image_pointer, ElfHandle->FileStruct, (u32)(obj_image), + image_pointer, arch_size+AR_GetEntrySize( &ArHdr)); //arヘッダとエントリをstripped elfにコピー + + new_image_pointer += (AR_GetEntrySize( &ArHdr) + arch_size); + newarch_size += (AR_GetEntrySize( &ArHdr) + arch_size); + } + /*次のエントリへ*/ + ElfHandle->ELi_ReadStub( &ArHdr, ElfHandle->FileStruct, (u32)(obj_image), image_pointer, arch_size); + image_pointer += arch_size + AR_GetEntrySize( &ArHdr); + } + ElfHandle->newelf_size = newarch_size; + }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; //デバッグプリント用 + u32 newelf_shoff = 0; //stripped elfイメージへの書き込みポインタ + u32 buf_shdr; + u32 section_num = 0; + u32 newelf_size; + u32 tmp_buf; + u32 *shdr_table; //セクションヘッダ新旧番号対応テーブル + u32 *sym_table; //シンボルエントリ新旧番号対応テーブル + + /* 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 = (u32)buf + sizeof( Elf32_Ehdr); + ElfHandle->shentsize = ElfHandle->CurrentEhdr.e_shentsize; + + /*セクションヘッダテーブル構築*/ + shdr_table = (u32*)malloc( 4 * ElfHandle->CurrentEhdr.e_shnum); + + + /*---------- ELShdrExのリストとshdr_tableを作る ----------*/ + 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; + shdr_table[i] = 0xFFFFFFFF; + }else{ /*デバッグ情報でない場合*/ + /*セクションヘッダをコピー*/ + ELi_GetShdr( ElfHandle, i, &(CurrentShdrEx->Shdr)); + CurrentShdrEx->debug_flag = 0; + shdr_table[i] = section_num; /*セクション新旧テーブル作成*/ +// printf( "shdr_table[0x%x] = 0x%x\n", i, section_num); + section_num++; + /*セクション文字列を取得しておく*/ + CurrentShdrEx->str = (char*)malloc( 128); //128文字バッファ取得 + ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx, + CurrentShdrEx->Shdr.sh_name, + CurrentShdrEx->str, 128); + } + } + 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 = ELi_ALIGN( (u32)(ElfHandle->buf_current), 4); +/* 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)); + }*/ + //シンボルテーブルセクション + else if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) { + ELi_BuildSymList( ElfHandle, i, &(CurrentShdrEx->sym_table)); //シンボルリスト作成 + { + ELSymEx* CurrentSymEx; + ELShdrEx* StrShEx; //文字列セクション + char symstr[128]; + u32 symbol_num = 0; + + /*--- シンボルエントリのデータを修正 ---*/ + CurrentSymEx = ElfHandle->SymEx; + while( CurrentSymEx != NULL) { //SymExをたどればデバッグシンボルは含まれない + /*文字列セクション取得*/ + StrShEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, + CurrentShdrEx->Shdr.sh_link); + /*--- 文字列セクションの中身構築 ---*/ + ELi_GetStrAdr( ElfHandle, CurrentShdrEx->Shdr.sh_link, //シンボル文字列取得 + CurrentSymEx->Sym.st_name, + symstr, 128); + + StrShEx->str_table = realloc( StrShEx->str_table, //シンボル文字列追加 + (StrShEx->str_table_size) + + strlen( symstr) + 1); + strcpy( (u8*)((u32)StrShEx->str_table + StrShEx->str_table_size), + symstr); + + CurrentSymEx->Sym.st_name = StrShEx->str_table_size; //シンボルエントリのデータを修正 + + StrShEx->str_table_size += ( strlen( symstr) + 1); + /*---------------------------------*/ + symbol_num++; + + CurrentSymEx->Sym.st_shndx = shdr_table[CurrentSymEx->Sym.st_shndx]; //シンボルエントリの対象セクション番号更新 + CurrentSymEx = CurrentSymEx->next; + }/*-------------------------------------*/ + + /*--- シンボルテーブルセクションヘッダの更新 ---*/ + CurrentShdrEx->loaded_adr = ELi_CopySymToBuffer( ElfHandle); + CurrentShdrEx->Shdr.sh_link = shdr_table[CurrentShdrEx->Shdr.sh_link]; //文字列セクション番号更新 + CurrentShdrEx->Shdr.sh_size = symbol_num * sizeof( Elf32_Sym); + /*----------------------------------------------*/ + } + ELi_FreeSymList( ElfHandle, CurrentShdrEx->sym_table); //シンボルリスト開放 + } + +/* printf( "section %02x relocated at %08x\n", + i, CurrentShdrEx->loaded_adr);*/ + } + } + + /*---------- REL, RELA, STRTABセクションの処理 ----------*/ + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + // + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + + if( CurrentShdrEx->debug_flag == 1) { //デバッグ情報の場合 + }else{ //デバッグ情報でない場合 + //RELセクション + if( CurrentShdrEx->Shdr.sh_type == SHT_REL) { + CurrentShdrEx->loaded_adr = (u32) + ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + { + Elf32_Rel* CurrentRel; + ELShdrEx* SymShdrEx; + u32 new_sym_num; + /*シンボルセクション取得*/ + SymShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, + CurrentShdrEx->Shdr.sh_link); + /*コピー先のRelセクションを修正*/ + for( j=0; j<(CurrentShdrEx->Shdr.sh_size/CurrentShdrEx->Shdr.sh_entsize); j++) { + CurrentRel = (Elf32_Rel*)(CurrentShdrEx->loaded_adr + (j * sizeof( Elf32_Rel))); + new_sym_num = SymShdrEx->sym_table[ELF32_R_SYM(CurrentRel->r_info)]; + CurrentRel->r_info = ELF32_R_INFO( new_sym_num, + ELF32_R_TYPE(CurrentRel->r_info)); + } + } + } + //RELAセクション + else if( CurrentShdrEx->Shdr.sh_type == SHT_RELA) { + CurrentShdrEx->loaded_adr = (u32) + ELi_CopySectionToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + { + Elf32_Rela* CurrentRela; + ELShdrEx* SymShdrEx; + u32 new_sym_num; + /*シンボルセクション取得*/ + SymShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, + CurrentShdrEx->Shdr.sh_link); + /*コピー先のRelaセクションを修正*/ + for( j=0; j<(CurrentShdrEx->Shdr.sh_size/CurrentShdrEx->Shdr.sh_entsize); j++) { + CurrentRela = (Elf32_Rela*)(CurrentShdrEx->loaded_adr + (j * sizeof( Elf32_Rela))); +// printf( "symnum: 0x%x\n", ELF32_R_SYM(CurrentRela->r_info)); +// printf( "sym_table:0x%x", (u32)(SymShdrEx->sym_table)); + new_sym_num = SymShdrEx->sym_table[ELF32_R_SYM(CurrentRela->r_info)]; + CurrentRela->r_info = ELF32_R_INFO( new_sym_num, + ELF32_R_TYPE(CurrentRela->r_info)); + } + } + } + //文字列テーブルセクション + else if( CurrentShdrEx->Shdr.sh_type == SHT_STRTAB) { + if( i == ElfHandle->CurrentEhdr.e_shstrndx) { //セクション名文字列テーブルセクション + CurrentShdrEx->loaded_adr = (u32) + ELi_CopyShStrToBuffer( ElfHandle, &(CurrentShdrEx->Shdr)); + }else{ + CurrentShdrEx->loaded_adr = (u32) + ELi_CopySymStrToBuffer( ElfHandle, CurrentShdrEx); +// printf( "sym str section:0x%x, size:0x%x\n", i, CurrentShdrEx->str_table_size); + } + } + } + } + /*-------------------------------------------------------*/ + + + /*ここまででセクションの中身だけがstripped elfにコピーされた*/ + + + /*---------- セクションヘッダを stripped elfにコピー ----------*/ + buf_shdr = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); + ElfHandle->buf_current = buf_shdr; +// printf( "buf_shdr = 0x%x\n", buf_shdr); +// printf( "buf = 0x%x\n", (u32)buf); + + newelf_shoff = buf_shdr - ((u32)(buf)); +// printf( "newelf_shoff = 0x%x\n", newelf_shoff); + + section_num = 0; + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + // + tmp_buf = buf_shdr + ( section_num * sizeof( Elf32_Shdr)); + + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + if( CurrentShdrEx->debug_flag == 1) { //デバッグ情報の場合はNULLセクションに変換 +// memset( (u8*)tmp_buf, '\0', sizeof( Elf32_Shdr)); + }else{ + /*オフセット更新*/ + if( CurrentShdrEx->loaded_adr != 0) { + CurrentShdrEx->Shdr.sh_offset = (CurrentShdrEx->loaded_adr - (u32)buf); + } + /*セクションヘッダをstripped elfイメージへコピー*/ + CurrentShdrEx->Shdr.sh_link = shdr_table[CurrentShdrEx->Shdr.sh_link]; //セクション番号更新 + if( CurrentShdrEx->Shdr.sh_type == SHT_SYMTAB) { + /*シンボルテーブルのsh_typeはシンボルエントリのインデックスを表す*/ + }else{ + CurrentShdrEx->Shdr.sh_info = shdr_table[CurrentShdrEx->Shdr.sh_info]; //セクション番号更新 + } + memcpy( (u8*)tmp_buf, &(CurrentShdrEx->Shdr), + sizeof( Elf32_Shdr)); + section_num++; /*セクション数更新*/ + } + } + // コピー終了後 + ElfHandle->process = EL_COPIED; + /*------------------------------------------------------------*/ + + ElfHandle->newelf_size = (buf_shdr - (u32)buf) + (section_num*sizeof( Elf32_Shdr)); +// printf( "newelf_size = 0x%x\n", ElfHandle->newelf_size); + + /*---------- ELFヘッダ更新 ----------*/ + ElfHandle->CurrentEhdr.e_shnum = section_num; /*減ったセクション数をELFヘッダに反映*/ + ElfHandle->CurrentEhdr.e_shstrndx = shdr_table[ElfHandle->CurrentEhdr.e_shstrndx]; + //セクションヘッダオフセット更新 + ElfHandle->CurrentEhdr.e_shoff = newelf_shoff; + memcpy( (u8*)buf, &(ElfHandle->CurrentEhdr), sizeof( Elf32_Ehdr)); /*ELFヘッダをstripped elfイメージにコピー*/ + /*-----------------------------------*/ + + + /*---------- 再配置 ----------*/ +/* 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", num_of_entry); + printf( "Section Header Info.\n"); + printf( "link : %x\n", CurrentShdrEx->Shdr.sh_link); + printf( "info : %x\n", 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 ", ElfHandle->Rel.r_offset); + printf( "%08x ", ElfHandle->Rel.r_info); + printf( " "); + printf( "%08x ", 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", num_of_entry); + printf( "Section Header Info.\n"); + printf( "link : %x\n", CurrentShdrEx->Shdr.sh_link); + printf( "info : %x\n", 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 ", ElfHandle->Rela.r_offset); + printf( "%08x ", ElfHandle->Rela.r_info); + printf( " "); + printf( "%08x ", 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, 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, 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; +} + + + + + +/*------------------------------------------------------ + アドレステーブルからエントリを削除する + -----------------------------------------------------*/ +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) + -----------------------------------------------------*/ +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; + } + /*------------------------------------*/ +} + +/*------------------------------------------------------ + 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/stripdebug/elf_loader.h b/tools/stripdebug/elf_loader.h new file mode 100644 index 0000000..634c987 --- /dev/null +++ b/tools/stripdebug/elf_loader.h @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------------* + Project: TWL - ELF Loader + File: elf_loader.h + + Copyright 2006,2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ +#ifndef _ELF_LOADER_H_ +#define _ELF_LOADER_H_ + +#include +#include "types.h" +#include "elf.h" + + +/*------------------------------------------------------ + セクションヘッダ拡張(ロードアドレス等に対応) + -----------------------------------------------------*/ +typedef struct { + void* next; + u16 index; + u16 debug_flag; /*0:デバッグ情報でない、1:デバッグ情報*/ + u32 loaded_adr; + u32 alloc_adr; + u32 loaded_size; + Elf32_Shdr Shdr; + char* str; /*セクション名文字列をコピーしてきたもの*/ + u32* sym_table; /*シンボルセクションのとき有効な新旧対応表*/ + void* str_table; /*STRセクションのとき有効:新文字列テーブル*/ + u32 str_table_size; /*STRセクションのとき有効:新文字列テーブルのサイズ*/ +}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リストの先頭 */ + ELSymEx** SymExTbl; /* SymExアドレスのテーブル(全シンボル数ぶん)*/ + u32 SymExTarget; /* SymExリストを構築したシンボルセクションのセクション番号 */ + + ELi_ReadFunc ELi_ReadStub; /* リードスタブ関数 */ + void* FileStruct; /* ファイル構造体 */ + + u32 mem_adr; /*最初にロードされたセクションのsh_addrが入る(DSのROMヘッダ用パラメータ)*/ + u32 newelf_size; +}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/stripdebug/loader_subset.c b/tools/stripdebug/loader_subset.c new file mode 100644 index 0000000..887b698 --- /dev/null +++ b/tools/stripdebug/loader_subset.c @@ -0,0 +1,580 @@ +/*---------------------------------------------------------------------------* + Project: TWL - 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)) + +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_CopySymStrToBuffer( ELHandle* ElfHandle, ELShdrEx* SymStrShdrEx) +{ + u32 load_start, i; + + /*アラインメントをとる*/ + load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); + + memcpy( load_start, SymStrShdrEx->str_table, SymStrShdrEx->str_table_size); + + /*セクションヘッダのサイズ修正*/ + SymStrShdrEx->Shdr.sh_size = SymStrShdrEx->str_table_size; + + /*バッファポインタを移動*/ + ElfHandle->buf_current = (void*)(load_start + SymStrShdrEx->str_table_size); + + return( void*)load_start; +} + +/*------------------------------------------------------ + セクション文字列の中身をバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopyShStrToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr) +{ + u32 load_start, i; + u32 total_size = 0; + ELShdrEx* CurrentShdrEx; + + /*アラインメントをとる*/ + load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); +// load_adr = load_start; + + for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) { + CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i); + + if( CurrentShdrEx->debug_flag == 1) { + }else{ + CurrentShdrEx->Shdr.sh_name = total_size; + strcpy( load_start+total_size, CurrentShdrEx->str); + total_size += (strlen( CurrentShdrEx->str) + 1); + } + } + + /*セクションヘッダのサイズ修正*/ + Shdr->sh_size = total_size; + + /*バッファポインタを移動*/ + ElfHandle->buf_current = (void*)(load_start + total_size); + + return( void*)load_start; +} + +/*------------------------------------------------------ + シンボルエントリをまとめてバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopySymToBuffer( ELHandle* ElfHandle) +{ + u32 load_start, load_adr; + u32 total_size = 0; + ELSymEx* CurrentSymEx; + + /*アラインメントをとる*/ + load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4); + load_adr = load_start; + + CurrentSymEx = ElfHandle->SymEx; + while( CurrentSymEx != NULL) { + /*コピー*/ + memcpy( (u8*)load_adr, &(CurrentSymEx->Sym), + sizeof( Elf32_Sym)); + CurrentSymEx = CurrentSymEx->next; + load_adr += sizeof( Elf32_Sym); + total_size += sizeof( Elf32_Sym); +// printf( "symbol found\n"); + } + + /*バッファポインタを移動*/ + ElfHandle->buf_current = (void*)(load_start + total_size); + + return( void*)load_start; +} + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +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); +} + + +/*------------------------------------------------------ + シンボルリストを作成する + + -----------------------------------------------------*/ +void ELi_BuildSymList( ELHandle* elElfDesc, u32 symsh_index, u32** sym_table) +{ + u32 i; + u32 num_of_sym; //シンボルの全体数 + u16 debug_flag; + Elf32_Sym TestSym; + ELSymEx* CurrentSymEx; + ELShdrEx* CurrentShdrEx; + Elf32_Shdr SymShdr; + ELSymEx DmySymEx; + u32 sym_num = 0; + + if( elElfDesc->SymExTarget == symsh_index) { +// printf( "%s skip.\n", __FUNCTION__); + return; //既にリスト作成済み + }else{ + ELi_FreeSymList( elElfDesc, sym_table); /*シンボルリストを開放する*/ + } + +// printf( "%s build\n", __FUNCTION__); + + /*SYMTABセクションヘッダ取得*/ + ELi_GetShdr( elElfDesc, symsh_index, &SymShdr); + + /*シンボル新旧対応テーブル構築*/ + *sym_table = (u32*)malloc( 4 * (SymShdr.sh_size / SymShdr.sh_entsize)); + + num_of_sym = (SymShdr.sh_size) / (SymShdr.sh_entsize); //シンボルの全体数 + elElfDesc->SymExTbl = malloc( num_of_sym * 4); + + /*---------- ElSymExのリストを作る ----------*/ + CurrentSymEx = &DmySymEx; + for( i=0; iShdrEx, TestSym.st_shndx); + if( CurrentShdrEx) { + debug_flag = CurrentShdrEx->debug_flag; + }else{ + debug_flag = 0; + }/*-------------------------------*/ + + if( debug_flag == 1) { + elElfDesc->SymExTbl[i] = NULL; + (*sym_table)[i] = 0xFFFFFFFF; + }else{ + CurrentSymEx->next = malloc( sizeof(ELSymEx)); + CurrentSymEx = (ELSymEx*)(CurrentSymEx->next); + + memcpy( &(CurrentSymEx->Sym), &TestSym, sizeof(TestSym)); + + elElfDesc->SymExTbl[i] = CurrentSymEx; + + (*sym_table)[i] = sym_num; + + sym_num++; + +// printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx); + + /*-- ElSymExのThumbフラグをセット(関数シンボルだけ必要)--*/ + if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) { + CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( elElfDesc, CurrentSymEx->Sym.st_shndx, + CurrentSymEx->Sym.st_value)); + }else{ + CurrentSymEx->thumb_flag = 0; + }/*--------------------------------------------------------*/ + } + } + + CurrentSymEx->next = NULL; + elElfDesc->SymEx = DmySymEx.next; + /*-------------------------------------------*/ + + + elElfDesc->SymExTarget = symsh_index; +} + + +/*------------------------------------------------------ + シンボルリストを開放する + + -----------------------------------------------------*/ +void ELi_FreeSymList( ELHandle* elElfDesc, u32** sym_table) +{ + ELSymEx* CurrentSymEx; + ELSymEx* FwdSymEx; + + if( elElfDesc->SymExTbl != NULL) { + free( elElfDesc->SymExTbl); + elElfDesc->SymExTbl = NULL; + } + + /*------- ElSymExのリストを解放する -------*/ + CurrentSymEx = elElfDesc->SymEx; + if( CurrentSymEx) { + while( CurrentSymEx->next != NULL) { + FwdSymEx = CurrentSymEx; + CurrentSymEx = CurrentSymEx->next; + free( FwdSymEx); + } + elElfDesc->SymEx = NULL; + } + /*-----------------------------------------*/ + +/* if( *sym_table) { //ここはアプリケーションで開放させるのでコメントアウト + free( *sym_table); + }*/ + + + elElfDesc->SymExTarget = 0xFFFFFFFF; +} + + +/*------------------------------------------------------ + リストから指定インデックスの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/stripdebug/loader_subset.h b/tools/stripdebug/loader_subset.h new file mode 100644 index 0000000..9d67074 --- /dev/null +++ b/tools/stripdebug/loader_subset.h @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------------* + Project: TWL - ELF Loader + File: loader_subset.h + + Copyright 2006,2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef _LOADER_SUBSET_H_ +#define _LOADER_SUBSET_H_ + +#include "types.h" +#include "elf.h" +#include "elf_loader.h" + + +/*------------------------------------------------------ + シンボル文字列の中身をバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopySymStrToBuffer( ELHandle* ElfHandle, ELShdrEx* SymStrShdrEx); + + +/*------------------------------------------------------ + セクション文字列の中身をバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopyShStrToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr); + + +/*------------------------------------------------------ + シンボルエントリをまとめてバッファにコピーする + -----------------------------------------------------*/ +void* ELi_CopySymToBuffer( ELHandle* ElfHandle); + + +/*------------------------------------------------------ + セクションをバッファにコピーする + -----------------------------------------------------*/ +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_BuildSymList( ELHandle* elElfDesc, u32 symsh_index, u32** sym_table); + + +/*------------------------------------------------------ + シンボルリストを開放する + + -----------------------------------------------------*/ +void ELi_FreeSymList( ELHandle* elElfDesc, u32** sym_table); + + +/*------------------------------------------------------ + シンボルを再定義する + -----------------------------------------------------*/ +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/stripdebug/readme.txt b/tools/stripdebug/readme.txt new file mode 100644 index 0000000..b517906 --- /dev/null +++ b/tools/stripdebug/readme.txt @@ -0,0 +1,21 @@ + +・stripdebug + +elfファイルからデバッグ情報を削除します。 +具体的には、以下の情報を削除します。 + +・デバッグセクションのセクションヘッダ +・デバッグセクションの中身 +・シンボルセクションのデバッグシンボルエントリ +・セクション文字列テーブルの中のデバッグセクション用文字列エントリ +・シンボル文字列テーブルの中のデバッグシンボル用文字列エントリ + +stripコマンドとの相違点は次の通りです。 + +・セクションを並び換えない +・セクションの先頭アドレスを示すシンボルを生成しない +・セクション文字列テーブルおよびシンボル文字列テーブルの文字列を + 重複して参照しない +・元ファイルにセクション対応テーブルをスペシャルセクションとして + 追加する(未実装) + diff --git a/tools/stripdebug/searcharg.c b/tools/stripdebug/searcharg.c new file mode 100644 index 0000000..60abce3 --- /dev/null +++ b/tools/stripdebug/searcharg.c @@ -0,0 +1,61 @@ + +#include +#include +#include + +#include "searcharg.h" + +/* +char* opt[7]; +char* opt_arg[7]; +char* arg[7]; + +int opt_num; +int arg_num; +*/ + +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/stripdebug/searcharg.h b/tools/stripdebug/searcharg.h new file mode 100644 index 0000000..490e916 --- /dev/null +++ b/tools/stripdebug/searcharg.h @@ -0,0 +1,21 @@ + +#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; + + +void SA_searchopt( SAArgList* ArgList, int argc, char* argv[]); + + + +#endif /*__SEARCH_ARG__*/ diff --git a/tools/stripdebug/stripdebug.c b/tools/stripdebug/stripdebug.c new file mode 100644 index 0000000..c04aa03 --- /dev/null +++ b/tools/stripdebug/stripdebug.c @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------* + Project: tools - makedsrom + File: stripdebug.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 // getopt() +#include +#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 STRIPPED_ELF_FILENAME "stripped-" +FILE* NewElfFilep; + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +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, j, k; + int n; + int narg; + int t; + FILE *FHp; + u32 *elfbuf; + u32* newelfbuf; + u32 elfsize; + u32 mainp_malloc_size, subp_malloc_size; + size_t filesize; + ELHandle ElfH; + u32 loadstart, loadend, loadsize, ramadr; + u32 entry_address, ram_address; + u32 sub_loadstart, sub_loadend, sub_loadsize, sub_ramadr; + u32 sub_entry_address, sub_ram_address;; + u32 header_buf[DS_ROM_HEADER_SIZE/4]; + char* elf_filename; + u32 elf_namesize; + char* slash_pointer; + SAArgList ArgList; + u16 result; + + +// printf( "binbuf : %x\n", binbuf); +/* + for( i=0; i 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/stripdebug/version.h b/tools/stripdebug/version.h new file mode 100644 index 0000000..155e84d --- /dev/null +++ b/tools/stripdebug/version.h @@ -0,0 +1 @@ +#define SDK_DATE_OF_LATEST_FILE 20060905UL