Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: unc - 68000 disassembler (Part 2 of 2) Message-ID: <1519@panda.UUCP> Date: 14 Mar 86 15:00:16 GMT Sender: jpn@panda.UUCP Lines: 2888 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 31 Submitted by: turner@imagen.UUCP #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # iset.c # libmtch.c # main.c # prin.c # robj.c # This archive created: Thu Mar 13 18:56:11 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'iset.c'" '(19541 characters)' if test -f 'iset.c' then echo shar: will not over-write existing file "'iset.c'" else cat << \SHAR_EOF > 'iset.c' /* * SCCS: @(#)iset.c 1.2 11/2/84 14:18:23 * Decode instructions. * *********************************************************************** * This software is copyright of * * John M Collins * 47 Cedarwood Drive * St Albans * Herts, AL4 0DN * England +44 727 57267 * * and is released into the public domain on the following conditions: * * 1. No free maintenance will be guaranteed. * 2. Nothing may be based on this software without * acknowledgement, including incorporation of this * notice. * * Notwithstanding the above, the author welcomes correspondence and bug * fixes. *********************************************************************** */ #include #include #include "unc.h" ef_fids mainfile; long endt; void gette(), putte(); void mkdref(); long gettw(); symbol textlab(); int l1(), l2(), el1(), lea(), lmove(), lcbch(), jj(); int limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel(); int pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg(); int pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea(); int plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg(); int pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf(); struct opstr { unsigned short mask; unsigned short match; int (*opsize)(); int (*opprin)(); char *prarg; } optab[] = { 0xf000, 0x2000, lmove, pmove, "l", 0xf000, 0x3000, lmove, pmove, "w", 0xf000, 0x1000, lmove, pmove, "b", 0xf000, 0x6000, lcbch, pcbch, 0, 0xffbf, 0x003c, l2, pcs, "or", 0xff00, 0x0000, limed, pimed, "or", 0xffbf, 0x023c, l2, pcs, "and", 0xff00, 0x0200, limed, pimed, "and", 0xff00, 0x0400, limed, pimed, "sub", 0xff00, 0x0600, limed, pimed, "add", 0xffbf, 0x0a3c, l2, pcs, "eor", 0xff00, 0x0a00, limed, pimed, "eor", 0xff00, 0x0c00, limed, pimed, "cmp", 0xf138, 0x0108, l2, pmovp, 0, 0xff00, 0x0800, lsbit, psbit, 0, 0xf100, 0x0100, lonew, pdbit, 0, 0xffc0, 0x40c0, lonew, pcs2, "sr", 0xff00, 0x4000, lone, pone, "negx", 0xff00, 0x4200, lone, pone, "clr", 0xffc0, 0x44c0, lonew, pcs2, "cc", 0xff00, 0x4400, lone, pone, "neg", 0xffc0, 0x46c0, lonew, pcs2, "sr", 0xff00, 0x4600, lone, pone, "not", 0xffc0, 0x4800, lonew, ppea, "nbcd", 0xfff8, 0x4840, l1, pdreg, "swap", 0xffc0, 0x4840, lonel, ppea, "pea", 0xfff8, 0x4880, l1, pdreg, "extw", 0xfff8, 0x48c0, l1, pdreg, "extl", 0xfb80, 0x4880, lmvml, pmvml, 0, 0xffc0, 0x4ac0, lonew, ppea, "tas", 0xff00, 0x4a00, lone, pone, "tst", 0xfff0, 0x4e40, l1, ptrap, 0, 0xfff8, 0x4e50, l2, plink, 0, 0xfff8, 0x4e58, l1, pareg, "unlk\t%s", 0xfff8, 0x4e60, l1, pareg, "movl\t%s,usp", 0xfff8, 0x4e68, l1, pareg, "movl\tusp,%s", 0xffff, 0x4e70, l1, pareg, "reset", 0xffff, 0x4e71, l1, pareg, "nop", 0xffff, 0x4e72, l2, pstop, 0, 0xffff, 0x4e73, el1, pareg, "rte", 0xffff, 0x4e75, el1, pareg, "rts", 0xffff, 0x4e76, l1, pareg, "trapv", 0xffff, 0x4e77, el1, pareg, "rtr", 0xfffe, 0x4e7a, l2, pmovc, 0, 0xffc0, 0x4e80, jj, ppea, "jsr", 0xffc0, 0x4ec0, jj, ppea, "jmp", 0xf1c0, 0x4180, lonew, podreg,"chk", 0xf1c0, 0x41c0, lonel, plea, 0, 0xf0f8, 0x50c8, lcbch, pdbcc, 0, 0xf0c0, 0x50c0, lonew, pscc, 0, 0xf100, 0x5000, lone, pqu, "add", 0xf100, 0x5100, lone, pqu, "sub", 0xf100, 0x7000, l1, pmqu, 0, 0xf1c0, 0x80c0, lonew, podreg,"divu", 0xf1c0, 0x81c0, lonew, podreg,"divs", 0xf1f0, 0x8100, l1, ptreg, "sbcd", 0xf000, 0x8000, loone, pomode,"or", 0xf1f0, 0x9100, l1, ptreg, "subxb", 0xf1f0, 0x9140, l1, ptreg, "subxw", 0xf1f0, 0x9180, l1, ptreg, "subxl", 0xf000, 0x9000, loone, pomode,"sub", 0xf1f8, 0xb108, l1, pcmpm, "cmpmb", 0xf1f8, 0xb148, l1, pcmpm, "cmpmw", 0xf1f8, 0xb188, l1, pcmpm, "cmpml", 0xf100, 0xb000, loone, pomode,"cmp", 0xf1c0, 0xb1c0, loone, pomode,"cmp", 0xf100, 0xb100, loone, pomode,"eor", 0xf1c0, 0xc0c0, lonew, podreg,"mulu", 0xf1c0, 0xc1c0, lonew, podreg,"muls", 0xf1f0, 0xc100, l1, ptreg, "abcd", 0xf130, 0xc100, l1, pexg, 0, 0xf000, 0xc000, loone, pomode,"and", 0xf1f0, 0xd100, l1, ptreg, "addxb", 0xf1f0, 0xd140, l1, ptreg, "addxw", 0xf1f0, 0xd180, l1, ptreg, "addxl", 0xf000, 0xd000, loone, pomode,"add", 0xf8c0, 0xe0c0, lonew, pmshf, 0, 0xf000, 0xe000, l1, pshf, 0, 0 }; char *areg[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp"}; char *cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"}; char *shtype[] = { "as", "ls", "rox", "ro" }; char *bittyp[] = { "tst", "chg", "clr", "set" }; char *creg[] = { "sfc", "dfc", "usp", "vbr" }; /* * Length functions. */ int l1() { return 1; } int l2() { return 2; } int el1(te) t_entry *te; { te->t_bchtyp = T_UNBR; return 1; } int lea(instr, size, pos) unsigned instr, size; long pos; { switch ((instr >> 3) & 0x7) { case 0: case 1: case 2: case 3: case 4: return 1; case 5: case 6: return 2; default: switch (instr & 0x7) { case 0: case 2: case 3: return 2; case 1: mkdref(pos, size); return 3; case 4: if (size > 2) return 3; return 2; default: return 0; } } } /* * Lengths of move instructions. */ int lmove(te, pos) t_entry *te; long pos; { register unsigned tc = te->t_contents; unsigned sz = 1; int lng, lng2; lng = tc & 0xf000; if (lng == 0x3000) sz = 2; else if (lng == 0x2000) sz = 4; if ((lng = lea(tc, sz, pos+2)) <= 0) return 0; lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng); if (lng2 <= 0) return 0; return lng + lng2 - 1; } /* * Lengths for conditional branches and dbcc instructions. */ int lcbch(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; long dest = pos + 2; int res = 2; if ((tc & 0xf000) == 0x5000 || (tc & 0xff) == 0) dest += (short)gettw(&mainfile, pos+2, R_WORD); else { dest += (char) tc; res = 1; } if ((tc & 0xff00) == 0x6000) te->t_bchtyp = T_UNBR; else if ((tc & 0xff00) == 0x6100) te->t_bchtyp = T_JSR; else te->t_bchtyp = T_CONDBR; te->t_relsymb = textlab(dest, pos); return res; } int jj(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; t_entry nextl; te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR; if ((tc & 0x3f) == 0x39) { gette(&mainfile, pos+2, &nextl); if (nextl.t_relsymb == NULL) { nextl.t_relsymb = textlab(gettw(&mainfile, pos+2, R_LONG), pos); putte(&mainfile, pos+2, &nextl); } te->t_relsymb = nextl.t_relsymb; /* Easy ref */ } return lea(tc, 4, pos+2); } int limed(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; int lng; /* * Specifically exclude byte address register operands, * and ones which have lengths of 3. */ if ((tc & 0xf8) == 0x08) return 0; if ((tc & 0xc0) >= 0x80) { if (tc & 0x40) return 0; lng = lea(tc, 4, pos+6); if (lng > 0) lng += 2; } else { lng = lea(tc, (unsigned)((tc & 0xc0)?2:1), pos+4); if (lng > 0) lng++; } return lng; } int lsbit(te, pos) t_entry *te; long pos; { int lng = lea(te->t_contents, 1, pos+4); if (lng > 0) lng++; return lng; } int lmvml(te, pos) t_entry *te; long pos; { int lng = lea(te->t_contents, (unsigned)(te->t_contents&0x40? 4:2), pos+4); if (lng > 0) lng++; return lng; } /* * Length depends on bits 6 and 7 of instruction. */ int lone(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; return lea(tc, 1 << ((tc >> 6) & 3), pos+2); } /* * Length depends on bits 6-8 of instruction. */ int loone(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; switch ((tc >> 6) & 7) { case 0: case 4: return lea(tc, 1, pos+2); case 1: case 3: case 5: return lea(tc, 2, pos+2); case 2: case 6: case 7: return lea(tc, 4, pos+2); } /*NOTREACHED*/ } int lonew(te, pos) t_entry *te; long pos; { return lea(te->t_contents, 2, pos+2); } int lonel(te, pos) t_entry *te; long pos; { return lea(te->t_contents, 4, pos+2); } /* * Print routines. */ int findleng(tc) unsigned tc; { switch ((tc >> 6) & 3) { case 0: return 'b'; case 1: return 'w'; default: return 'l'; } } void piword(disp) unsigned disp; { int szc; (void) printf("@(0x%x,", disp & 0xff); if (disp & 0x8000) (void) printf("%s", areg[(disp >> 12) & 0x7]); else (void) printf("d%d", (disp >> 12) & 0x7); szc = 'w'; if (disp & (1 << 10)) szc = 'l'; (void) printf(":%c)", szc); } void paddr(pos) long pos; { t_entry tent; symbol symb; gette(&mainfile, pos, &tent); if (tent.t_relsymb != NULL) { symb = tent.t_relsymb; if (symb->s_lsymb != 0) (void) printf("%u$", symb->s_lsymb); else (void) printf("%s", symb->s_name); if (tent.t_reldisp != 0) (void) printf("+0x%x", tent.t_reldisp); return; } (void) printf("0x%x", gettw(&mainfile, pos, R_LONG)); } int prea(ea, pos, sz) unsigned ea, sz; long pos; /* Address of previous word to extn */ { unsigned reg = ea & 0x7; long disp; pos += 2; switch ((ea >> 3) & 0x7) { case 0: (void) printf("d%d", reg); return 0; case 1: (void) printf("%s", areg[reg]); return 0; case 2: (void) printf("%s@", areg[reg]); return 0; case 3: (void) printf("%s@+", areg[reg]); return 0; case 4: (void) printf("%s@-", areg[reg]); return 0; case 5: disp = gettw(&mainfile, pos, R_WORD); (void) printf("%s@(0x%x)", areg[reg], disp); return 2; case 6: (void) printf("%s", areg[reg]); piword((unsigned) gettw(&mainfile, pos, R_WORD)); return 2; default: switch (reg) { case 0: disp = gettw(&mainfile, pos, R_WORD); (void) printf("0x%x:w", disp); return 2; case 1: paddr(pos); return 4; case 2: disp = gettw(&mainfile, pos, R_WORD); (void) printf("pc@(0x%x)", disp); return 2; case 3: (void) printf("pc"); piword((unsigned) gettw(&mainfile, pos, R_WORD)); return 2; case 4: (void) printf("#"); if (sz < 4) (void) printf("0x%x", gettw(&mainfile, pos, R_WORD)); else paddr(pos); return sz; default: (void) fprintf(stderr, "Funny mode\n"); exit(220); } } /*NOTREACHED*/ } int pmove(te, pos) t_entry *te; long pos; { unsigned sz = 2; unsigned tc = te->t_contents; (void) printf("mov%s\t", optab[te->t_iindex].prarg); if ((tc & 0xf000) == 0x2000) sz = 4; pos += prea(tc, pos, sz); putchar(','); (void) prea(((tc >> 9) & 0x7) | ((tc >> 3) & 0x38), pos, sz); } int pcbch(te) t_entry *te; { int cc = ((te->t_contents >> 8) & 0xf) - 2; char *msg; register symbol ts; if (cc < 0) msg = cc < -1? "ra": "sr"; else msg = cclist[cc]; (void) printf("b%s", msg); if (te->t_lng < 2) (void) printf("s"); ts = te->t_relsymb; if (ts->s_lsymb != 0) (void) printf("\t%u$", ts->s_lsymb); else (void) printf("\t%s", ts->s_name); } int pdbcc(te) t_entry *te; { unsigned tc = te->t_contents; int cc = ((tc >> 8) & 0xf) - 2; char *msg; register symbol ts; if (cc < 0) msg = cc < -1? "t": "f"; else msg = cclist[cc]; ts = te->t_relsymb; (void) printf("db%s\td%d,", msg, tc & 0x7); if (ts->s_lsymb) (void) printf("%u$", ts->s_lsymb); else (void) printf("%s", ts->s_name); } int pscc(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; int cc = ((tc >> 8) & 0xf) - 2; char *msg; if (cc < 0) msg = cc < -1? "t": "f"; else msg = cclist[cc]; (void) printf("s%s\t", msg); (void) prea(tc, pos, 1); } int pcs(te, pos) t_entry *te; long pos; { long disp = gettw(&mainfile, pos+2, R_WORD); (void) printf("%s", optab[te->t_iindex].prarg); if ((te->t_contents & 0xc0) == 0) (void) printf("b\t#0x%x,cc", disp); else (void) printf("w\t#0x%x,sr", disp); } int pmovc(te, pos) t_entry *te; long pos; { int disp = gettw(&mainfile, pos+2, R_WORD); int ctrl = ((disp >> 10) & 2) | (disp & 1); (void) printf("movec\t"); if ((te->t_contents & 1) == 0) (void) printf("%s,", creg[ctrl]); if (disp & 0x8000) (void) printf("%s", areg[(disp >> 12) & 7]); else (void) printf("d%d", disp >> 12); if (te->t_contents & 1) (void) printf(",%s", creg[ctrl]); } int pimed(te, pos) t_entry *te; long pos; { int sz = findleng(te->t_contents); (void) printf("%s%c\t#", optab[te->t_iindex].prarg, sz); if (sz == 'l') { paddr(pos+2); putchar(','); (void) prea(te->t_contents, pos+4, 4); } else { (void) printf("0x%x,", gettw(&mainfile, pos+2, R_WORD)); (void) prea(te->t_contents, pos+2, 2); } } int pmovp(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; long disp = gettw(&mainfile, pos+2, R_WORD); int dreg = tc >> 9; char *ar = areg[tc & 0x7]; (void) printf("movep"); if (tc & (1 << 6)) putchar('l'); else putchar('w'); if (tc & (1 << 7)) (void) printf("\td%d,%s@(0x%x)", dreg, ar, disp); else (void) printf("\t%s@(0x%x),d%d", ar, disp, dreg); } int psbit(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; (void) printf("b%s\t#%d,", bittyp[(tc >> 6) & 0x3], gettw(&mainfile, pos+2, R_WORD)); (void) prea(tc, pos+2, 1); } /*ARGSUSED*/ int pstop(te, pos) t_entry *te; long pos; { (void) printf("stop\t#0x%x", gettw(&mainfile, pos+2, R_WORD)); } int pdbit(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; (void) printf("b%s\td%d,", bittyp[(tc >> 6) & 0x3], (tc >> 9) & 0x7); (void) prea(tc, pos, 1); } int pcs2(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; (void) printf("movw\t"); if ((tc & 0xffc0) == 0x40c0) { (void) printf("sr,"); (void) prea(tc, pos, 2); } else { (void) prea(tc, pos, 2); (void) printf(",%s", optab[te->t_iindex].prarg); } } int pone(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; int sz = findleng(tc); (void) printf("%s%c\t", optab[te->t_iindex].prarg, sz); (void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2)); } int ppea(te, pos) /* nbcd, pea, tas, jmp, jsr */ t_entry *te; long pos; { (void) printf("%s\t", optab[te->t_iindex].prarg); (void) prea(te->t_contents, pos, (unsigned)(te->t_lng > 2? 4: 2)); } int plea(te, pos) t_entry *te; long pos; { (void) printf("lea\t"); (void) prea(te->t_contents, pos, 4); (void) printf(",%s", areg[(te->t_contents >> 9) & 0x7]); } int pdreg(te) t_entry *te; { (void) printf("%s\td%d", optab[te->t_iindex].prarg, te->t_contents & 7); } int pmvml(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; register unsigned dw = gettw(&mainfile, pos+2, R_WORD); unsigned sz = 4; int sc = 'l'; register int i; register unsigned bit; (void) printf("movem"); if ((tc & 0x40) == 0) { sc = 'w'; sz = 2; } (void) printf("%c\t", sc); if (tc & 0x400) { (void) prea(tc, pos+2, sz); (void) printf(",#0x%x", dw); } else { (void) printf("#0x%x,", dw); (void) prea(tc, pos+2, sz); } (void) printf("\t|"); if ((tc & 0x38) == 0x20) { bit = 0x8000; for (i = 0; i < 8; i++) { if (dw & bit) (void) printf(" d%d", i); bit >>= 1; } for (i = 0; i < 8; i++) { if (dw & bit) (void) printf(" %s", areg[i]); bit >>= 1; } } else { bit = 1; for (i = 0; i < 8; i++) { if (dw & bit) (void) printf(" d%d", i); bit <<= 1; } for (i = 0; i < 8; i++) { if (dw & bit) (void) printf(" %s", areg[i]); bit <<= 1; } } } int ptrap(te) t_entry *te; { (void) printf("trap\t#0x%x", te->t_contents & 0xf); } int plink(te, pos) t_entry *te; long pos; { (void) printf("link\t%s,#0x%x", areg[te->t_contents & 0x7], gettw(&mainfile, pos+2, R_WORD)); } int pareg(te) t_entry *te; { (void) printf(optab[te->t_iindex].prarg, areg[te->t_contents & 0x7]); } int podreg(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; (void) printf("%s\t", optab[te->t_iindex].prarg); (void) prea(tc, pos, 2); (void) printf(",d%d", (tc >> 9) & 0x7); } int pqu(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; int sz = findleng(tc); int amt = (tc >> 9) & 0x7; if (amt == 0) amt = 8; (void) printf("%sq%c\t#%d,", optab[te->t_iindex].prarg, sz, amt); (void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2)); } int pmqu(te) t_entry *te; { unsigned tc = te->t_contents; (void) printf("moveq\t#0x%x,d%d", (char)tc, (tc >> 9) & 0x7); } int ptreg(te) t_entry *te; { register unsigned tc = te->t_contents; int rx = (tc >> 9) & 0x7; int ry = tc & 0x7; (void) printf("%s\t", optab[te->t_iindex].prarg); if (tc & 0x8) (void) printf("%s@-,%s@-", areg[ry], areg[rx]); else (void) printf("d%d,d%d", ry, rx); } int pcmpm(te) t_entry *te; { register unsigned tc = te->t_contents; (void) printf("%s\t%s@+,%s@+", optab[te->t_iindex].prarg, areg[tc & 7], areg[(tc >> 9) & 7]); } int pomode(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; char bef[4], aft[4]; int sz; int reg = (tc >> 9) & 7; bef[0] = aft[0] = '\0'; switch ((tc >> 6) & 7) { case 0: sz = 'b'; goto toreg; case 1: sz = 'w'; goto toreg; case 2: sz = 'l'; toreg: (void) sprintf(aft, ",d%d", reg); break; case 3: sz = 'w'; goto toareg; case 7: sz = 'l'; toareg: (void) sprintf(aft, ",%s", areg[reg]); break; case 4: sz = 'b'; goto frreg; case 5: sz = 'w'; goto frreg; case 6: sz = 'l'; frreg: (void) sprintf(bef, "d%d,", reg); break; } (void) printf("%s%c\t%s", optab[te->t_iindex].prarg, sz, bef); (void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2)); (void) printf(aft); } int pexg(te) t_entry *te; { unsigned tc = te->t_contents; int r1 = (tc >> 9) & 7, r2 = tc & 7; (void) printf("exg\t"); if ((tc & 0x00f8) == 0x0048) (void) printf("%s,", areg[r1]); else (void) printf("d%d,", r1); if (tc & 0x8) (void) printf("%s", areg[r2]); else (void) printf("d%d", r2); } int pmshf(te, pos) t_entry *te; long pos; { unsigned tc = te->t_contents; (void) printf("%s%cw\t", shtype[(tc >> 9) & 3], tc & 0x100? 'l': 'r'); (void) prea(tc, pos, 2); } int pshf(te) t_entry *te; { unsigned tc = te->t_contents; int sz = findleng(tc); int disp = (tc >> 9) & 7; (void) printf("%s%c%c\t", shtype[(tc >> 3) & 3], tc & 0x100? 'l': 'r', sz); if (tc & 0x20) (void) printf("d%d", disp); else (void) printf("#%d", disp == 0? 8: disp); (void) printf(",d%d", tc & 7); } /* * Find length etc of instruction. */ int findinst(te, pos) register t_entry *te; long pos; { register struct opstr *op; unsigned tc = te->t_contents; int lng = 0; register int i; te->t_type = T_BEGIN; te->t_bchtyp = T_NOBR; for (op = &optab[0]; op->mask; op++) { if ((tc & op->mask) == op->match) { te->t_iindex = op - optab; lng = (op->opsize)(te, pos); break; } } for (i = 1; i < lng; i++) { t_entry ctent; long npos = pos+i+i; if (npos >= endt) goto clearem; gette(&mainfile, npos, &ctent); if (ctent.t_bdest || ctent.t_dref) { clearem: for (i--; i > 0; i--) { npos = pos + i + i; gette(&mainfile, npos, &ctent); ctent.t_type = T_UNKNOWN; putte(&mainfile, npos, &ctent); } lng = 0; goto ginv; } ctent.t_type = T_CONT; putte(&mainfile, npos, &ctent); } if (lng <= 0) { ginv: te->t_vins = 0; te->t_lng = 1; te->t_type = T_UNKNOWN; te->t_bchtype = T_NOBR; } else te->t_lng = lng; return lng; } /* * Print instruction. */ void prinst(te, pos) t_entry *te; long pos; { putchar('\t'); (optab[te->t_iindex].opprin)(te, pos); putchar('\n'); } SHAR_EOF if test 19541 -ne "`wc -c < 'iset.c'`" then echo shar: error transmitting "'iset.c'" '(should have been 19541 characters)' fi fi echo shar: extracting "'libmtch.c'" '(7242 characters)' if test -f 'libmtch.c' then echo shar: will not over-write existing file "'libmtch.c'" else cat << \SHAR_EOF > 'libmtch.c' /* * SCCS: @(#)libmtch.c 1.2 11/2/84 14:18:55 * Read library files. * *********************************************************************** * This software is copyright of * * John M Collins * 47 Cedarwood Drive * St Albans * Herts, AL4 0DN * England +44 727 57267 * * and is released into the public domain on the following conditions: * * 1. No free maintenance will be guaranteed. * 2. Nothing may be based on this software without * acknowledgement, including incorporation of this * notice. * * Notwithstanding the above, the author welcomes correspondence and bug * fixes. *********************************************************************** */ #include #include #include #include #include #include "unc.h" long lseek(); void bfopen(), bfclose(), nomem(); void rrell2(), markmatch(); char *strchr(), *strrchr(), *strncpy(), *strcat(), *strcpy(), *malloc(); int matchup(); long findstart(); char verbose; /* Tell the world what we are doing */ char *tfnam; char *cfile; ef_fids mainfile; struct commit dreltab; int donedrel, donebrel; long trelpos, drelpos, brelpos; static struct libit currlib = {-1, 0, -1, ""}; void lclash(str) char *str; { (void) fprintf(stderr, "Library scan failure - %s\n", str); (void) fprintf(stderr, "Searching %s\n", cfile); if (currlib.lf_name[0]) (void) fprintf(stderr, "Member is %s\n", currlib.lf_name); exit(255); } /* * Find next member. */ long nextmemb(lfd) register struct libit *lfd; { struct ar_hdr arbuf; if (lfd->lf_next < 0) return -1; (void) lseek(lfd->lf_fd, lfd->lf_next, 0); if (read(lfd->lf_fd, (char *)&arbuf, sizeof(arbuf)) != sizeof(arbuf)) { lfd->lf_next = -1; return -1; } (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name)); lfd->lf_offset = lfd->lf_next + sizeof(arbuf); lfd->lf_next = (lfd->lf_offset + arbuf.ar_size + 1) & ~1; return lfd->lf_offset; } /* * Decode a file name thus - * * -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc * -Lxxx forget "lib" ".a" bit thus -Lcrt0.o * or read LDPATH environment var to give list of directories as sh * (default /lib:/usr/lib). * * Alternatively treat as normal pathname. * * File names may be followed by (membername) if the file is an archive, * thus * * -lc(printf.o) * * in which case the specified module is fetched. */ struct libit *getfnam(str) char *str; { char *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL; static char *pathn; extern char *getenv(); long magic; struct ar_hdr arhdr; int fd; if ((bp = strrchr(str, '(')) != NULL && (ep = strrchr(str, ')')) != NULL) *ep = *bp = '\0'; if (str[0] == '-' && (str[1] == 'l' || str[1] == 'L')) { if (pathn == NULL) { if ((pathn = getenv("LDPATH")) == NULL) pathn = "/lib:/usr/lib"; } fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1)); if (fullpath == NULL) nomem(); pathb = pathn; do { pathe = strchr(pathb, ':'); if (*pathb == ':') fullpath[0] = '\0'; else { if (pathe != NULL) *pathe = '\0'; (void) strcpy(fullpath, pathb); (void) strcat(fullpath, "/"); if (pathe != NULL) *pathe = ':'; } if (str[1] == 'l') (void) strcat(fullpath, "lib"); (void) strcat(fullpath, &str[2]); if (str[1] == 'l') (void) strcat(fullpath, ".a"); if ((fd = open(fullpath, O_RDONLY)) >= 0) goto found; pathb = pathe + 1; } while (pathe != NULL); (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n", &str[2], pathn); exit(101); } else if ((fd = open(str, O_RDONLY)) < 0) { (void) fprintf(stderr, "Cannot open %s\n", str); exit(102); } found: if ((read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic) || magic != ARMAG)) { if (ep != NULL) { (void) fprintf(stderr, "%s is not library file\n", fullpath != NULL? fullpath: str); exit(103); } if (fullpath != NULL) free(fullpath); currlib.lf_fd = fd; currlib.lf_offset = 0; currlib.lf_next = -1; currlib.lf_name[0] = '\0'; return &currlib; } /* * It appears to be a library file - see if we want a specific * one. */ if (ep != NULL) { currlib.lf_offset = sizeof(magic) + sizeof(struct ar_hdr); for (;;) { if (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr)) { (void) fprintf(stderr, "Cannot find member %s in %s\n", bp+1, fullpath?fullpath: str); exit(103); } if (strncmp(bp+1, arhdr.ar_name, sizeof(arhdr.ar_name)) == 0) break; currlib.lf_offset += arhdr.ar_size + sizeof(arhdr) + 1; currlib.lf_offset &= ~ 1; (void) lseek(fd, (long)(currlib.lf_offset - sizeof(arhdr)), 0); } if (fullpath != NULL) free(fullpath); currlib.lf_fd = fd; currlib.lf_next = -1; currlib.lf_name[0] = '\0'; *bp = '('; *ep = ')'; return &currlib; } /* * Otherwise point to 1st member in library. */ if (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr)) { (void) fprintf(stderr, "Library %s empty\n", fullpath? fullpath: str); exit(104); } if (fullpath != NULL) free(fullpath); currlib.lf_offset = sizeof(magic) + sizeof(arhdr); currlib.lf_next = currlib.lf_offset + arhdr.ar_size + 1; currlib.lf_next &= ~1; currlib.lf_fd = fd; (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name)); return &currlib; } /* * Process library files. */ #define MINTEXT 6 void lscan(nfiles, fnames) int nfiles; char **fnames; { ef_fids libfile; register ef_fid ll = &libfile; register struct libit *clf; extern symbol dolsymb(); int firstfile; for (; nfiles > 0; fnames++, nfiles--) { clf = getfnam(*fnames); cfile = *fnames; firstfile = 1; do { bfopen(tfnam, ll); /* * If file is garbled, silently forget it and go * on to the next one. */ if (!rtext(clf->lf_fd, clf->lf_offset, ll)) goto closeit; if (ll->ef_tsize < MINTEXT) goto closeit; if (!rdata(clf->lf_fd, clf->lf_offset, ll)) goto closeit; if (rrell1(clf->lf_fd, clf->lf_offset, ll) < 0) goto closeit; /* * If first file in library, find it from * beginning of main file. */ if (firstfile) { if ((trelpos = findstart(&mainfile, ll)) < 0) goto closeit; firstfile = 0; } else if (!matchup(&mainfile, ll, trelpos)) goto closeit; /* * Found a match. */ if (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll)) { (void) fprintf(stderr, "Corrupt file %s\n", *fnames); exit(150); } donedrel = 0; donebrel = 0; rrell2(clf->lf_fd, clf->lf_offset, ll); if (verbose) { (void) fprintf(stderr, "Found: "); if (clf->lf_name[0]) (void) fprintf(stderr, "%.14s in ", clf->lf_name); (void) fprintf(stderr, "%s\n", *fnames); } if (libfile.ef_stvec != NULL) { free(libfile.ef_stvec); libfile.ef_stvec = NULL; libfile.ef_stcnt = 0; } dreltab.c_int = 0; /* * Start looking next time round * where last one left off. */ markmatch(&mainfile, ll, trelpos); trelpos += libfile.ef_tsize; closeit: bfclose(ll); } while (nextmemb(clf) >= 0); } } SHAR_EOF if test 7242 -ne "`wc -c < 'libmtch.c'`" then echo shar: error transmitting "'libmtch.c'" '(should have been 7242 characters)' fi fi echo shar: extracting "'main.c'" '(6255 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else cat << \SHAR_EOF > 'main.c' /* * SCCS: @(#)main.c 1.2 11/2/84 14:19:31 * Main routine etc. * *********************************************************************** * This software is copyright of * * John M Collins * 47 Cedarwood Drive * St Albans * Herts, AL4 0DN * England +44 727 57267 * * and is released into the public domain on the following conditions: * * 1. No free maintenance will be guaranteed. * 2. Nothing may be based on this software without * acknowledgement, including incorporation of this * notice. * * Notwithstanding the above, the author welcomes correspondence and bug * fixes. *********************************************************************** */ #include #include #include #include #include "unc.h" #define LINELNG 70 void inturdat(), intutext(), intudat(), intlsym(); void ptext(), pdata(), pabs(), pbss(), lscan(); ef_fids mainfile; int par_entry, par_round; /* 68000 parameters */ int nmods; /* Number of modules it looks like */ char *tfnam = "split"; char lsyms; /* Generate local symbols */ char verbose; /* Tell the world what we are doing */ char noabs; /* No non-global absolutes */ int rel; /* File being analysed is relocatable */ int lpos; symbol dosymb(); struct libit *getfnam(); /* * Get hex characters, also allowing for 'k' and 'm'. */ int ghex(str) register char *str; { register int result = 0; register int lt; for (;;) { lt = *str++; switch (lt) { default: err: (void) fprintf(stderr, "Invalid hex digit \'%c\'\n", lt); exit(1); case '\0': return result; case '0':case '1':case '2':case '3':case '4': case '5':case '6':case '7':case '8':case '9': result = (result << 4) + lt - '0'; continue; case 'a':case 'b':case 'c':case 'd':case 'e':case 'f': result = (result << 4) + lt - 'a' + 10; continue; case 'A':case 'B':case 'C':case 'D':case 'E':case 'F': result = (result << 4) + lt - 'A' + 10; continue; case 'k':case 'K': if (*str != '\0') goto err; return result << 10; case 'm':case 'M': if (*str != '\0') goto err; return result << 20; } } } /* * Process entry line options. Return number dealt with. */ int doopts(av) char *av[]; { register int cnt = 0, lt; register char *arg; struct var vs; uvar(&vs); par_entry = vs.v_ustart; par_round = vs.v_txtrnd - 1; for (;;) { arg = *++av; if (*arg++ != '-') return cnt; cnt++; nx: switch (lt = *arg++) { default: (void) fprintf(stderr, "Bad option -%c\n", lt); exit(1); case '\0': continue; case 'l': /* A file name */ case 'L': return cnt - 1; case 's': lsyms++; goto nx; case 'v': verbose++; goto nx; case 'a': noabs++; goto nx; case 'R': case 'N': if (*arg == '\0') { cnt++; arg = *++av; if (arg == NULL) { bo: (void) fprintf(stderr,"Bad -%c option\n",lt); exit(1); } } if (lt == 'R') par_entry = ghex(arg); else par_round = ghex(arg) - 1; continue; case 't': if (*arg == '\0') { cnt++; arg = *++av; if (arg == NULL) goto bo; } tfnam = arg; continue; case 'o': if (*arg == '\0') { cnt++; arg = *++av; if (arg == NULL) goto bo; } if (freopen(arg, "w", stdout) == NULL) { (void) fprintf(stderr, "Help! cant open %s\n", arg); exit(20); } continue; } } } /* * Open binary files. Arrange to erase them when finished. */ void bfopen(nam, fid) char *nam; ef_fid fid; { char fnam[80]; (void) sprintf(fnam, "%s.tx", nam); if ((fid->ef_t = open(fnam, O_RDWR|O_CREAT, 0666)) < 0) { efil: (void) fprintf(stderr, "Help could not open %s\n", fnam); exit(4); } (void) unlink(fnam); (void) sprintf(fnam, "%s.dt", nam); if ((fid->ef_d = open(fnam, O_RDWR|O_CREAT, 0666)) < 0) goto efil; (void) unlink(fnam); } /* * Close binary files. They should get zapped anyway. */ void bfclose(fid) ef_fid fid; { (void) close(fid->ef_t); (void) close(fid->ef_d); } /* * Main routine. */ main(argc, argv) int argc; char *argv[]; { int i; char *progname = argv[0]; char *msg; register struct libit *lfd; i = doopts(argv); argc -= i; argv += i; if (argc < 2) { (void) fprintf(stderr, "Usage: %s [ options ] file\n", progname); exit(1); } lfd = getfnam(argv[1]); if (lfd->lf_next > 0) { (void) fprintf(stderr, "Main file (%s) cannot be library\n", argv[1]); exit(2); } bfopen(tfnam, &mainfile); if (verbose) (void) fprintf(stderr, "Scanning text\n"); if (!rtext(lfd->lf_fd, lfd->lf_offset, &mainfile)) { msg = "text"; bf: (void) fprintf(stderr, "Bad format input file - reading %s\n", msg); exit(5); } if (verbose) (void) fprintf(stderr, "Scanning data\n"); if (!rdata(lfd->lf_fd, lfd->lf_offset, &mainfile)) { msg = "data"; goto bf; } if (verbose) (void) fprintf(stderr, "Scanning symbols\n"); if (!rsymb(lfd->lf_fd, lfd->lf_offset, dosymb, &mainfile)) { msg = "symbols"; goto bf; } if (verbose) (void) fprintf(stderr, "Scanning for relocation\n"); if ((rel = rrel(lfd->lf_fd, lfd->lf_offset, &mainfile)) < 0) { msg = "reloc"; goto bf; } if (rel) { if (verbose) (void) fprintf(stderr, "File is relocatable\n"); if (argc > 2) (void) fprintf(stderr, "Sorry - no scan on reloc files\n"); } else lscan(argc - 2, &argv[2]); if (verbose) (void) fprintf(stderr, "End of input\n"); (void) close(lfd->lf_fd); if (nmods > 0) (void) fprintf(stderr, "Warning: at least %d merged modules\n", nmods + 1); if (mainfile.ef_stvec != NULL) { free(mainfile.ef_stvec); mainfile.ef_stvec = NULL; mainfile.ef_stcnt = 0; } if (verbose) (void) fprintf(stderr, "Text anal 1\n"); intutext(); if (verbose) (void) fprintf(stderr, "Data anal 1\n"); intudat(&mainfile); if (!rel) { if (verbose) (void) fprintf(stderr, "Data anal 2\n"); inturdat(&mainfile); } if (lsyms) { if (verbose) (void) fprintf(stderr, "Local symbol scan\n"); intlsym(); } pabs(); ptext(&mainfile); pdata(&mainfile); pbss(&mainfile); bfclose(&mainfile); exit(0); } SHAR_EOF if test 6255 -ne "`wc -c < 'main.c'`" then echo shar: error transmitting "'main.c'" '(should have been 6255 characters)' fi fi echo shar: extracting "'prin.c'" '(5480 characters)' if test -f 'prin.c' then echo shar: will not over-write existing file "'prin.c'" else cat << \SHAR_EOF > 'prin.c' /* * SCCS: @(#)prin.c 1.2 11/2/84 14:19:47 * Print stuff. * *********************************************************************** * This software is copyright of * * John M Collins * 47 Cedarwood Drive * St Albans * Herts, AL4 0DN * England +44 727 57267 * * and is released into the public domain on the following conditions: * * 1. No free maintenance will be guaranteed. * 2. Nothing may be based on this software without * acknowledgement, including incorporation of this * notice. * * Notwithstanding the above, the author welcomes correspondence and bug * fixes. *********************************************************************** */ #include #include #include "unc.h" #define LINELNG 70 void gette(), getde(); long gettw(), getdw(); void prinst(); char noabs; /* No non-global absolutes */ int rel; /* File being analysed is relocatable */ int lpos; struct commit abstab, comtab; /* * Print absolute and common values. */ void pabs() { register int i; register symbol cs; for (i = 0; i < abstab.c_int; i++) for (i = 0; i < abstab.c_int; i++) { cs = abstab.c_symb[i]; if (cs->s_glob) (void) printf("\t.globl\t%s\n", cs->s_name); else if (noabs) continue; (void) printf("%s\t=\t0x%lx\n", cs->s_name, cs->s_value); } for (i = 0; i < comtab.c_int; i++) { cs = comtab.c_symb[i]; (void) printf("\t.comm\t%s,%d\n", cs->s_name, cs->s_value); } } /* * Print out labels. */ void plabs(ls, seg) register symbol ls; int seg; { for (; ls != NULL; ls = ls->s_link) { if (ls->s_type != seg) continue; if (ls->s_lsymb) { (void) printf("%u$:\n", ls->s_lsymb); return; /* Set last */ } if (ls->s_glob) (void) printf("\n\t.globl\t%s", ls->s_name); (void) printf("\n%s:\n", ls->s_name); } } /* * Print out text. */ void ptext(fid) register ef_fid fid; { register long tpos, endt; t_entry tstr; (void) printf(".text\n"); tpos = fid->ef_tbase; endt = tpos + fid->ef_tsize; contin: for (; tpos < endt; tpos += tstr.t_lng * 2) { gette(fid, tpos, &tstr); plabs(tstr.t_lab, TEXT); if (tstr.t_type == T_BEGIN) prinst(&tstr, tpos); else if (tstr.t_relsymb != NULL) { (void) printf("\t.long\t%s", tstr.t_relsymb->s_name); if (tstr.t_relsymb->s_type!=TEXT && tstr.t_relsymb->s_type!=DATA) (void) printf("+0x%x", gettw(fid, tpos, R_LONG)); putchar('\n'); tpos += 4; goto contin; } else (void) printf("\t.word\t0x%x\n", tstr.t_contents); } /* * Print out any trailing label. */ gette(fid, tpos, &tstr); plabs(tstr.t_lab, TEXT); } /* * Print out data. */ void pdata(fid) register ef_fid fid; { register long dpos, endd; register int lng; unsigned ctyp; int had, par, inc; char *msg; d_entry dstr; (void) printf("\n.data\n"); dpos = fid->ef_dbase; endd = dpos + fid->ef_dsize; while (dpos < endd) { getde(fid, dpos, &dstr); plabs(dstr.d_lab, DATA); switch (dstr.d_type) { case D_CONT: (void) fprintf(stderr, "Data sync error\n"); exit(200); case D_ASC: case D_ASCZ: ctyp = dstr.d_type; lng = dstr.d_lng; (void) printf("\t.asci"); if (ctyp == D_ASC) (void) printf("i\t\""); else { (void) printf("z\t\""); lng--; } while (lng > 0) { getde(fid, dpos, &dstr); switch (dstr.d_contents) { default: if (dstr.d_contents < ' ' || dstr.d_contents > '~') (void) printf("\\%.3o", dstr.d_contents); else putchar(dstr.d_contents); break; case '\"': case '\'': case '\\': case '|': (void) printf("\\%c", dstr.d_contents); break; case '\b': (void) printf("\\b"); break; case '\n': (void) printf("\\n"); break; case '\r': (void) printf("\\r"); break; } lng--; dpos++; } (void) printf("\"\n"); if (ctyp == D_ASCZ) dpos++; break; case D_BYTE: msg = "byte"; par = R_BYTE; inc = 1; goto wrest; case D_WORD: msg = "word"; par = R_WORD; inc = 2; goto wrest; case D_LONG: msg = "long"; par = R_LONG; inc = 4; wrest: (void) printf("\t.%s\t", msg); lng = dstr.d_lng; lpos = 16; had = 0; while (lng > 0) { if (lpos > LINELNG) { (void) printf("\n\t.%s\t", msg); lpos = 16; } else if (had) lpos += printf(", "); lpos += printf("0x%x", getdw(fid, dpos, par)); lng -= inc; dpos += inc; had++; } putchar('\n'); break; case D_ADDR: (void) printf("\t.long\t"); lng = dstr.d_lng; lpos = 16; had = 0; while (lng > 0) { if (lpos > LINELNG) { (void) printf("\n\t.long\t"); lpos = 16; } else if (had) lpos += printf(", "); getde(fid, dpos, &dstr); lpos += printf("%s", dstr.d_relsymb->s_name); lng -= sizeof(long); dpos += sizeof(long); had++; } putchar('\n'); break; } } /* * Print trailing label. */ getde(fid, dpos, &dstr); plabs(dstr.d_lab, DATA); } void pbss(fid) register ef_fid fid; { register long bpos = fid->ef_bbase; long endb = fid->ef_end; d_entry bstr; (void) printf("\n.bss\n"); while (bpos < endb) { getde(fid, bpos, &bstr); plabs(bstr.d_lab, BSS); (void) printf("\t.space\t%d\n", bstr.d_lng); bpos += bstr.d_lng; } getde(fid, endb, &bstr); plabs(bstr.d_lab, BSS); } SHAR_EOF if test 5480 -ne "`wc -c < 'prin.c'`" then echo shar: error transmitting "'prin.c'" '(should have been 5480 characters)' fi fi echo shar: extracting "'robj.c'" '(18429 characters)' if test -f 'robj.c' then echo shar: will not over-write existing file "'robj.c'" else cat << \SHAR_EOF > 'robj.c' /* * SCCS: @(#)robj.c 1.2 11/2/84 14:19:59 * Read object files. * *********************************************************************** * This software is copyright of * * John M Collins * 47 Cedarwood Drive * St Albans * Herts, AL4 0DN * England +44 727 57267 * * and is released into the public domain on the following conditions: * * 1. No free maintenance will be guaranteed. * 2. Nothing may be based on this software without * acknowledgement, including incorporation of this * notice. * * Notwithstanding the above, the author welcomes correspondence and bug * fixes. *********************************************************************** * * This particular module will obviously have to be munged beyond * recognition for another object format. */ #include #include #include "unc.h" void gette(), getde(), setde(), putte(), putde(); long gettw(), getdw(); void reallst(), lclash(), nomem(), unimpl(); void addit(); char *malloc(); long lseek(); int par_entry, par_round, nmods, donedrel, donebrel; struct commit abstab, comtab, dreltab; long trelpos, drelpos, brelpos; ef_fids mainfile; symbol lookup(), inventsymb(), getnsymb(); #define DBSIZE 100 #define STINIT 20 /* * Read text segment. Return 0 if not ok. */ int rtext(inf, offset, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ ef_fid outf; /* Output file descriptor */ { t_entry tstr; struct bhdr filhdr; register long size; register int i, l; unsigned short inbuf[DBSIZE/2]; /* * Initialise fields in structure. */ tstr.t_type = T_UNKNOWN; tstr.t_vins = 1; /* For the moment */ tstr.t_bdest = 0; tstr.t_gbdest = 0; tstr.t_lng = 1; tstr.t_reloc = R_NONE; tstr.t_rdisp = 0; tstr.t_isrel = 0; tstr.t_amap = 0; tstr.t_dref = 0; tstr.t_relsymb = NULL; tstr.t_reldisp = 0; tstr.t_lab = NULL; tstr.t_lsymb = 0; tstr.t_refhi = 0; tstr.t_reflo = 0x7fffffff; tstr.t_match = 0; /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return 0; if (filhdr.fmagic != FMAGIC && filhdr.fmagic != NMAGIC) return 0; /* * Warn user if entry point does not tie up. */ if (filhdr.entry != par_entry) (void) fprintf(stderr, "Warning: File has -R%X\n", filhdr.entry); outf->ef_entry = filhdr.entry; outf->ef_tbase = filhdr.entry; outf->ef_dbase = filhdr.tsize + filhdr.entry; if (filhdr.fmagic == NMAGIC) outf->ef_dbase = (outf->ef_dbase + par_round) & (~par_round); outf->ef_bbase = outf->ef_dbase + filhdr.dsize; outf->ef_end = outf->ef_bbase + filhdr.bsize; outf->ef_tsize = filhdr.tsize; outf->ef_dsize = filhdr.dsize; outf->ef_bsize = filhdr.bsize; (void) lseek(inf, offset + TEXTPOS, 0); size = outf->ef_tsize; while (size > 1) { l = size > DBSIZE? DBSIZE: size; if (read(inf, (char *)inbuf, l) != l) return 0; l /= 2; for (i = 0; i < l; i++) { tstr.t_contents = inbuf[i]; (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr)); } size -= l + l; } /* * Extra one to cope with "etext". */ (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr)); return 1; } /* * Same sort of thing for the data segment. */ int rdata(inf, offset, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ ef_fid outf; /* Output file descriptor */ { d_entry dstr; struct bhdr filhdr; register long size; register int i, l; unsigned char inbuf[DBSIZE]; /* * Initialise fields in structure. */ dstr.d_type = D_BYTE; dstr.d_reloc = R_NONE; dstr.d_lng = 1; dstr.d_relsymb = NULL; dstr.d_reldisp = 0; dstr.d_lab = NULL; /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return 0; (void) lseek(inf, offset + DATAPOS, 0); size = outf->ef_dsize; while (size > 0) { l = size > DBSIZE? DBSIZE: size; if (read(inf, (char *)inbuf, l) != l) return 0; for (i = 0; i < l; i++) { dstr.d_contents = inbuf[i]; (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); } size -= l; } /* * Repeat for BSS segment. */ dstr.d_contents = 0; for (size = outf->ef_bsize; size > 0; size--) (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); /* * Extra one to cope with "end". */ (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); return 1; } /* * Process symbol table segment. */ int rsymb(inf, offset, dproc, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ symbol (*dproc)(); register ef_fid outf; /* Output file descriptor */ { register symbol csym; struct bhdr filhdr; struct sym isym; register long size; register int i, l; char inbuf[SYMLENGTH+1]; /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return 0; offset += SYMPOS; size = filhdr.ssize; if (size <= 0) return 1; /* * Guesstimate symbol table vector size. */ l = size / (sizeof(struct sym) + 4); if (l <= 0) l = STINIT; outf->ef_stvec = (symbol *) malloc(l * sizeof(symbol)); if (outf->ef_stvec == NULL) nomem(); outf->ef_stcnt = 0; outf->ef_stmax = l; while (size > sizeof(struct sym)) { (void) lseek(inf, offset, 0); if (read(inf, (char *)&isym, sizeof(isym)) != sizeof(isym)) return 0; size -= sizeof(isym); l = SYMLENGTH; if (l > size) l = size; if (read(inf, inbuf, l) != l) return 0; inbuf[l] = '\0'; for (i = 0; inbuf[i] != '\0'; i++) ; size -= i + 1; offset += sizeof(isym) + i + 1; csym = (*dproc)(lookup(inbuf), isym.stype, isym.svalue, outf); if (outf->ef_stcnt >= outf->ef_stmax) reallst(outf); outf->ef_stvec[outf->ef_stcnt++] = csym; } return 1; } /* * Process relocation stuff. -1 error, 0 no relocation, 1 relocation. */ int rrel(inf, offset, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ ef_fid outf; /* Output file descriptor */ { struct bhdr filhdr; struct reloc crel; t_entry tstr; d_entry dstr; register long size; long cont, pos; /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return -1; if (filhdr.rtsize <= 0 && filhdr.rdsize <= 0) return 0; size = filhdr.rtsize; (void) lseek(inf, RTEXTPOS + offset, 0); while (size >= sizeof(struct reloc)) { if (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel)) return -1; pos = crel.rpos + outf->ef_tbase; gette(outf, pos, &tstr); tstr.t_reloc = crel.rsize + 1; /* Fiddle! YUK!!! */ tstr.t_rdisp = crel.rdisp; tstr.t_rptr = crel.rsegment; if (crel.rsegment == REXT) { if (crel.rsymbol >= outf->ef_stcnt) return -1; tstr.t_relsymb = outf->ef_stvec[crel.rsymbol]; tstr.t_reldisp = gettw(outf, pos, (int)crel.rsize+1); } else { cont = gettw(outf, pos, (int)crel.rsize+1); tstr.t_relsymb = getnsymb(outf, crel.rsegment, cont); } tstr.t_relsymb->s_used++; putte(outf, pos, &tstr); size -= sizeof(crel); } /* * And now repeat all that for data relocations. */ size = filhdr.rdsize; (void) lseek(inf, RDATAPOS + offset, 0); while (size >= sizeof(struct reloc)) { if (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel)) return -1; pos = crel.rpos + outf->ef_dbase; getde(outf, pos, &dstr); dstr.d_reloc = crel.rsize + 1; /* Fiddle! YUK!!! */ dstr.d_rptr = crel.rsegment; if (crel.rsegment == REXT) { if (crel.rsymbol >= outf->ef_stcnt) return -1; dstr.d_relsymb = outf->ef_stvec[crel.rsymbol]; dstr.d_reldisp = getdw(outf, pos, (int)crel.rsize+1); } else { cont = getdw(outf, pos, (int)crel.rsize+1); dstr.d_relsymb = getnsymb(outf, crel.rsegment, cont); if (dstr.d_relsymb->s_type == TEXT) { gette(outf, cont, &tstr); tstr.t_dref = 1; putte(outf, cont, &tstr); } } switch (crel.rsize) { default: unimpl("Data byte relocation"); break; case RWORD: unimpl("data word reloc"); dstr.d_type = D_WORD; dstr.d_lng = 2; setde(outf, pos+1, D_CONT, 1); break; case RLONG: dstr.d_type = D_ADDR; dstr.d_lng = 4; setde(outf, pos+1, D_CONT, 1); setde(outf, pos+2, D_CONT, 1); setde(outf, pos+3, D_CONT, 1); break; } dstr.d_relsymb->s_used++; putde(outf, pos, &dstr); size -= sizeof(crel); } return 1; } /* * Process a symbol. */ symbol dosymb(sy, type, val, fid) register symbol sy; int type; long val; ef_fid fid; { t_entry tstr; d_entry dstr; if (!sy->s_newsym) { if (type & EXTERN) { (void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name); exit(10); } if (++sy->s_defs > nmods) nmods = sy->s_defs; sy = inventsymb("DUP"); } sy->s_value = val; switch (type) { default: return NULL; case EXTERN|UNDEF: if (val != 0) { sy->s_type = COMM; addit(&comtab, sy); } else sy->s_type = N_UNDF; sy->s_glob = 1; break; case EXTERN|ABS: sy->s_type = N_ABS; sy->s_glob = 1; addit(&abstab, sy); break; case ABS: sy->s_type = N_ABS; addit(&abstab, sy); break; case EXTERN|TEXT: case TEXT: sy->s_type = N_TEXT; gette(fid, val, &tstr); tstr.t_bdest = 1; if (type & EXTERN) { tstr.t_gbdest = 1; sy->s_glob = 1; } sy->s_link = tstr.t_lab; tstr.t_lab = sy; putte(fid, val, &tstr); break; case BSS: case EXTERN|BSS: sy->s_type = N_BSS; goto datrest; case DATA: case EXTERN|DATA: sy->s_type = N_DATA; datrest: getde(fid, val, &dstr); if (type & EXTERN) sy->s_glob = 1; sy->s_link = dstr.d_lab; dstr.d_lab = sy; putde(fid, val, &dstr); break; } sy->s_newsym = 0; return sy; } /* * Process relocation stuff in putative library modules. * The main function of all this is to mark which bits of the text * not to look at as I compare the stuff. * * As with "rrel", return -1 error, 0 no relocation, 1 relocation. */ int rrell1(inf, offset, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ ef_fid outf; /* Output file descriptor */ { struct bhdr filhdr; struct reloc crel; t_entry tstr; register long size; long pos; /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return -1; if (filhdr.rtsize <= 0 && filhdr.rdsize <= 0) return 0; size = filhdr.rtsize; (void) lseek(inf, RTEXTPOS + offset, 0); while (size >= sizeof(struct reloc)) { if (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel)) return -1; pos = crel.rpos + outf->ef_tbase; gette(outf, pos, &tstr); tstr.t_reloc = crel.rsize + 1; /* Fiddle! YUK!!! */ tstr.t_rdisp = crel.rdisp; tstr.t_rptr = crel.rsegment; tstr.t_isrel = 1; putte(outf, pos, &tstr); if (crel.rsize == RLONG) { gette(outf, pos+2, &tstr); tstr.t_isrel = 1; putte(outf, pos+2, &tstr); } size -= sizeof(crel); } /* * Dont bother with data relocation at this stage. We'll * tie that up later. */ return 1; } /* * Process a symbol in library file. The extern variable trelpos gives * the place in the main file where the library module is relocated. * We don't know the data position until we do the final merge, perhaps * not even then. */ symbol dolsymb(sy, type, val, fid) register symbol sy; int type; long val; ef_fid fid; { t_entry tstr; switch (type) { default: return NULL; case EXTERN|UNDEF: if (!sy->s_newsym) return sy; sy->s_value = val; if (val != 0) { sy->s_type = COMM; addit(&dreltab, sy); } else sy->s_type = N_UNDF; sy->s_glob = 1; break; case EXTERN|ABS: if (!sy->s_newsym) { if (sy->s_type != N_ABS || sy->s_value != val) lclash("abs"); } sy->s_type = N_ABS; sy->s_value = val; sy->s_glob = 1; addit(&abstab, sy); break; case EXTERN|TEXT: sy->s_type = N_TEXT; val += trelpos - fid->ef_tbase; if (!sy->s_newsym) { if (val != sy->s_value) lclash("tsym"); return sy; } sy->s_value = val; gette(&mainfile, val, &tstr); tstr.t_bdest = 1; tstr.t_gbdest = 1; sy->s_glob = 1; sy->s_link = tstr.t_lab; tstr.t_lab = sy; putte(&mainfile, val, &tstr); break; case EXTERN|BSS: if (!sy->s_newsym) return sy; sy->s_type = N_BSS; sy->s_value = val - fid->ef_bbase; goto datrest; case EXTERN|DATA: if (!sy->s_newsym) return sy; sy->s_type = N_DATA; sy->s_value = val - fid->ef_dbase; datrest: sy->s_glob = 1; addit(&dreltab, sy); break; } sy->s_newsym = 0; return sy; } /* * Change definition of undefined symbol as we define it. */ void reassign(sy, val) register symbol sy; long val; { sy->s_value = val; if (val < mainfile.ef_tbase) { sy->s_type = N_ABS; addit(&abstab, sy); } else if (val < mainfile.ef_dbase) { t_entry tstr; sy->s_type = N_TEXT; gette(&mainfile, val, &tstr); tstr.t_bdest = 1; tstr.t_gbdest = 1; sy->s_glob = 1; sy->s_link = tstr.t_lab; tstr.t_lab = sy; putte(&mainfile, val, &tstr); } else { d_entry dstr; sy->s_type = val < mainfile.ef_bbase? N_DATA: N_BSS; getde(&mainfile, val, &dstr); sy->s_link = dstr.d_lab; dstr.d_lab = sy; putde(&mainfile, val, &dstr); } } /* * When we discover where bss or data come, reallocate the table. */ void zapdat(seg, inc) int seg; long inc; { register int i; register symbol csymb; d_entry dent; for (i = 0; i < dreltab.c_int; i++) { csymb = dreltab.c_symb[i]; if (csymb->s_type != seg) continue; csymb->s_value += inc; getde(&mainfile, csymb->s_value, &dent); csymb->s_link = dent.d_lab; dent.d_lab = csymb; putde(&mainfile, csymb->s_value, &dent); } } /* * Process relocation stuff in library module which we are inserting. * Horrors if something goes wrong. */ void rrell2(inf, offset, outf) int inf; /* a.out file (possibly in library) */ long offset; /* Offset from start of inf of a.out file */ ef_fid outf; /* Output file descriptor */ { struct bhdr filhdr; struct reloc crel; t_entry mtstr; d_entry mdstr; register long size; register symbol csymb; long pos, mpos, mval, lval; int dhere = 0; /* Mark whether bss done */ /* * Read a.out header. */ (void) lseek(inf, offset, 0); if (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr)) return; if (filhdr.rtsize <= 0 && filhdr.rdsize <= 0) return; size = filhdr.rtsize; (void) lseek(inf, RTEXTPOS + offset, 0); for (; size >= sizeof(struct reloc); size -= sizeof(crel)) { if (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel)) lclash("rd trel"); pos = crel.rpos + outf->ef_tbase; mpos = crel.rpos + trelpos; gette(&mainfile, mpos, &mtstr); lval = gettw(outf, pos, (int)crel.rsize+1); mval = gettw(&mainfile, mpos, (int)crel.rsize+1); switch (crel.rsegment) { case RTEXT: if (lval + trelpos - outf->ef_tbase != mval) lclash("Trel"); continue; case RDATA: if (donedrel) { if (lval + drelpos - outf->ef_dbase != mval) lclash("Drel"); } else { donedrel++; drelpos = mval - lval + outf->ef_dbase; } continue; case RBSS: if (donebrel) { if (lval + brelpos - outf->ef_bbase != mval) lclash("brel"); } else { donebrel++; brelpos = mval - lval + outf->ef_bbase; } continue; case REXT: if (crel.rsymbol >= outf->ef_stcnt) lclash("Bad sy no"); csymb = outf->ef_stvec[crel.rsymbol]; if (csymb == NULL) continue; switch (csymb->s_type) { case N_UNDF: reassign(csymb, mval - lval); break; case N_ABS: if (lval + csymb->s_value != mval) lclash("abs rel"); break; case N_TEXT: if (lval + csymb->s_value != mval) lclash("text rel"); break; case N_DATA: if (lval + csymb->s_value != mval) lclash("data rel"); break; case N_BSS: if (lval + csymb->s_value != mval) lclash("bss rel"); break; case COMM: reassign(csymb, mval - lval); break; } mtstr.t_relsymb = csymb; mtstr.t_reldisp = lval; break; } } /* * Relocate data and bss if possible. */ if (donebrel) { zapdat(N_BSS, brelpos); dhere++; } if (!donedrel) return; zapdat(N_DATA, drelpos); /* * And now repeat all that for data relocations if possible */ size = filhdr.rdsize; (void) lseek(inf, RDATAPOS + offset, 0); for (; size >= sizeof(struct reloc); size -= sizeof(crel)) { if (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel)) lclash("Rd drel"); if (crel.rsize != RLONG) continue; pos = crel.rpos + outf->ef_dbase; mpos = crel.rpos + drelpos; getde(&mainfile, mpos, &mdstr); lval = getdw(outf, pos, (int)crel.rsize+1); mval = getdw(&mainfile, mpos, (int)crel.rsize+1); switch (crel.rsegment) { case RTEXT: if (lval + trelpos - outf->ef_tbase != mval) lclash("Trel-d"); continue; case RDATA: if (lval + drelpos - outf->ef_dbase != mval) lclash("Drel-d"); continue; case RBSS: if (donebrel) { if (lval + brelpos - outf->ef_bbase != mval) lclash("brel"); } else { donebrel++; brelpos = mval - lval + outf->ef_bbase; } continue; case REXT: if (crel.rsymbol >= outf->ef_stcnt) lclash("Bad sy no"); csymb = outf->ef_stvec[crel.rsymbol]; if (csymb == NULL) continue; switch (csymb->s_type) { case N_UNDF: reassign(csymb, mval - lval); break; case N_ABS: if (lval + csymb->s_value != mval) lclash("abs rel"); break; case N_TEXT: if (lval + csymb->s_value != mval) lclash("text rel"); break; case N_DATA: if (lval + csymb->s_value != mval) lclash("data rel"); break; case N_BSS: if (lval + csymb->s_value != mval) lclash("bss rel"); break; case COMM: reassign(csymb, mval - lval); break; } mtstr.t_relsymb = csymb; mtstr.t_reldisp = lval; break; } } if (dhere || !donebrel) return; zapdat(N_BSS, brelpos); } SHAR_EOF if test 18429 -ne "`wc -c < 'robj.c'`" then echo shar: error transmitting "'robj.c'" '(should have been 18429 characters)' fi fi exit 0 # End of shell archive