|
|
1.1 ! root 1: /* ! 2: * ld/pass2.c ! 3: * Pass 2 ! 4: * Read, relocate and output segments of module ! 5: */ ! 6: #include "data.h" ! 7: ! 8: void ! 9: loadmod( mp ) ! 10: mod_t * mp; ! 11: { ! 12: static char *name = ""; ! 13: static FILE *inputf, *inputr, *inputs; ! 14: int segn; ! 15: ! 16: if (watch) { ! 17: errCount--; ! 18: mpmsg(mp, "loading" ); /* NODOC */ ! 19: } ! 20: ! 21: if (strcmp(name, mp->fname)) { /* avoid opening lib many times */ ! 22: if (*name) { ! 23: fclose(inputf); ! 24: fclose(inputr); ! 25: fclose(inputs); ! 26: } ! 27: name = mp->fname; ! 28: ! 29: if (((inputf = fopen(name, "r")) == NULL) || ! 30: ((inputr = fopen(name, "r")) == NULL) || ! 31: ((inputs = fopen(name, "r")) == NULL)) { ! 32: filemsg(name, "can't open"); /* NODOC */ ! 33: exit(1); ! 34: } ! 35: } ! 36: ! 37: for (segn = 0; segn < S_BSSD; segn++) { ! 38: char *t; /* actual text */ ! 39: seg_t *isgp, *orsp; ! 40: unsigned i, len; ! 41: long size; ! 42: FILE *ofp, *orp; ! 43: ! 44: isgp = mp->seg + segn; ! 45: ! 46: if (!isgp->size) ! 47: continue; ! 48: ! 49: len = isgp->size; ! 50: if (len != isgp->size) ! 51: mpfatal(mp, "is corrupt"); ! 52: ! 53: t = alloc(len + 4); ! 54: fseek(inputf, isgp->daddr, 0 ); ! 55: if (1 != fread(t, len, 1, inputf)) ! 56: mpfatal(mp, "Read error in pass2"); ! 57: ! 58: orsp = oseg + segn; ! 59: ofp = outputf[segn]; ! 60: orp = outputr[segn]; ! 61: size = (long)isgp->size; ! 62: ! 63: w_message("relocating seg#%d[%06lx]@%06lx to %06lx @ %ld", ! 64: segn, ! 65: size, ! 66: (long)isgp->vbase, ! 67: (long)orsp->vbase, ! 68: isgp->nreloc); ! 69: ! 70: if (isgp->nreloc) ! 71: fseek(inputr, isgp->relptr, 0); ! 72: ! 73: for (i = 0; i < isgp->nreloc; i++) { ! 74: char *ptr; ! 75: char *mtype; ! 76: sym_t *s; ! 77: RELOC rel; ! 78: long relf, w; ! 79: int commsw; ! 80: long workl; ! 81: short works; ! 82: ! 83: /* get reloc record */ ! 84: if (1 != fread(&rel, RELSZ, 1, inputr)) ! 85: mpfatal(mp, "Read error in pass 2"); ! 86: ! 87: ! 88: w = rel.r_vaddr - isgp->vbase; ! 89: if ((w < 0) || (w > len)) { ! 90: mpmsg(mp, "relocation out of range %lx", w); ! 91: /* A relocation record points outside the ! 92: * range of its segment. */ ! 93: continue; ! 94: } ! 95: ptr = t + w; ! 96: ! 97: s = mp->sym[(int)rel.r_symndx]; ! 98: relf = s->value; ! 99: mtype = "rel"; ! 100: ! 101: if (reloc) { ! 102: RELOC orel; ! 103: ! 104: orel.r_type = rel.r_type; ! 105: orel.r_vaddr = w + orsp->vbase - ! 106: aouth.text_start; ! 107: if (s->scnum) ! 108: orel.r_symndx = s->scnum - 1; ! 109: else ! 110: orel.r_symndx = s->symno; ! 111: if (1 != fwrite(&orel, sizeof(orel), 1, orp)) ! 112: fatal("Write error"); /* NODOC */ ! 113: } ! 114: ! 115: /* ! 116: * This wierdness is to deal with a coff wierdness. ! 117: * If dealing with a common the text is incremented ! 118: * by the length of the common as seen in that ! 119: * module. ! 120: */ ! 121: commsw = (s->scnum <= 0); ! 122: if (s->sclass == C_EXT) { ! 123: SYMENT sym; ! 124: ! 125: fseek(inputs, ! 126: mp->symptr + (rel.r_symndx * SYMESZ), ! 127: 0); ! 128: if (1 != fread(&sym, SYMESZ, 1, inputs)) ! 129: fatal("Read error"); /* NODOC */ ! 130: if ((C_EXT == sym.n_sclass) && ! 131: sym.n_value && ! 132: !sym.n_scnum) { ! 133: commsw = 1; ! 134: relf -= sym.n_value; ! 135: } ! 136: } ! 137: if (!commsw && (s->mod == mp)) ! 138: relf -= mp->seg[s->scnum - 1].vbase; ! 139: ! 140: switch (rel.r_type) { ! 141: case R_PCRBYTE: ! 142: mtype = "pcrel"; ! 143: relf -= orsp->vbase; ! 144: case R_RELBYTE: ! 145: w = *ptr; ! 146: *ptr = w + relf; ! 147: break; ! 148: case R_PCRWORD: ! 149: mtype = "pcrel"; ! 150: relf -= orsp->vbase; ! 151: case R_RELWORD: ! 152: case R_DIR16: ! 153: memcpy(&works, ptr, 2); ! 154: w = works; ! 155: works += relf; ! 156: memcpy(ptr, &works, 2); ! 157: break; ! 158: case R_PCRLONG: ! 159: mtype = "pcrel"; ! 160: relf -= orsp->vbase; ! 161: case R_RELLONG: ! 162: case R_DIR32: ! 163: memcpy(&workl, ptr, 4); ! 164: w = workl; ! 165: workl += relf; ! 166: memcpy(ptr, &workl, 4); ! 167: break; ! 168: default: ! 169: mpmsg(mp, ! 170: "unknown relocation r_type $d", ! 171: rel.r_type); ! 172: /* Unknown type on COFF relocation record. */ ! 173: } ! 174: w_message("%s(%d) %lx = %s(%d, %lx) + %lx", ! 175: mtype, ! 176: rel.r_type, ! 177: relf + w, ! 178: s->name, ! 179: s->symno, ! 180: s->value, ! 181: w); ! 182: } ! 183: ! 184: orsp->vbase += size; ! 185: if (1 != fwrite(t, len, 1, ofp)) ! 186: fatal("Write error"); /* NODOC */ ! 187: free(t); ! 188: } ! 189: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.