Line 1... |
Line 1... |
//convert.c by Steve Rhoads 4/26/01
|
//convert.c by Steve Rhoads 4/26/01
|
|
//Now uses the ELF format (get gccmips_elf.zip)
|
//set $gp and zero .sbss and .bss
|
//set $gp and zero .sbss and .bss
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
#define BUF_SIZE (1024*1024)
|
#define BUF_SIZE (1024*1024)
|
/*Assumes running on PC little endian*/
|
/*Assumes running on PC little endian*/
|
#define ntohl(A) ((A>>24)|((A&0x00ff0000)>>8)|((A&0xff00)<<8)|(A<<24))
|
#define ntohl(A) (((A)>>24)|(((A)&0x00ff0000)>>8)|(((A)&0xff00)<<8)|((A)<<24))
|
|
#define ntohs(A) ((((A)&0xff00)>>8)|((A)<<8))
|
|
|
#define CODE_START 0x60
|
#define EI_NIDENT 16
|
#define SECTION_START 0x4c
|
#define SHT_PROGBITS 1
|
#define SECTION_END 0x160
|
#define SHT_STRTAB 3
|
#define SECTION_SIZE 0x28
|
#define SHT_NOBITS 8
|
#define SECTION_OFFSET 0xc
|
|
#define SECTION_LENGTH 0x10
|
typedef struct {
|
|
unsigned char e_ident[EI_NIDENT];
|
struct header_t {
|
unsigned short e_e_type;
|
unsigned long text_offset,text_length;
|
unsigned short e_machine;
|
unsigned long rdata_offset,rdata_length;
|
unsigned long e_version;
|
unsigned long data_offset,data_length;
|
unsigned long e_entry;
|
unsigned long sdata_offset,sdata_length;
|
unsigned long e_phoff;
|
unsigned long sbss_offset,sbss_length;
|
unsigned long e_shoff;
|
unsigned long bss_offset,bss_length;
|
unsigned long e_flags;
|
} header;
|
unsigned short e_ehsize;
|
|
unsigned short e_phentsize;
|
|
unsigned short e_phnum;
|
|
unsigned short e_shentsize;
|
|
unsigned short e_shnum;
|
|
unsigned short e_shstrndx;
|
|
} ElfHeader;
|
|
|
|
typedef struct {
|
|
unsigned long p_type;
|
|
unsigned long p_offset;
|
|
unsigned long p_vaddr;
|
|
unsigned long p_paddr;
|
|
unsigned long p_filesz;
|
|
unsigned long p_memsz;
|
|
unsigned long p_flags;
|
|
unsigned long p_align;
|
|
} Elf32_Phdr;
|
|
|
|
typedef struct {
|
|
unsigned long sh_name;
|
|
unsigned long sh_type;
|
|
unsigned long sh_flags;
|
|
unsigned long sh_addr;
|
|
unsigned long sh_offset;
|
|
unsigned long sh_size;
|
|
unsigned long sh_link;
|
|
unsigned long sh_info;
|
|
unsigned long sh_addralign;
|
|
unsigned long sh_entsize;
|
|
} Elf32_Shdr;
|
|
|
unsigned long load(char *ptr,unsigned long address)
|
#if 0
|
|
unsigned long load(unsigned char *ptr,unsigned long address)
|
{
|
{
|
unsigned long value;
|
unsigned long value;
|
value=*(unsigned long*)(ptr+address);
|
value=*(unsigned long*)(ptr+address);
|
value=ntohl(value);
|
value=ntohl(value);
|
return value;
|
return value;
|
}
|
}
|
|
|
|
unsigned short load_short(unsigned char *ptr,unsigned long address)
|
|
{
|
|
return (ptr[address]<<8)+ptr[address+1];
|
|
}
|
|
#endif
|
|
|
void set_low(char *ptr,unsigned long address,unsigned long value)
|
void set_low(char *ptr,unsigned long address,unsigned long value)
|
{
|
{
|
unsigned long opcode;
|
unsigned long opcode;
|
opcode=*(unsigned long*)(ptr+address);
|
opcode=*(unsigned long*)(ptr+address);
|
opcode=ntohl(opcode);
|
opcode=ntohl(opcode);
|
Line 44... |
Line 84... |
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
{
|
{
|
FILE *infile,*outfile,*txtfile;
|
FILE *infile,*outfile,*txtfile;
|
unsigned char *buf,*code;
|
unsigned char *buf,*code;
|
long size,stack_pointer;
|
long size,stack_pointer;
|
unsigned long code_offset,index,name,offset,length,d,i,gp_ptr;
|
unsigned long length,d,i,gp_ptr=0;
|
|
unsigned long bss_start=0,bss_end=0;
|
|
|
|
ElfHeader *elfHeader;
|
|
Elf32_Phdr *elfProgram;
|
|
Elf32_Shdr *elfSection;
|
|
|
printf("test.exe -> code.txt & test2.exe\n");
|
printf("test.exe -> code.txt & test2.exe\n");
|
infile=fopen("test.exe","rb");
|
infile=fopen("test.exe","rb");
|
if(infile==NULL) {
|
if(infile==NULL) {
|
printf("Can't open test.exe");
|
printf("Can't open test.exe");
|
return 0;
|
return 0;
|
}
|
}
|
buf=(unsigned char*)malloc(BUF_SIZE);
|
buf=(unsigned char*)malloc(BUF_SIZE);
|
size=fread(buf,1,BUF_SIZE,infile);
|
size=fread(buf,1,BUF_SIZE,infile);
|
fclose(infile);
|
fclose(infile);
|
|
code=(unsigned char*)malloc(BUF_SIZE);
|
|
memset(code,0,BUF_SIZE);
|
|
|
code_offset=load(buf,CODE_START);
|
elfHeader=(ElfHeader*)buf;
|
printf("code_offset=0x%x ",code_offset);
|
if(strncmp(elfHeader->e_ident+1,"ELF",3)) {
|
code=buf+code_offset;
|
printf("Error: Not an ELF file!\n");
|
|
printf("Use the gccmips_elf.zip from opencores/projects/plasma!\n");
|
/*load all of the segment offsets and lengths*/
|
return -1;
|
for(index=SECTION_START;index<code_offset-0x20;index+=SECTION_SIZE) {
|
}
|
name=load(buf,index);
|
|
offset=load(buf,index+SECTION_OFFSET);
|
elfHeader->e_entry=ntohl(elfHeader->e_entry);
|
length=load(buf,index+SECTION_LENGTH);
|
elfHeader->e_phoff=ntohl(elfHeader->e_phoff);
|
switch(name) {
|
elfHeader->e_shoff=ntohl(elfHeader->e_shoff);
|
case 0x2e746578: /*.text*/
|
elfHeader->e_phentsize=ntohs(elfHeader->e_phentsize);
|
header.text_offset=offset;
|
elfHeader->e_phnum=ntohs(elfHeader->e_phnum);
|
header.text_length=length;
|
elfHeader->e_shentsize=ntohs(elfHeader->e_shentsize);
|
offset+=length;
|
elfHeader->e_shnum=ntohs(elfHeader->e_shnum);
|
length=0;
|
|
header.rdata_offset=offset;
|
|
header.rdata_length=length;
|
|
header.data_offset=offset;
|
|
header.data_length=length;
|
|
header.sdata_offset=offset;
|
|
header.sdata_length=length;
|
|
header.sbss_offset=offset;
|
|
header.sbss_length=length;
|
|
header.bss_offset=offset;
|
|
header.bss_length=length;
|
|
break;
|
|
case 0x2e726461: /*.rdata*/
|
|
header.rdata_offset=offset;
|
|
header.rdata_length=length;
|
|
offset+=length;
|
|
length=0;
|
|
header.data_offset=offset;
|
|
header.data_length=length;
|
|
header.sdata_offset=offset;
|
|
header.sdata_length=length;
|
|
header.sbss_offset=offset;
|
|
header.sbss_length=length;
|
|
header.bss_offset=offset;
|
|
header.bss_length=length;
|
|
break;
|
|
case 0x2e646174: /*.data*/
|
|
header.data_offset=offset;
|
|
header.data_length=length;
|
|
offset+=length;
|
|
length=0;
|
|
header.sdata_offset=offset;
|
|
header.sdata_length=length;
|
|
header.sbss_offset=offset;
|
|
header.sbss_length=length;
|
|
header.bss_offset=offset;
|
|
header.bss_length=length;
|
|
break;
|
|
case 0x2e736461: /*.sdata*/
|
|
header.sdata_offset=offset;
|
|
header.sdata_length=length;
|
|
offset+=length;
|
|
length=0;
|
length=0;
|
header.sbss_offset=offset;
|
|
header.sbss_length=length;
|
for(i=0;i<elfHeader->e_phnum;++i) {
|
header.bss_offset=offset;
|
elfProgram=(Elf32_Phdr*)(buf+elfHeader->e_phoff+elfHeader->e_phentsize*i);
|
header.bss_length=length;
|
elfProgram->p_offset=ntohl(elfProgram->p_offset);
|
break;
|
elfProgram->p_vaddr=ntohl(elfProgram->p_vaddr);
|
case 0x2e736273: /*.sbss*/
|
elfProgram->p_filesz=ntohl(elfProgram->p_filesz);
|
header.sbss_offset=offset;
|
elfProgram->p_memsz=ntohl(elfProgram->p_memsz);
|
header.sbss_length=length;
|
// printf("[0x%x,0x%x,0x%x]\n",elfProgram->p_vaddr,elfProgram->p_offset,elfProgram->p_filesz);
|
offset+=length;
|
memcpy(code+elfProgram->p_vaddr,buf+elfProgram->p_offset,elfProgram->p_filesz);
|
length=0;
|
length=elfProgram->p_vaddr+elfProgram->p_memsz;
|
header.bss_offset=offset;
|
}
|
header.bss_length=length;
|
|
break;
|
for(i=0;i<elfHeader->e_shnum;++i) {
|
case 0x2e627373: /*.bss*/
|
elfSection=(Elf32_Shdr*)(buf+elfHeader->e_shoff+elfHeader->e_shentsize*i);
|
header.bss_offset=offset;
|
elfSection->sh_name=ntohl(elfSection->sh_name);
|
header.bss_length=length;
|
elfSection->sh_type=ntohl(elfSection->sh_type);
|
break;
|
elfSection->sh_addr=ntohl(elfSection->sh_addr);
|
default: printf("unknown 0x%x\n",name);
|
elfSection->sh_offset=ntohl(elfSection->sh_offset);
|
|
elfSection->sh_size=ntohl(elfSection->sh_size);
|
|
#if 0
|
|
printf("{0x%x,0x%x:0x%x,0x%x,0x%x}\n",
|
|
elfSection->sh_name,elfSection->sh_type,elfSection->sh_addr,
|
|
elfSection->sh_offset,elfSection->sh_size);
|
|
#endif
|
|
#if 0
|
|
if(elfSection->sh_type==SHT_PROGBITS||elfSection->sh_type==SHT_STRTAB) {
|
|
// memcpy(code+elfSection->sh_addr,buf+elfSection->sh_offset,elfSection->sh_size);
|
|
length=elfSection->sh_addr+elfSection->sh_size;
|
|
bss_start=length;
|
|
}
|
|
#endif
|
|
if(elfSection->sh_type==SHT_PROGBITS) {
|
|
gp_ptr=elfSection->sh_addr;
|
|
}
|
|
if(elfSection->sh_type==SHT_NOBITS) {
|
|
if(bss_start==0) {
|
|
bss_start=elfSection->sh_addr;
|
|
}
|
|
bss_end=elfSection->sh_addr+elfSection->sh_size;
|
}
|
}
|
}
|
}
|
|
|
|
if(bss_start==length) {
|
|
bss_start=length;
|
|
bss_end=length+4;
|
|
}
|
|
|
/*Initialize the $gp register for sdata and sbss*/
|
/*Initialize the $gp register for sdata and sbss*/
|
gp_ptr=header.sdata_offset+0x8000;
|
gp_ptr+=0x7ff0;
|
printf("gp_ptr=0x%x ",gp_ptr);
|
printf("gp_ptr=0x%x ",gp_ptr);
|
/*modify the first opcodes in boot.asm*/
|
/*modify the first opcodes in boot.asm*/
|
/*modify the lui opcode*/
|
/*modify the lui opcode*/
|
set_low(code,0,gp_ptr>>16);
|
set_low(code,0,gp_ptr>>16);
|
/*modify the ori opcode*/
|
/*modify the ori opcode*/
|
set_low(code,4,gp_ptr&0xffff);
|
set_low(code,4,gp_ptr&0xffff);
|
|
|
/*Clear .sbss and .bss*/
|
/*Clear .sbss and .bss*/
|
printf(".sbss=0x%x .bss_end=0x%x\n",
|
printf(".sbss=0x%x .bss_end=0x%x\n",bss_start,bss_end);
|
header.sbss_offset,header.bss_offset+header.bss_length);
|
set_low(code,8,bss_start);
|
set_low(code,8,header.sbss_offset);
|
set_low(code,12,bss_end);
|
set_low(code,12,header.bss_offset+header.bss_length);
|
|
|
|
/*Set stack pointer*/
|
/*Set stack pointer*/
|
stack_pointer=header.bss_offset+header.bss_length+512;
|
stack_pointer=bss_end+512;
|
printf("Stack pointer=0x%x\n",stack_pointer);
|
printf("Stack pointer=0x%x\n",stack_pointer);
|
set_low(code,16,stack_pointer);
|
set_low(code,16,stack_pointer);
|
|
|
/*write out code.txt*/
|
/*write out code.txt*/
|
outfile=fopen("test2.exe","wb");
|
outfile=fopen("test2.exe","wb");
|
|
fwrite(code,length,1,outfile);
|
|
fclose(outfile);
|
|
|
txtfile=fopen("code.txt","w");
|
txtfile=fopen("code.txt","w");
|
for(i=0;i<=header.sdata_offset+header.sdata_length;i+=4) {
|
for(i=0;i<=length;i+=4) {
|
d=load(code,i);
|
d=ntohl(*(unsigned long*)(code+i));
|
fprintf(txtfile,"%8.8x\n",d);
|
fprintf(txtfile,"%8.8x\n",d);
|
fwrite(code+i,4,1,outfile);
|
|
}
|
}
|
fclose(outfile);
|
|
fclose(txtfile);
|
fclose(txtfile);
|
free(buf);
|
free(buf);
|
|
|
return 0;
|
return 0;
|
}
|
}
|