/* lkrloc.c */ /* * (C) Copyright 1989,1990 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 */ #include #include #include #include "aslink.h" /* * Process relocation operations * and call designated output routine */ VOID reloc(c) char c; { switch(c) { case 'T': relt(); break; case 'R': relr(); break; case 'P': relp(); break; case 'E': rele(); break; default: fprintf(stderr, "Undefined Relocation Operation\n"); break; } } /* * Relocation 'T' processing. */ VOID relt() { rtcnt = 0; while (more()) { if (rtcnt < NTXT) { rtval[rtcnt] = eval(); rtflg[rtcnt] = 1; rtcnt++; } } } /* * Relocation 'R' processing */ VOID relr() { register mode; register addr_t reli, relv; int aindex, rindex, rtp, error; addr_t r, rtbase, rtofst, paga, pags, pc; struct areax **a; struct sym **s; /* * Get area and symbol lists */ a = hp->a_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R_WORD | R_AREA) || eval()) fprintf(stderr, "R input error\n"); /* * Get area pointer */ aindex = evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); return; } /* * Base values */ rtbase = add_w(0, 0); rtofst = 2; /* * Relocate address */ pc = add_w(a[aindex]->a_addr, 0); /* * Do remaining relocations */ while (more()) { error = 0; mode = eval(); rtp = eval(); rindex = evword(); /* * R_SYM or R_AREA references */ if (mode & R_SYM) { if (rindex >= hp->h_nglob) { fprintf(stderr, "R symbol error\n"); return; } reli = symval(s[rindex]); } else { if (rindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); return; } reli = a[rindex]->a_addr; } /* * R_PCR addressing */ if (mode & R_PCR) { if (mode & R_BYTE) { reli -= (pc + (rtp-rtofst) + 1); } else { reli -= (pc + (rtp-rtofst) + 2); } } /* * R_PAG0 or R_PAG addressing */ if (mode & (R_PAG0|R_PAG)) { paga = sdp.s_area->a_addr; pags = sdp.s_addr; reli -= paga + pags; } /* * R_BYTE or R_WORD operation */ if (mode & R_BYTE) { if (mode & R_BYT2) { relv = add_b2(reli, rtp); } else { relv = add_b1(reli, rtp); } } else { relv = add_w(reli, rtp); } /* * R_BYTE with R_BYT2 offset adjust */ if (mode & R_BYTE) { if (mode & R_BYT2) { rtofst += 1; } } /* * Unsigned Byte Checking */ if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF) error = 1; /* * PCR Relocation Error Checking */ if (mode & R_PCR && mode & R_BYTE) { r = relv & ~0x7F; if (r != (addr_t) ~0x7F && r != 0) error = 2; } /* * Page Relocation Error Checking */ if (mode & R_PAG0 && (relv & ~0xFF || paga || pags)) error = 3; if (mode & R_PAG && (relv & ~0xFF)) error = 4; /* * Error Processing */ if (error) { rerr.aindex = aindex; rerr.mode = mode; rerr.rtbase = rtbase + rtp - rtofst - 1; rerr.rindex = rindex; rerr.rval = relv - reli; relerr(errmsg[error-1]); } } if (oflag == 1) { ihx(1); } else if (oflag == 2) { s19(1); } } char *errmsg[] = { "Unsigned Byte error", "Byte PCR relocation error", "Page0 relocation error", "Page Mode relocation error" }; /* * Relocation 'P' processing */ VOID relp() { register aindex, rindex; int mode, rtp; addr_t relv; struct areax **a; struct sym **s; /* * Get area and symbol lists */ a = hp->a_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R_WORD | R_AREA) || eval()) fprintf(stderr, "P input error\n"); /* * Get area pointer */ aindex = evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); return; } /* * Do remaining relocations */ while (more()) { mode = eval(); rtp = eval(); rindex = evword(); /* * R_SYM or R_AREA references */ if (mode & R_SYM) { if (rindex >= hp->h_nglob) { fprintf(stderr, "P symbol error\n"); return; } relv = symval(s[rindex]); } else { if (rindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); return; } relv = a[rindex]->a_addr; } add_w(relv, rtp); } /* * Paged values */ aindex = add_w(0,2); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); return; } sdp.s_areax = a[aindex]; sdp.s_area = sdp.s_areax->a_bap; sdp.s_addr = add_w(0,4); if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF) relerp("Page Definition Boundary Error"); } /* * EOF processing */ VOID rele() { if (oflag == 1) { ihx(0); } else if (oflag == 2) { s19(0); } } /* * Evaluate word */ addr_t evword() { register addr_t v; if (hilo) { v = (eval() << 8); v += eval(); } else { v = eval(); v += (eval() << 8); } return(v); } /* * Add byte values */ addr_t add_b1(v, i) register addr_t v; register int i; { return(rtval[i] += v); } /* * Add byte values */ addr_t add_b2(v, i) addr_t v; int i; { register addr_t j; if (hilo) { j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff); rtflg[i] = 0; rtval[i+1] = j & 0xff; } else { j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8); rtval[i] = j & 0xff; rtflg[i+1] = 0; } return(j); } /* * Add word values */ addr_t add_w(v, i) register addr_t v; register int i; { register addr_t j; if (hilo) { j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff); rtval[i] = (j >> 8) & 0xff; rtval[i+1] = j & 0xff; } else { j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8); rtval[i] = j & 0xff; rtval[i+1] = (j >> 8) & 0xff; } return(j); } /* * Relocation Error Report */ VOID relerr(str) char *str; { errdmp(stderr, str); if (mfp) errdmp(mfp, str); } /* * Relocation error dump routine */ VOID errdmp(fptr, str) FILE *fptr; char *str; { int mode, aindex, rindex; struct sym **s; struct areax **a; struct areax *raxp; a = hp->a_list; s = hp->s_list; mode = rerr.mode; aindex = rerr.aindex; rindex = rerr.rindex; /* * Print Error */ fprintf(fptr, "\n?ASlink-W-%s", str); /* * Print symbol if symbol based */ if (mode & R_SYM) { fprintf(fptr, " for symbol %.*s\n", NCPS, &s[rindex]->s_id[0]); } else { fprintf(fptr, "\n"); } /* * Print Ref Info */ fprintf(fptr, " file module area offset\n"); fprintf(fptr, " Refby %-8.8s %-8.8s %-8.8s ", hp->h_lfile->f_idp, &hp->m_id[0], &a[aindex]->a_bap->a_id[0]); prntval(fptr, rerr.rtbase); /* * Print Def Info */ if (mode & R_SYM) { raxp = s[rindex]->s_axp; } else { raxp = a[rindex]; } fprintf(fptr, " Defin %-8.8s %-8.8s %-8.8s ", raxp->a_bhp->h_lfile->f_idp, &raxp->a_bhp->m_id[0], &raxp->a_bap->a_id[0]); if (mode & R_SYM) { prntval(fptr, s[rindex]->s_addr); } else { prntval(fptr, rerr.rval); } } VOID prntval(fptr, v) FILE *fptr; addr_t v; { if (xflag == 0) { fprintf(fptr, "%04X\n", v); } else if (xflag == 1) { fprintf(fptr, "%06o\n", v); } else if (xflag == 2) { fprintf(fptr, "%05u\n", v); } } /* * Paging Error Report */ VOID relerp(str) char *str; { erpdmp(stderr, str); if (mfp) erpdmp(mfp, str); } /* * Paging error dump routine */ VOID erpdmp(fptr, str) FILE *fptr; char *str; { register struct head *thp; thp = sdp.s_areax->a_bhp; /* * Print Error */ fprintf(fptr, "\n?ASlink-W-%s\n", str); /* * Print PgDef Info */ fprintf(fptr, " file module pgarea pgoffset\n"); fprintf(fptr, " PgDef %-8.8s %-8.8s %-8.8s ", thp->h_lfile->f_idp, &thp->m_id[0], &sdp.s_area->a_id[0]); prntval(fptr, sdp.s_area->a_addr + sdp.s_addr); }