|
|
1.1 ! root 1: /* Copyright 1989 by AT&T Bell Laboratories */ ! 2: /* linkdata.c -- group files into the text segment of a .o file */ ! 3: ! 4: #define SYMBOL "_datalist" ! 5: #define END_SYMBOL "_endmo" ! 6: ! 7: #include <stdio.h> ! 8: #include <a.out.h> ! 9: #include <assert.h> ! 10: #include <sys/types.h> ! 11: #include <sys/stat.h> ! 12: #include "tags.h" ! 13: ! 14: #define LONG (sizeof(long)) ! 15: #define align(x) (((x) + (LONG - 1)) & ~(LONG - 1)) ! 16: ! 17: #ifdef SPARC ! 18: #define relocation_info reloc_info_sparc ! 19: #endif ! 20: ! 21: #define RELINFO_SZ (sizeof (struct relocation_info)) ! 22: ! 23: struct relocation_info rconst, *rel; ! 24: struct nlist nlconst, *nl; ! 25: ! 26: struct str_table { /* The string table buffer. */ ! 27: int len; /* length including this word */ ! 28: char strs[4]; ! 29: } *str_tbl; ! 30: char *str_ptr; /* the next location in the string table. */ ! 31: ! 32: /* add_name: ! 33: * Extract the structure name from the file name and add it to the string table ! 34: * buffer (with an initial "_"). ! 35: */ ! 36: void add_name (file) ! 37: char *file; ! 38: { ! 39: register char *p, *begin; ! 40: int len, res; ! 41: ! 42: /* find the beginning of the file name. */ ! 43: for (p = begin = file; *p; p++) { ! 44: if (*p == '/') ! 45: begin = p+1; ! 46: } ! 47: ! 48: /* find the ".mo" */ ! 49: for (p = begin, len = 0; *p && (*p != '.'); p++, len++) ! 50: continue; ! 51: ! 52: *str_ptr++ = '_'; ! 53: strncpy(str_ptr, begin, len); ! 54: str_ptr += len; ! 55: *str_ptr++ = '\0'; ! 56: str_tbl->len += (len+2); ! 57: } ! 58: ! 59: void die(s) ! 60: char *s; ! 61: { ! 62: perror(s); ! 63: exit(1); ! 64: } ! 65: ! 66: extern long *malloc(); /* wrong but convenient */ ! 67: ! 68: ! 69: /* link: ! 70: * append the code from file to linked code. pc is the relative starting address, ! 71: * last = 1, if this is the last file to link. ! 72: */ ! 73: int link (file, pc, last) ! 74: char *file; long pc; int last; ! 75: { ! 76: int fd; ! 77: long i, len, n, nbytes; ! 78: char *s; ! 79: struct stat st; ! 80: static int bufsize = 0; ! 81: static long *buf; ! 82: ! 83: if ((fd = open(file, 0)) == -1) { ! 84: char buf[64]; ! 85: sprintf(buf, "open: %s", file); ! 86: die(buf); ! 87: } ! 88: if (fstat(fd, &st) == -1) ! 89: die("stat"); ! 90: ! 91: n = st.st_size; ! 92: len = strlen(file); ! 93: nbytes = align(n) + align(len) + 6 * LONG; ! 94: ! 95: if (n + len + 40 > bufsize) { ! 96: bufsize = n + len + 4096; ! 97: if (buf != NULL) ! 98: free(buf); ! 99: buf = malloc(bufsize); ! 100: if (buf == NULL) ! 101: die("malloc(buf)"); ! 102: } ! 103: ! 104: /* initialize the header record and add its fields to the list of ! 105: * relocatable addresses. ! 106: */ ! 107: buf[0] = mak_desc(3, tag_record); ! 108: #ifdef SPARC ! 109: #define REL(addr, addend) \ ! 110: (*rel = rconst, rel->r_addend = (addend), (rel++)->r_address = (addr)) ! 111: ! 112: buf[1] = 0; ! 113: REL(pc + LONG, pc + 5 * LONG); ! 114: buf[2] = 0; ! 115: REL(pc + 2 * LONG, pc + 6 * LONG + align(len)); ! 116: if (last) ! 117: buf[3] = 1; /* either ML 0 */ ! 118: else { ! 119: buf[3] = 0; ! 120: REL(pc + 3 * LONG, pc + nbytes + LONG); ! 121: } ! 122: #else ! 123: ! 124: #define REL(addr) (*rel = rconst, (rel++)->r_address = (addr)) ! 125: ! 126: buf[1] = pc + 5 * LONG; /* address of file name */ ! 127: REL(pc + LONG); ! 128: buf[2] = buf[1] + LONG + align(len); /* address of code */ ! 129: REL(pc + 2 * LONG); ! 130: if (last) ! 131: buf[3] = 1; /* either ML 0 */ ! 132: else { ! 133: buf[3] = pc + nbytes + LONG; /* or the address of next module */ ! 134: REL(pc + 3 * LONG); ! 135: } ! 136: #endif ! 137: ! 138: buf[4] = mak_desc(len, tag_string); /* tag for file name */ ! 139: strcpy(&buf[5], file); ! 140: s = ((char *) &buf[5]) + len; ! 141: for (i = align(len); i > len; i--) ! 142: *s++ = 0; ! 143: ! 144: *((long *) s) = mak_desc(n, tag_string); /* tag for code */ ! 145: s += LONG; ! 146: ! 147: /* record this structure in the symbol and string tables */ ! 148: *nl = nlconst; ! 149: nl->n_un.n_strx = str_tbl->len; ! 150: nl->n_value = pc + 6*LONG + align(len); /* relative code address */ ! 151: nl++; ! 152: add_name(file); ! 153: ! 154: if (read(fd, s, n) != n) ! 155: die("read"); ! 156: s += n; ! 157: for (i = align(n); i > n; i--) ! 158: *s++ = 0; ! 159: ! 160: if (close(fd) == -1) ! 161: die("close"); ! 162: ! 163: assert(s - nbytes == (char *) buf); ! 164: write(1, buf, nbytes); ! 165: return nbytes; ! 166: } ! 167: ! 168: int main(argc, argv) ! 169: int argc; ! 170: char *argv[]; ! 171: { ! 172: long pc = 0; ! 173: struct exec exec; ! 174: struct nlist *nlbase; ! 175: struct relocation_info *relbase; ! 176: int i, sz; ! 177: ! 178: /* allocate space for the string table */ ! 179: sz = strlen(SYMBOL)+strlen(END_SYMBOL)+LONG+1; ! 180: for (i = 1; i < argc; i++) ! 181: sz += strlen(argv[i])+2; ! 182: str_tbl = (struct str_table *) malloc(align(sz)); ! 183: if ((long)str_tbl == NULL) ! 184: die("malloc(str_tbl)"); ! 185: ! 186: /* initialize the string table buffer with the "_datalist" string */ ! 187: str_ptr = str_tbl->strs; ! 188: strcpy(str_ptr, SYMBOL); ! 189: str_ptr += strlen(SYMBOL)+1; ! 190: str_tbl->len = LONG + strlen(SYMBOL)+1; ! 191: ! 192: /* Allocate space for nlist and reloc info buffers */ ! 193: nl = nlbase = (struct nlist *) malloc((argc+1) * sizeof(struct nlist)); ! 194: if ((long) nl == NULL) ! 195: die("malloc(nl)"); ! 196: rel = relbase = (struct relocation_info *) malloc(3 * argc * RELINFO_SZ); ! 197: if ((long) rel == NULL) ! 198: die("malloc(rel)"); ! 199: ! 200: /* build a nlist constant to initialize from, and initialize the datalist entry. */ ! 201: nlconst.n_other = 0; ! 202: nlconst.n_desc = 0; ! 203: if (argc > 1) { ! 204: nlconst.n_type = N_EXT | N_TEXT; /* global in text area */ ! 205: nlconst.n_value = 4; /* for datalist */ ! 206: } ! 207: else { ! 208: /* Actually, there is only one symbol (ie., datalist) */ ! 209: nlconst.n_type = N_EXT | N_ABS; ! 210: nlconst.n_value = 1; /* ML zero */ ! 211: } ! 212: *nl = nlconst; (nl++)->n_un.n_strx = 4; /* datalist, first string table entry */ ! 213: ! 214: /* build a relocation constant to assign from */ ! 215: #ifdef SPARC ! 216: rconst.r_address = 0; ! 217: rconst.r_index = N_TEXT; ! 218: rconst.r_extern = 0; /* r_index is the segment (text) */ ! 219: rconst.r_type = RELOC_32; ! 220: rconst.r_addend = 0; ! 221: #else ! 222: rconst.r_address = 0; ! 223: rconst.r_symbolnum = 4; /* i don't know why this works. magic? */ ! 224: rconst.r_pcrel = 0; ! 225: rconst.r_length = 2; /* long */ ! 226: rconst.r_extern = 0; ! 227: #endif ! 228: ! 229: /* initialize the header, we fill in the text size info later */ ! 230: #ifdef M68 ! 231: exec.a_machtype = M_68020; ! 232: #endif ! 233: #ifdef SPARC ! 234: exec.a_dynamic = 0; ! 235: exec.a_machtype = M_SPARC; ! 236: exec.a_toolversion = 1; ! 237: #endif ! 238: exec.a_magic = OMAGIC; ! 239: exec.a_data = 0; ! 240: exec.a_bss = 0; ! 241: /* one per mo plus "datalist" and "_endmo" */ ! 242: exec.a_syms = (argc+1) * sizeof(struct nlist); ! 243: exec.a_entry = 0; ! 244: exec.a_drsize = 0; ! 245: if (write(1, &exec, sizeof exec) == -1) ! 246: die("write"); ! 247: ! 248: for (i=1; i<argc; i++) ! 249: pc += link(argv[i], pc, i==argc-1); ! 250: ! 251: exec.a_text = pc; ! 252: exec.a_trsize = (rel - relbase) * RELINFO_SZ; ! 253: ! 254: if (write(1, relbase, exec.a_trsize) == -1) ! 255: die("write(rel)"); ! 256: ! 257: /* Add "_endmo" to the name list and string table */ ! 258: *nl = nlconst; ! 259: nl->n_un.n_strx = str_tbl->len; ! 260: nl->n_type = N_EXT | N_TEXT; ! 261: nl->n_value = pc; ! 262: nl++; ! 263: strcpy(str_ptr, END_SYMBOL); ! 264: str_tbl->len += strlen(END_SYMBOL)+1; ! 265: ! 266: /* write out the symbol table. */ ! 267: if (write(1, nlbase, exec.a_syms) == -1) ! 268: die("write(nl)"); ! 269: ! 270: /* write out the string table */ ! 271: if (write(1, str_tbl, str_tbl->len) == -1) ! 272: die("write(str_tbl)"); ! 273: ! 274: /* update the header to reflect the true text size */ ! 275: if (lseek(1, 0, 0L) == -1) ! 276: die("lseek"); ! 277: if (write(1, &exec, sizeof exec) == -1) ! 278: die("write(exec)"); ! 279: ! 280: return 0; ! 281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.