diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /utils/5coff/5coff.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'utils/5coff/5coff.c')
| -rw-r--r-- | utils/5coff/5coff.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/utils/5coff/5coff.c b/utils/5coff/5coff.c new file mode 100644 index 00000000..cae73108 --- /dev/null +++ b/utils/5coff/5coff.c @@ -0,0 +1,316 @@ +#include "auxi.h" + +#define RND(x, y) ((((x)+(y)-1)/(y))*(y)) + +char *cmd; +int sflag, dflag; + +int ifd, ofd; +Fhdr ihdr; + +long HEADR, INITTEXT, INITDAT, INITRND, INITENTRY; +long textsize, datsize, bsssize; + +int cout; +int thumb; + +static void get_file(char *); +static void put_file(char *); +static void usage(char *); +static long strxtol(char *); +static void readsyms(void); + +char *fail = "error"; + +void +main(int argc, char *argv[]) +{ + char *a, *ifile, *ofile; + + cmd = argv[0]; + + INITTEXT = -1; + INITDAT = -1; + INITRND = -1; + INITENTRY = -1; + + ARGBEGIN { + /* + * Options without args + */ + case 's': + sflag = 1; + break; + /* + * Options with args + */ + case 'T': + a = ARGF(); + if(a) + INITTEXT = strxtol(a); + break; + case 'D': + a = ARGF(); + if(a) + INITDAT = strxtol(a); + break; + case 'R': + a = ARGF(); + if(a) + INITRND = strxtol(a); + break; + case 'E': + a = ARGF(); + if(a) + INITENTRY = strxtol(a); + break; + case 'd': + dflag |= strxtol(ARGF()); + break; + default: + usage("Invalid option"); + } ARGEND + + if (argc != 2) + usage("Wrong number of arguments"); + + ifile = argv[0]; + ofile = argv[1]; + + get_file(ifile); + put_file(ofile); + exits(0); +} + +char usagemsg[] = +"usage: %s options infile outfile\n\t options (for outfile): -H[1234] -s -T<text> -D<data> -R<rnd> -E<entry>\n"; + +static void +usage(char *msg) +{ + fprint(2, "***Error: %s\n", msg); + fprint(2, usagemsg, cmd); + exits("usage"); +} + +static long +strxtol(char *s) +{ + char *es; + int base = 0; + long r; + + if (*s == '0') + if (*++s == 'x'){ + base = 16; + s++; + } + else + base = 8; + r = strtol(s, &es, base); + if (*es) + usage("bad number"); + return(r); +} + +static void +get_file(char *ifile) +{ + int h; + + ifd = open(ifile, OREAD); + if (ifd < 0) { + fprint(2, "5coff: open %s: %r\n", ifile); + exits("open"); + } + h = crackhdr(ifd, &ihdr); + if (!h || dflag){ + fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, ihdr.type, ihdr.name); + fprint(2, "txt %lux, ent %lux, txtsz %lux, dataddr %lux\n", + ihdr.txtaddr, ihdr.entry, ihdr.txtsz, ihdr.dataddr); + } + if (!h) + usage("File type not recognized"); + machbytype(ihdr.type); + if (dflag) + fprint(2, "name: <%s> pgsize:%ux\n", mach->name, mach->pgsize); + + HEADR = 22+28+3*48; + if(INITTEXT == -1) + INITTEXT = ihdr.txtaddr; + else + ihdr.txtaddr = INITTEXT; + if(INITDAT == -1) + INITDAT = ihdr.dataddr; + else + ihdr.dataddr = INITDAT; + if(INITENTRY == -1) + INITENTRY = ihdr.entry; + else + ihdr.entry = INITENTRY; + textsize = ihdr.txtsz; + datsize = ihdr.datsz; + bsssize = ihdr.bsssz; + if(INITRND > 0) + ihdr.dataddr = INITDAT = RND(INITTEXT+textsize, INITRND); + if(0){ + INITTEXT = INITENTRY; + INITDAT = RND(INITTEXT+textsize, 4); + } + if(0){ + print("H=%lux T=%lux D=%lux t=%lux d=%lux b=%lux e=%lux\n", HEADR, INITTEXT, INITDAT, textsize, datsize, bsssize, INITENTRY); + print("%lux %lux %lux %lux %lux %lux\n", ihdr.txtaddr, ihdr.dataddr, ihdr.entry, ihdr.txtsz, ihdr.datsz, ihdr.bsssz); + } + + readsyms(); +} + +#define WB 128 +#define WSAFE (WB-4) +char Wbuf[WB]; +char *wp = Wbuf; + +void +cflush(void) +{ + if(wp > Wbuf) + write(ofd, Wbuf, wp-Wbuf); + wp = Wbuf; +} + +void +lput(long l) +{ + wp[0] = l>>24; + wp[1] = l>>16; + wp[2] = l>>8; + wp[3] = l; + wp += 4; + if(wp >= Wbuf+WSAFE) + cflush(); +} + +void +cput(int l) +{ + wp[0] = l; + wp += 1; + if(wp >= Wbuf+WSAFE) + cflush(); +} + +void +hputl(int l) +{ + wp[1] = l>>8; + wp[0] = l; + wp += 2; + if(wp >= Wbuf+WSAFE) + cflush(); +} + +void +lputl(long l) +{ + wp[3] = l>>24; + wp[2] = l>>16; + wp[1] = l>>8; + wp[0] = l; + wp += 4; + if(wp >= Wbuf+WSAFE) + cflush(); +} + +static void +copyseg(long sz) +{ + char buf[1024]; + + cflush(); + while (sz > 0){ + long n; + long r; + + n = sz; + if (n > sizeof buf) + n = sizeof buf; + sz -= n; + + if ((r = read(ifd, buf, n)) != n){ + fprint(2, "%ld = read(...%ld) at %ld\n", r, n, (long)seek(ifd, 0, 1)); + perror("Premature eof"); + exits(fail); + } + if ((r = write(ofd, buf, n)) != n){ + fprint(2, "%ld = write(...%ld)\n", r, n); + perror("Write error!"); + exits(fail); + } + } + cflush(); +} + +static void +put_file(char *ofile) +{ + ofd = create(ofile, OWRITE, 0666); + if (ofd < 0) { + fprint(2, "5coff: create %s: %r\n", ofile); + exits("create"); + } + cout = ofd; + + /* TBS lput for Plan9 header before ? */ + + seek(ifd, ihdr.txtoff, 0); + seek(ofd, HEADR, 0); + copyseg(ihdr.txtsz); + + seek(ifd, ihdr.datoff, 0); + seek(ofd, HEADR+textsize, 0); + copyseg(ihdr.datsz); + + seek(ofd, HEADR+textsize+datsize, 0); + coffsym(); + cflush(); + cofflc(); + cflush(); + + seek(ofd, 0, 0); + coffhdr(); + cflush(); + + close(ifd); + close(ofd); +} + +long +entryvalue(void) +{ + return INITENTRY; +} + +void +diag(char *s, ...) +{ + fprint(2, "%s\n", s); + exits("error"); +} + +static void +readsyms(void) +{ + int i; + long n; + Sym *s; + + if(sflag) + return; + n = syminit(ifd, &ihdr); + beginsym(); + for(i = 0; i < n; i++){ + s = getsym(i); + newsym(i, s->name, s->value, s->type); + } + endsym(); +} |
