|
|
1.1 ! root 1: /* ! 2: * ld/pass2.c ! 3: * Pass 2 ! 4: * Read, relocate and output segments of module ! 5: */ ! 6: ! 7: #include "data.h" ! 8: ! 9: void ! 10: loadmod( mp ) ! 11: mod_t * mp; ! 12: { ! 13: seg_t *isgp, *irsp, *osgp, *orsp; ! 14: sym_t *sp; ! 15: int opcode, relseg; ! 16: int segn; ! 17: uaddr_t addr, bias; ! 18: unsigned int symno; ! 19: FILE *ifp, *irfp, *ofp, *orfp; ! 20: static FILE *inputf[NLSEG]; ! 21: static char *fname = NULL; ! 22: ! 23: if ( watch ) ! 24: mpmsg( mp, "loading" ); ! 25: ! 26: for ( segn = 0; segn < NLSEG; segn++ ) { ! 27: ! 28: if ( (segn != L_REL) && (outputf[segn] == NULL) ) ! 29: continue; ! 30: ! 31: if ( fname != mp->fname ) { ! 32: ! 33: if ( fname != NULL ) ! 34: fclose( inputf[segn] ); ! 35: ! 36: if (( inputf[segn] = fopen(mp->fname, "r")) == NULL ) { ! 37: filemsg(mp->fname, "can't open (pass 2)"); ! 38: exit(1); ! 39: } ! 40: } ! 41: ! 42: fseek( inputf[segn], mp->seg[segn].daddr, 0 ); ! 43: ! 44: if ( watch && (mp->seg[segn].size != 0) ) ! 45: message("relocating seg#%d[%06lo]@%06lo to %06lo", ! 46: segn, (long)mp->seg[segn].size, ! 47: (long)mp->seg[segn].vbase, ! 48: (long)oseg[segn].vbase); ! 49: } ! 50: ! 51: fname = mp->fname; ! 52: irfp = inputf[L_REL]; ! 53: irsp = &mp->seg[L_REL]; ! 54: orfp = outputf[L_REL]; ! 55: orsp = &oseg[L_REL]; ! 56: ! 57: while ( (opcode = getbyte(irfp, irsp)) != EOF ) { ! 58: ! 59: addr = getaddr( irfp, irsp ); ! 60: ! 61: /* ! 62: * Find segment in which it address lies ! 63: */ ! 64: for (segn=0, isgp=&mp->seg[0]; segn < L_SYM; segn++, isgp++) { ! 65: if ( (addr >= isgp->vbase) ! 66: && (addr < isgp->vbase+isgp->size) ) ! 67: break; ! 68: } ! 69: ! 70: if ( (segn == L_BSSI) ! 71: || (segn == L_BSSD) ! 72: || (segn == L_SYM) ) { ! 73: mpmsg( mp, "bad relocation address %06lo", (long)addr); ! 74: continue; ! 75: } ! 76: ! 77: ifp = inputf[segn]; ! 78: ofp = outputf[segn]; ! 79: osgp = &oseg[segn]; ! 80: ! 81: /* ! 82: * Put unrelocated stuff ! 83: */ ! 84: while ( isgp->vbase < addr ) ! 85: putbyte( getbyte(ifp, isgp), ofp, osgp ); ! 86: ! 87: bias = 0; ! 88: ! 89: switch ( relseg = (opcode & LR_SEG) ) { ! 90: ! 91: case L_SYM: ! 92: /* ! 93: * Symbolic reference: ! 94: * L_SYM[+LR_PCR+LR_WORD],addr-16,symno-16,offset ! 95: */ ! 96: symno = getsymno( irfp, irsp ); ! 97: ! 98: if ( symno >= mp->nsym ) { ! 99: mpmsg( mp, "bad reloc. sym. no. %d", symno ); ! 100: } ! 101: ! 102: else if ( (sp = mp->sym[symno]) == NULL ) { ! 103: mpmsg( mp, "symbol %d not kept", symno ); ! 104: } ! 105: ! 106: /* ! 107: * Symbolic reference not resolved. ! 108: */ ! 109: else if ( sp->s.ls_type == (L_GLOBAL|L_REF) ) { ! 110: if ( orfp != NULL ) { ! 111: putbyte( opcode, orfp, orsp ); ! 112: putaddr( osgp->vbase, orfp, orsp ); ! 113: putsymno( sp->symno, orfp, orsp ); ! 114: } ! 115: } ! 116: ! 117: /* ! 118: * Convert symbolic reference to segment reference. ! 119: */ ! 120: else { ! 121: bias = sp->s.ls_addr; ! 122: ! 123: if ( orfp != NULL ) { ! 124: putbyte(sp->s.ls_type&LR_SEG ! 125: |opcode&~LR_SEG, ! 126: orfp, orsp); ! 127: putaddr( osgp->vbase, orfp, orsp ); ! 128: ! 129: /* ! 130: * Keep segment size correct ! 131: */ ! 132: orsp->size -= sizeof(short); ! 133: } ! 134: } ! 135: break; ! 136: ! 137: case L_SHRI: ! 138: case L_PRVI: ! 139: case L_BSSI: ! 140: case L_SHRD: ! 141: case L_PRVD: ! 142: case L_BSSD: ! 143: bias = oseg[relseg].vbase ! 144: - mp->seg[relseg].vbase; ! 145: /* no break */ ! 146: ! 147: case L_ABS: ! 148: if ( orfp != NULL ) { ! 149: putbyte( opcode, orfp, orsp ); ! 150: putaddr( osgp->vbase, orfp, orsp ); ! 151: } ! 152: break; ! 153: ! 154: default: ! 155: goto BadCode; ! 156: } ! 157: ! 158: if ( opcode & LR_PCR ) ! 159: bias += isgp->vbase - osgp->vbase; ! 160: ! 161: switch ( opcode & LR_OP ) { ! 162: ! 163: default: ! 164: BadCode: ! 165: mpmsg( mp, "bad relocation opcode %03o", opcode ); ! 166: break; ! 167: ! 168: case LR_BYTE: ! 169: bias += getbyte( ifp, isgp ); ! 170: putbyte( (char)bias, ofp, osgp ); ! 171: break; ! 172: ! 173: case LR_WORD: ! 174: bias += getword( ifp, isgp ); ! 175: putword( (short)bias, ofp, osgp ); ! 176: break; ! 177: } ! 178: } ! 179: ! 180: /* ! 181: * Copy remainder of segments. ! 182: */ ! 183: for ( segn = 0; segn < L_SYM; segn++ ) ! 184: if ( (ofp = outputf[segn]) != NULL ) ! 185: copyseg(inputf[segn], &mp->seg[segn], ofp, &oseg[segn]); ! 186: ! 187: /* ! 188: * Adjust bss bases (others done by copyseg). ! 189: */ ! 190: oseg[L_BSSD].vbase += mp->seg[L_BSSD].size; ! 191: oseg[L_BSSI].vbase += mp->seg[L_BSSI].size; ! 192: } ! 193: ! 194: /* ! 195: * I/O routines ! 196: */ ! 197: void ! 198: putstruc( p, s, fp, sgp ) ! 199: register char *p; ! 200: register unsigned int s; ! 201: register FILE *fp; ! 202: register seg_t *sgp; ! 203: { ! 204: while ( s-- ) ! 205: putbyte( *p++, fp, sgp ); ! 206: } ! 207: ! 208: unsigned short ! 209: getword( fp, sgp ) ! 210: FILE *fp; ! 211: seg_t *sgp; ! 212: { ! 213: return( (worder == LOHI) ? getlohi(fp,sgp) : gethilo(fp,sgp) ); ! 214: } ! 215: ! 216: unsigned short ! 217: getlohi( fp, sgp ) ! 218: FILE *fp; ! 219: seg_t *sgp; ! 220: { ! 221: register unsigned char b; ! 222: ! 223: b = getbyte( fp, sgp ); ! 224: return( (getbyte(fp,sgp) << 8) | b ); ! 225: } ! 226: ! 227: unsigned short ! 228: gethilo( fp, sgp ) ! 229: FILE *fp; ! 230: seg_t *sgp; ! 231: { ! 232: register unsigned char b; ! 233: ! 234: b = getbyte(fp, sgp); ! 235: return( (b << 8) | getbyte(fp,sgp) ); ! 236: } ! 237: ! 238: int ! 239: getbyte( fp, sgp ) ! 240: FILE *fp; ! 241: seg_t *sgp; ! 242: { ! 243: if ( sgp->size == 0 ) ! 244: return( EOF ); ! 245: ! 246: else { ! 247: sgp->size--; ! 248: sgp->vbase++; ! 249: return( getc(fp) ); ! 250: } ! 251: } ! 252: ! 253: void ! 254: putword( w, fp, sgp ) ! 255: unsigned short w; ! 256: FILE *fp; ! 257: seg_t *sgp; ! 258: { ! 259: if ( worder == LOHI ) ! 260: putlohi( w, fp, sgp ); ! 261: ! 262: else ! 263: puthilo( w, fp, sgp ); ! 264: } ! 265: ! 266: void ! 267: putlohi( w, fp, sgp ) ! 268: unsigned short w; ! 269: FILE *fp; ! 270: seg_t *sgp; ! 271: { ! 272: putbyte( w & 0377, fp, sgp ); ! 273: putbyte( w >>8, fp, sgp ); ! 274: } ! 275: ! 276: void ! 277: puthilo( w, fp, sgp ) ! 278: unsigned short w; ! 279: FILE *fp; ! 280: seg_t *sgp; ! 281: { ! 282: putbyte( w >> 8, fp, sgp ); ! 283: putbyte( w & 0377, fp, sgp ); ! 284: } ! 285: ! 286: void ! 287: putbyte( b, fp, sgp ) ! 288: unsigned char b; ! 289: FILE *fp; ! 290: seg_t *sgp; ! 291: { ! 292: sgp->vbase++; ! 293: putc( b, fp ); ! 294: } ! 295: ! 296: /* ! 297: * Copy a segment. ! 298: * Watch out for EOF before the expected size. ! 299: */ ! 300: copyseg(ifp, isgp, ofp, osgp) FILE *ifp, *ofp; seg_t *isgp, *osgp; ! 301: { ! 302: register int b; ! 303: register fsize_t n; ! 304: ! 305: for (n = isgp->size; n > 0; n--) { ! 306: if ((b = getc(ifp)) == EOF) ! 307: break; ! 308: putc(b, ofp); ! 309: } ! 310: while (n-- > 0) ! 311: putc(0, ofp); ! 312: n = isgp->size; ! 313: isgp->vbase += n; ! 314: osgp->vbase += n; ! 315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.