ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /utils/5coff/5coff.c/
#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 %llux, ent %llux, txtsz %lux, dataddr %llux\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("%llux %llux %llux %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();
}