1
0
Files
2022-09-29 17:59:04 +03:00

293 lines
7.0 KiB
C

/*
* elf2coff
* Usage: elf2coff elfExecutableInputFileName CoffExecutableOutputFileName
* converts elf executable into coff executable
* CAVEATS: -code must be linked at lower address than data
* -data should be adjacent to code, or else elf2coff will extend
* the text segment in size and pad it with zeroes until
* the code and data are contiguous
*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <arcs/io.h>
#include <arcs/large.h>
#include <string.h>
#include <setjmp.h>
#include <aouthdr.h>
#include <filehdr.h>
#include <scnhdr.h>
#include <sym.h>
#include <arcs/dload.h>
extern __psint_t malloc(int);
int Verbose = 0;
int Debug = 0;
int e2c_verbose = 0;
LONG Close(ULONG foo){ return 0; }
mem_contains(){return 1;}
void dmabuf_free(){}
int range_check(){return 0;}
void flush_cache(){}
MEMORYDESCRIPTOR *md_alloc(unsigned long a, unsigned long b, MEMORYTYPE c)
{
MEMORYDESCRIPTOR m;
return &m;
}
LONG md_dealloc(unsigned long a, unsigned long b) { return 0;}
/* this is dead code, referenced by the elf loader, but never executed */
void (*dload(int a, void * b, void * c, struct execinfo * d, int *e))()
{
fprintf(stderr, "dload\n"); exit (-1);
return 0;
}
void expand(){fprintf(stderr, "expand\n"); exit (-1); }
void _argvize(){fprintf(stderr, "_argvize\n"); exit (-1); }
void mem_getblock(){fprintf(stderr, "mem_getblock\n"); exit (-1); }
void init_str(){fprintf(stderr, "init_str\n"); exit (-1); }
void new_str1(){fprintf(stderr, "new_str1\n"); exit (-1); }
void find_str(){fprintf(stderr, "find_str\n"); exit (-1); }
void new_str2(){fprintf(stderr, "new_str2\n"); exit (-1); }
void nuxi_s(){fprintf(stderr, "nuxi_s\n"); exit (-1); }
void nuxi_l(){fprintf(stderr, "nuxi_l\n"); exit (-1); }
void makepath(){fprintf(stderr, "makepath\n"); exit (-1); }
void set_str(){fprintf(stderr, "set_str\n"); exit (-1); }
void _scandevs(){fprintf(stderr, "_scandevs\n"); exit (-1); }
void rbsetbs(){fprintf(stderr, "rbsetbs\n"); exit (-1); }
void client_start(){fprintf(stderr, "client_start\n"); exit (-1); }
void close_noncons(){fprintf(stderr, "close_noncons\n"); exit (-1); }
void mem_list(){}
/* end of dead code; if we had a linker which stripped out unreferenced
* functions, we wouldn't need this dead code
*/
long
Open(CHAR *a, OPENMODE mode, ulong *ret)
{
int err = open(a, O_RDONLY);
if(err == -1) {
fprintf(stderr, "couldn't open %s for reading\n", a);
return EBADF;
}
else {
*ret = err;
}
return 0;
}
LONG
Seek(unsigned long fd, LARGE *off, enum seekmode how_seek)
{
off_t offset = off->lo, new_off;
new_off = lseek(fd, offset, (how_seek == SeekAbsolute) ? SEEK_SET : SEEK_CUR);
return (new_off != -1) ? ESUCCESS : EBADF;
}
char *
dmabuf_malloc(int size)
{
char *p = (char *)malloc(size);
if(p == 0) {
fprintf(stderr, "malloc(%d): ran out of memory\n");
exit(-1);
}
return p;
}
static char *outfile;
static
int
do_open(char *s)
{
int ret = open(s, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
if(ret == -1) {
fprintf(stderr, "Couldn't open %s for writing.\n", s);
perror(0);
exit(-1);
}
return ret;
}
static
void
write_out(int fd, char *buf, int cnt)
{
int ret;
do {
ret = write(fd, buf, cnt);
cnt -= ret;
} while(cnt && ret != -1);
if(cnt != 0) {
fprintf(stderr, "Error writing to %s\n", outfile);
perror(0);
}
}
void
dump_output_file(ULONG entry, ULONG text_start, ULONG tsize,
ULONG data_start, ULONG dsize,
ULONG bss_start, ULONG bsize, char *coff_blk[2])
{
struct execinfo e, *ei = &e;
int fd;
struct scnhdr scn;
static struct scnhdr blank_scn;
char *pzero = 0;
int pad = 0;
ei->fh.f_magic = MIPSEBMAGIC;
ei->fh.f_nscns = 3;
ei->fh.f_nsyms = 0;
ei->fh.f_symptr = 0;
ei->fh.f_opthdr = sizeof(struct aouthdr);
ei->ah.magic = OMAGIC;
ei->ah.entry = entry;
ei->ah.text_start = text_start | 0xa0000000;
if (e2c_verbose)
printf("text_start is %x, size is %x\n", ei->ah.text_start, tsize);
ei->ah.tsize = tsize;
#define ZBUF_AMT 4096
if(dsize == 0) {
if(tsize <= ZBUF_AMT) {
fprintf(stderr, "Code+Data section in elf program too small to make a coff file\n");
exit(1);
}
dsize = tsize - ZBUF_AMT;
ei->ah.tsize = tsize = ZBUF_AMT;
ei->ah.data_start = ei->ah.text_start + ZBUF_AMT;
coff_blk[1] = coff_blk[0] + ZBUF_AMT;
}
else {
ei->ah.data_start = data_start | 0xa0000000;
if((pad = ei->ah.data_start - ei->ah.text_start - tsize) > 0 ) {
if (e2c_verbose)
printf("padding text by 0x%x\n", pad);
ei->ah.tsize += pad;
}
else {
/* no pad if data comes right after code or before code*/
pad = 0;
}
}
ei->ah.dsize = dsize;
ei->ah.bss_start = bss_start | 0xa0000000;
ei->ah.bsize = bsize;
if (e2c_verbose) {
printf("text_start is %x\n", ei->ah.text_start);
printf("text_size is %x\n", ei->ah.tsize);
printf("data_start is %x\n", ei->ah.data_start);
printf("data_size is %x\n", dsize);
printf("bss_start is %x\n", ei->ah.bss_start);
printf("bss_size is %x\n", bsize);
}
#undef KDM_TO_PHYS
#define KDM_TO_PHYS(x) ((x) & 0x1fffffff)
if ((KDM_TO_PHYS(ei->ah.text_start) + ei->ah.tsize) >
KDM_TO_PHYS(ei->ah.data_start)) {
fprintf(stderr,"Error: elf2coff: text/data overlap!\n");
exit(-1);
}
if ((KDM_TO_PHYS(ei->ah.data_start) + dsize) >
KDM_TO_PHYS(ei->ah.bss_start)) {
fprintf(stderr,"Error: elf2coff: bss/data overlap!\n");
exit(-1);
}
fd = do_open(outfile);
write_out(fd, (char *)&ei->fh, sizeof(ei->fh));
if(pad) {
pzero = (char *)malloc(pad);
if(pzero == 0) {
printf("malloc: unable to allocate 0x%x bytes\n", pad);
exit(-1);
}
}
write_out(fd, (char *)&ei->ah, sizeof(ei->ah));
/* blank out all unused fields */
scn = blank_scn;
scn.s_scnptr = sizeof(ei->fh) + sizeof(ei->ah) + 3 * sizeof(scn);
scn.s_paddr = scn.s_vaddr = ei->ah.text_start;
strcpy(scn.s_name, ".text");
scn.s_flags = STYP_TEXT;
scn.s_size = ei->ah.tsize;
write_out(fd, (char *)&scn, sizeof(scn));
scn.s_scnptr += tsize + pad;
scn.s_paddr = scn.s_vaddr = ei->ah.data_start;
strcpy(scn.s_name, ".data");
scn.s_size = ei->ah.dsize;
write_out(fd, (char *)&scn, sizeof(scn));
scn.s_scnptr += dsize;
scn.s_paddr = scn.s_vaddr = ei->ah.bss_start;
strcpy(scn.s_name, ".bss");
scn.s_flags = STYP_BSS;
scn.s_size = ei->ah.bsize;
write_out(fd, (char *)&scn, sizeof(scn));
write_out(fd, coff_blk[0], tsize);
if(pad) {
write_out(fd, pzero, pad);
}
write_out(fd, coff_blk[1], dsize);
/* don't bother to write out the bss segment */
}
LONG
Read(unsigned long fildes, void *bx, unsigned long nbyte, unsigned long *cnt_out)
{
char *buf = (char *)bx;
int cnt;
cnt = read((int)fildes, buf, nbyte);
*cnt_out = cnt;
return (cnt == nbyte) ? 0 : -1;
}
extern void loadbin(char *, unsigned long *, unsigned long);
int
main(int argc, char *argv[])
{
static char *Usage = "Usage: elf2coff [-v] inputfile outputfile\n";
unsigned long pc_junk;
char *src;
if (argc == 3) {
outfile = argv[2];
src = argv[1];
}
else if (argc == 4 && !strcmp(argv[1],"-v")) {
e2c_verbose = 1;
outfile = argv[3];
src = argv[2];
}
else {
fprintf(stderr, Usage);
exit(-1);
}
loadbin(src, &pc_junk, 0);
return 0;
}