1: /* 2: * netbind 3: * 4: * 1/6/95 -- remove 8 character limit on undefined symbol printf. sms. 5: * 1/8/94 -- revised for new object file format. sms. 6: * 7: * Resolve undefined inter-address-space references. 8: * 9: * Usage: 10: * netbind unix.o netnix.o 11: * 12: * Produces two files as output: 13: * 14: * d.unix.s -- definitions of all symbols referenced by 15: * unix.o but defined in netnix.o 16: * d.netnix.s -- definitions of all symbols referenced by 17: * netnix.o but defined in unix.o 18: */ 19: #include <sys/param.h> 20: #include <sys/file.h> 21: #include <a.out.h> 22: #include <stdio.h> 23: 24: extern char *strdup(), *rindex(); 25: 26: struct xexec refExec, defExec; 27: 28: #define MAXSYMLEN 32 29: 30: #define NSYMS 200 31: struct symbol { 32: char *s_name; 33: u_int s_value; 34: u_int s_type; 35: } symtab[NSYMS], *symfree; 36: 37: main(argc, argv) 38: int argc; 39: char **argv; 40: { 41: if (argc != 3) { 42: printf("usage: %s unix.bo netnix.bo\n", *argv); 43: exit(2); 44: } 45: resolve(argv[1], argv[2]); /* Produces d.unix.s */ 46: resolve(argv[2], argv[1]); /* Produces d.netnix.s */ 47: exit(0); 48: } 49: 50: /* 51: * resolve -- 52: * 53: * Resolve references made by ref to symbols defined in def. 54: * 55: * Side effects: 56: * Prints a list of undefined symbols if there are any. 57: * Produces the .s file corresponding to ref. 58: * Adds the number of undefined symbols encountered to undef. 59: */ 60: resolve(ref, def) 61: char *ref; /* Name of file referencing symbols */ 62: char *def; /* Name of file defining symbols */ 63: { 64: FILE *refIN, *defIN, *refSTR, *defSTR, *refOUT, *openobj(); 65: struct nlist syment; 66: off_t stroff_ref, stroff_def; 67: int nundef; 68: char *rp, refout[MAXPATHLEN], name[MAXSYMLEN + 2]; 69: 70: bzero(name, sizeof (name)); 71: if (rp = rindex(ref, '.')) 72: *rp = '\0'; 73: (void)sprintf(refout, "d.%s.s", ref); 74: if (rp) 75: *rp = '.'; 76: if ((refIN = openobj(ref, &refExec, &refSTR)) == NULL) 77: return; 78: if ((defIN = openobj(def, &defExec, &defSTR)) == NULL) { 79: fclose(refIN); 80: fclose(refSTR); 81: return; 82: } 83: if ((refOUT = fopen(refout, "w")) == NULL) { 84: perror(refout); 85: fclose(refIN); 86: fclose(refSTR); 87: fclose(defIN); 88: fclose(defSTR); 89: return; 90: } 91: 92: /* 93: * Actually generate the .s file needed. 94: * Assumes that refExec and defExec have been set up to 95: * hold the a.out headers for the reference and definition 96: * object files. 97: * 98: * Algorithm: 99: * Build a table of undefined symbols in refIN. 100: * Define them by reading the symbol table of defIN. 101: * Generate the .s file to refOUT. 102: */ 103: syminit(); 104: nundef = 0; 105: 106: /* Find the undefined symbols */ 107: stroff_ref = N_STROFF(refExec); 108: fseek(refIN, N_SYMOFF(refExec), L_SET); 109: while (fread(&syment, sizeof(syment), 1, refIN) > 0) { 110: if (syment.n_type == (N_EXT|N_UNDF) && syment.n_value == 0) 111: { 112: fseek(refSTR, stroff_ref + syment.n_un.n_strx, L_SET); 113: fread(name, sizeof (name), 1, refSTR); 114: if (strcmp(name, "_end") && 115: strcmp(name, "_etext") && 116: strcmp(name, "_edata")) 117: { 118: nundef++; 119: syment.n_un.n_name = name; 120: symadd(&syment); 121: } 122: } 123: } 124: 125: /* Define the undefined symbols */ 126: stroff_def = N_STROFF(defExec); 127: fseek(defIN, N_SYMOFF(defExec), L_SET); 128: while (fread(&syment, sizeof(syment), 1, defIN) > 0) { 129: if ((syment.n_type & N_EXT) == 0) 130: continue; 131: fseek(defSTR, stroff_def + syment.n_un.n_strx, L_SET); 132: fread(name, sizeof (name), 1, defSTR); 133: syment.n_un.n_name = name; 134: nundef -= symdef(&syment, &defExec.e); 135: } 136: 137: /* Any undefined symbols left? */ 138: if (nundef > 0) { 139: printf("%s: %d symbols undefined:\n", ref, nundef); 140: symundef(); 141: } 142: symprdef(refOUT); 143: 144: fclose(refSTR); 145: fclose(defSTR); 146: fclose(refIN); 147: fclose(defIN); 148: fclose(refOUT); 149: } 150: 151: /* 152: * openobj -- 153: * 154: * Open the indicated file, check to make sure that it is a 155: * valid object file with a symbol table, and read in the a.out header. 156: * 157: * Returns a pointer to an open FILE if successful, NULL if not. 158: * Prints its own error messages. 159: */ 160: FILE * 161: openobj(filename, exechdr, strfp) 162: char *filename; 163: struct xexec *exechdr; 164: FILE **strfp; 165: { 166: register FILE *f; 167: 168: if (!(f = fopen(filename, "r"))) { 169: perror(filename); 170: return((FILE *)NULL); 171: } 172: *strfp = fopen(filename, "r"); /* for strings */ 173: if (fread(exechdr, sizeof(*exechdr), 1, f) <= 0) { 174: printf("%s: no a.out header\n", filename); 175: goto bad; 176: } 177: if (N_BADMAG(exechdr->e)) { 178: printf("%s: bad magic number\n", filename); 179: goto bad; 180: } 181: if (exechdr->e.a_syms == 0) { 182: printf("%s: no symbol table\n", filename); 183: goto bad; 184: } 185: return(f); 186: bad: fclose(f); 187: fclose(*strfp); 188: return((FILE *)NULL); 189: } 190: 191: /* -------------------- Symbol table management ----------------------- */ 192: 193: /* 194: * syminit -- 195: * 196: * Clear and initialize the symbol table. 197: */ 198: syminit() 199: { 200: symfree = symtab; 201: } 202: 203: /* 204: * symadd -- 205: * 206: * Add a symbol to the table. 207: * We store both the symbol name and the symbol number. 208: */ 209: symadd(np) 210: struct nlist *np; 211: { 212: if (symfree >= &symtab[NSYMS]) { 213: printf("Symbol table overflow. Increase NSYMS.\n"); 214: exit (1); 215: } 216: symfree->s_name = strdup(np->n_un.n_name); 217: if (!symfree->s_name) 218: { 219: printf("netbind: out of memory for symbol strings\n"); 220: exit(1); 221: } 222: symfree->s_type = N_UNDF; 223: symfree->s_value = 0; 224: symfree++; 225: } 226: 227: /* 228: * symdef -- 229: * 230: * Use the supplied symbol to define an undefined entry in 231: * the symbol table. 232: * 233: * Returns 1 if the name of the symbol supplied was found in 234: * the table, 0 otherwise. 235: */ 236: symdef(np, ep) 237: struct nlist *np; 238: struct exec *ep; 239: { 240: register struct symbol *sp; 241: 242: for (sp = symtab; sp < symfree; sp++) 243: if (!strcmp(sp->s_name, np->n_un.n_name)) { 244: int type = (np->n_type & N_TYPE); 245: 246: switch (type) { 247: case N_TEXT: 248: case N_ABS: 249: sp->s_type = N_EXT|N_ABS; 250: sp->s_value = np->n_value; 251: break; 252: case N_DATA: 253: case N_BSS: 254: sp->s_type = N_EXT|N_ABS; 255: if (ep->a_flag) 256: sp->s_value = np->n_value; 257: else 258: sp->s_value = np->n_value - ep->a_text; 259: break; 260: case N_UNDF: 261: return(0); 262: default: 263: printf("netbind: symbol %s, bad type 0x%x\n", 264: np->n_un.n_name, np->n_type); 265: exit(1); 266: } 267: return (1); 268: } 269: return(0); 270: } 271: 272: /* 273: * symundef -- 274: * 275: * Print all undefined symbols in the symbol table. 276: * First sorts the table before printing it. 277: */ 278: symundef() 279: { 280: register struct symbol *sp; 281: int scmp(); 282: 283: qsort(symtab, symfree - symtab, sizeof(struct symbol), scmp); 284: for (sp = symtab; sp < symfree; sp++) 285: if ((sp->s_type & N_TYPE) == N_UNDF) 286: printf("%s\n", sp->s_name); 287: } 288: 289: scmp(s1, s2) 290: register struct symbol *s1, *s2; 291: { 292: return(strcmp(s1->s_name, s2->s_name)); 293: } 294: 295: /* 296: * symprdef -- 297: * 298: * Output all defined symbols in the symbol table. 299: * First sorts the table before printing it. 300: */ 301: symprdef(refOUT) 302: FILE *refOUT; 303: { 304: register struct symbol *sp; 305: int scmp(); 306: 307: qsort(symtab, symfree - symtab, sizeof (struct symbol), scmp); 308: for (sp = symtab; sp < symfree; sp++) 309: if ((sp->s_type & N_TYPE) != N_UNDF) { 310: fprintf(refOUT, ".globl %s\n", sp->s_name); 311: fprintf(refOUT, "%s = %o\n", sp->s_name, sp->s_value); 312: } 313: }