summaryrefslogtreecommitdiff
path: root/utils/5coff/5coff.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/5coff/5coff.c')
-rw-r--r--utils/5coff/5coff.c316
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();
+}