#include "romdir.h" #include "eedebug.h" typedef struct { u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE u16 e_machine; //Processor: 8=MIPS R3000 u32 e_version; //Version: 1=current u32 e_entry; //Entry point address u32 e_phoff; //Start of program headers (offset from file start) u32 e_shoff; //Start of section headers (offset from file start) u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips u16 e_ehsize; //ELF header size (0x34 = 52 bytes) u16 e_phentsize; //Program headers entry size u16 e_phnum; //Number of program headers u16 e_shentsize; //Section headers entry size u16 e_shnum; //Number of section headers u16 e_shstrndx; //Section header stringtable index } ELF_HEADER; typedef struct { u32 p_type; //see notes1 u32 p_offset; //Offset from file start to program segment. u32 p_vaddr; //Virtual address of the segment u32 p_paddr; //Physical address of the segment u32 p_filesz; //Number of bytes in the file image of the segment u32 p_memsz; //Number of bytes in the memory image of the segment u32 p_flags; //Flags for segment u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment } ELF_PHR; /* notes1 ------ 0=Inactive 1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 2=Dynamic linking 3=Interpreter. The array element must specify a path name 4=Note. The array element must specify the location and size of aux. info 5=reserved 6=The array element must specify location and size of the program header table. */ typedef struct { u32 sh_name; //No. to the index of the Section header stringtable index u32 sh_type; //See notes2 u32 sh_flags; //see notes3 u32 sh_addr; //Section start address u32 sh_offset; //Offset from start of file to section u32 sh_size; //Size of section u32 sh_link; //Section header table index link u32 sh_info; //Info u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. u32 sh_entsize; //Fixed size entries. } ELF_SHR; /* notes 2 ------- Type: 0=Inactive 1=PROGBITS 2=SYMTAB symbol table 3=STRTAB string table 4=RELA relocation entries 5=HASH hash table 6=DYNAMIC dynamic linking information 7=NOTE 8=NOBITS 9=REL relocation entries 10=SHLIB 0x70000000=LOPROC processor specifc 0x7fffffff=HIPROC 0x80000000=LOUSER lower bound 0xffffffff=HIUSER upper bound notes 3 ------- Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) 1=Write section contains data the is be writeable during execution. 2=Alloc section occupies memory during execution 4=Exec section contains executable instructions 0xf0000000=Mask bits processor-specific */ typedef struct { u32 st_name; u32 st_value; u32 st_size; u8 st_info; u8 st_other; u16 st_shndx; } Elf32_Sym; #define ELF32_ST_TYPE(i) ((i)&0xf) typedef struct { u32 r_offset; u32 r_info; } Elf32_Rel; char *sections_names; ELF_HEADER *elfHeader; ELF_PHR *elfProgH; ELF_SHR *elfSectH; u8 *elfdata; int elfsize; static void __memcpy(void *dest, const void *src, int n) { const u8 *s = (u8*)src; u8 *d = (u8*)dest; while (n) { *d++ = *s++; n--; } } int loadHeaders() { elfHeader = (ELF_HEADER*)elfdata; if ((elfHeader->e_shentsize != sizeof(ELF_SHR)) && (elfHeader->e_shnum > 0)) { return -1; } #ifdef ELF_LOG ELF_LOG( "type: " ); #endif switch( elfHeader->e_type ) { default: #ifdef ELF_LOG ELF_LOG( "unknown %x", elfHeader->e_type ); #endif break; case 0x0: #ifdef ELF_LOG ELF_LOG( "no file type" ); #endif break; case 0x1: #ifdef ELF_LOG ELF_LOG( "relocatable" ); #endif break; case 0x2: #ifdef ELF_LOG ELF_LOG( "executable" ); #endif break; } #ifdef ELF_LOG ELF_LOG( "\n" ); ELF_LOG( "machine: " ); #endif switch ( elfHeader->e_machine ) { default: #ifdef ELF_LOG ELF_LOG( "unknown" ); #endif break; case 0x8: #ifdef ELF_LOG ELF_LOG( "mips_rs3000" ); #endif break; } #ifdef ELF_LOG ELF_LOG("\n"); ELF_LOG("version: %d\n",elfHeader->e_version); ELF_LOG("entry: %08x\n",elfHeader->e_entry); ELF_LOG("flags: %08x\n",elfHeader->e_flags); ELF_LOG("eh size: %08x\n",elfHeader->e_ehsize); ELF_LOG("ph off: %08x\n",elfHeader->e_phoff); ELF_LOG("ph entsiz: %08x\n",elfHeader->e_phentsize); ELF_LOG("ph num: %08x\n",elfHeader->e_phnum); ELF_LOG("sh off: %08x\n",elfHeader->e_shoff); ELF_LOG("sh entsiz: %08x\n",elfHeader->e_shentsize); ELF_LOG("sh num: %08x\n",elfHeader->e_shnum); ELF_LOG("sh strndx: %08x\n",elfHeader->e_shstrndx); ELF_LOG("\n"); #endif return 0; } int loadProgramHeaders() { int i; if (elfHeader->e_phnum == 0) { return 0; } if (elfHeader->e_phentsize != sizeof(ELF_PHR)) { return -1; } elfProgH = (ELF_PHR*)&elfdata[elfHeader->e_phoff]; for ( i = 0 ; i < elfHeader->e_phnum ; i++ ) { #ifdef ELF_LOG ELF_LOG( "Elf32 Program Header\n" ); ELF_LOG( "type: " ); #endif switch ( elfProgH[ i ].p_type ) { default: #ifdef ELF_LOG ELF_LOG( "unknown %x", (int)elfProgH[ i ].p_type ); #endif break; case 0x1: #ifdef ELF_LOG ELF_LOG("load"); #endif /* if ( elfHeader->e_shnum == 0 ) {*/ if (elfProgH[ i ].p_offset < elfsize) { int size; if ((elfProgH[ i ].p_filesz + elfProgH[ i ].p_offset) > elfsize) { size = elfsize - elfProgH[ i ].p_offset; } else { size = elfProgH[ i ].p_filesz; } // __printf("loading program to %x\n", elfProgH[ i ].p_paddr + elfbase); __memcpy(elfProgH[ i ].p_paddr, &elfdata[elfProgH[ i ].p_offset], size); } #ifdef ELF_LOG ELF_LOG("\t*LOADED*"); #endif // } break; } #ifdef ELF_LOG ELF_LOG("\n"); ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset); ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr); ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr); ELF_LOG("file size: %08x\n",elfProgH[i].p_filesz); ELF_LOG("mem size: %08x\n",elfProgH[i].p_memsz); ELF_LOG("flags: %08x\n",elfProgH[i].p_flags); ELF_LOG("palign: %08x\n",elfProgH[i].p_align); ELF_LOG("\n"); #endif } return 0; } int loadSectionHeaders() { int i; int i_st = -1; int i_dt = -1; if (elfHeader->e_shnum == 0) { return -1; } elfSectH = (ELF_SHR*)&elfdata[elfHeader->e_shoff]; if ( elfHeader->e_shstrndx < elfHeader->e_shnum ) { sections_names = (char *)&elfdata[elfSectH[ elfHeader->e_shstrndx ].sh_offset]; } for ( i = 0 ; i < elfHeader->e_shnum ; i++ ) { #ifdef ELF_LOG ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ elfSectH[ i ].sh_name ] ); #endif /* if ( elfSectH[i].sh_flags & 0x2 ) { if (elfSectH[i].sh_offset < elfsize) { int size; if ((elfSectH[i].sh_size + elfSectH[i].sh_offset) > elfsize) { size = elfsize - elfSectH[i].sh_offset; } else { size = elfSectH[i].sh_size; } memcpy(&psM[ elfSectH[ i ].sh_addr &0x1ffffff ], &elfdata[elfSectH[i].sh_offset], size); } #ifdef ELF_LOG ELF_LOG( "\t*LOADED*" ); #endif }*/ #ifdef ELF_LOG ELF_LOG("\n"); ELF_LOG("type: "); #endif switch ( elfSectH[ i ].sh_type ) { default: #ifdef ELF_LOG ELF_LOG("unknown %08x",elfSectH[i].sh_type); #endif break; case 0x0: #ifdef ELF_LOG ELF_LOG("null"); #endif break; case 0x1: #ifdef ELF_LOG ELF_LOG("progbits"); #endif break; case 0x2: #ifdef ELF_LOG ELF_LOG("symtab"); #endif break; case 0x3: #ifdef ELF_LOG ELF_LOG("strtab"); #endif break; case 0x4: #ifdef ELF_LOG ELF_LOG("rela"); #endif break; case 0x8: #ifdef ELF_LOG ELF_LOG("no bits"); #endif break; case 0x9: #ifdef ELF_LOG ELF_LOG("rel"); #endif break; } #ifdef ELF_LOG ELF_LOG("\n"); ELF_LOG("flags: %08x\n", elfSectH[i].sh_flags); ELF_LOG("addr: %08x\n", elfSectH[i].sh_addr); ELF_LOG("offset: %08x\n", elfSectH[i].sh_offset); ELF_LOG("size: %08x\n", elfSectH[i].sh_size); ELF_LOG("link: %08x\n", elfSectH[i].sh_link); ELF_LOG("info: %08x\n", elfSectH[i].sh_info); ELF_LOG("addralign: %08x\n", elfSectH[i].sh_addralign); ELF_LOG("entsize: %08x\n", elfSectH[i].sh_entsize); #endif // dump symbol table if (elfSectH[i].sh_type == 0x02) { i_st = i; i_dt = elfSectH[i].sh_link; } /* if (elfSectH[i].sh_type == 0x01) { int size = elfSectH[i].sh_size / 4; u32 *ptr = (u32*)&psxM[(elfSectH[i].sh_addr + irx_addr) & 0x1fffff]; while (size) { if (*ptr == 0x41e00000) { // import func int ret = iopSetImportFunc(ptr+1); size-= ret; ptr+= ret; } if (*ptr == 0x41c00000) { // export func int ret = iopSetExportFunc(ptr+1); size-= ret; ptr+= ret; } size--; ptr++; } } */ /* if (!strcmp(".data", §ions_names[elfSectH[i].sh_name])) { // seems so.. psxRegs.GPR.n.gp = 0x8000 + irx_addr + elfSectH[i].sh_addr; }*/ } return 0; } u32 loadElfFile(char *filename, struct elfinfo *info) { struct rominfo ri; char str[256]; char str2[256]; int i; __printf("loadElfFile: %s\n", filename); if (romdirGetFile(filename, &ri) == NULL) { __printf("file %s not found!!\n", filename); return -1; } elfdata = (u8*)(0xbfc00000 + ri.fileOffset); elfsize = ri.fileSize; loadHeaders(); loadProgramHeaders(); loadSectionHeaders(); // __printf("loadElfFile: e_entry=%x\n", elfHeader->e_entry); return elfHeader->e_entry; }