|
|
1.1 ! root 1: /* coff.c -- rutines for manipulating coff executable files. */ ! 2: ! 3: #include <a_out.h> ! 4: #include "tboot.h" ! 5: ! 6: /* Convert COFF to load table. ! 7: * Used to generate loading instructions for use by tboot main(). ! 8: * Returns true on successful translation. ! 9: */ ! 10: ! 11: int ! 12: coff2load(ip, table, data_seg) ! 13: struct inode *ip; /* input: File to read. */ ! 14: struct load_segment table[]; /* output: How to read it. */ ! 15: uint16 *data_seg; /* output: Where to point es. */ ! 16: { ! 17: FILHDR fh; /* COFF file header. */ ! 18: AOUTHDR oh; /* COFF optional header. */ ! 19: SCNHDR sh; /* COFF section header. */ ! 20: ! 21: int i, j; /* Loop counters. */ ! 22: fsize_t section_seek; /* Seek counter for section headers. */ ! 23: ! 24: /* Read the file header. */ ! 25: iread(ip, &fh, (fsize_t) 0, (uint16) sizeof (fh)); ! 26: ! 27: ! 28: /* Check for the 5000 possible failures... */ ! 29: /* Is this really a i386 COFF file? */ ! 30: if (I386MAGIC != fh.f_magic) { ! 31: puts("COFF COFF! File header bad magic.\r\n"); ! 32: puts("This is not an i386 COFF file.\r\n"); ! 33: return (1==2); ! 34: } ! 35: ! 36: /* Is this an executable COFF file? */ ! 37: if (!(fh.f_flags & F_EXEC)) { ! 38: puts("Non-executable COFF file.\r\n"); ! 39: return (1==2); ! 40: } ! 41: ! 42: /* Does it have the information we need to execute it? */ ! 43: if (sizeof(oh) != fh.f_opthdr) { ! 44: puts("COFF optional header is wrong size.\r\n"); ! 45: return (1==2); ! 46: } ! 47: ! 48: /* Pointless witticism: */ ! 49: if (fh.f_timdat < 0x1000) { ! 50: puts( ! 51: "Wow! An executable from the first few thousand seconds of time!\r\n" ! 52: ); ! 53: } ! 54: ! 55: /* ASSERTION: We know this to be an executable i386 COFF file. */ ! 56: ! 57: /* Read the optional header. */ ! 58: /* This is the one with the data we really want. */ ! 59: iread(ip, &oh, (fsize_t) sizeof(fh), (uint16) sizeof (oh)); ! 60: ! 61: /* Validate the optional header. */ ! 62: ! 63: if (NORMAL_MAGIC != oh.magic) { ! 64: puts("COFF COFF! Optional header bad magic.\r\n"); ! 65: puts("This isn't a normal executable file.\r\n"); ! 66: return(1==2); ! 67: } ! 68: ! 69: /* Read through the section headers, ! 70: * looking for text and data segments, and ! 71: * turning them into little toads. Or something like that. ! 72: */ ! 73: ! 74: #define TEXT table[0] ! 75: #define DATA table[1] ! 76: ! 77: /* Loop until we have both the sections we want, at most twice. */ ! 78: for (TEXT.valid = (1==2), DATA.valid = (1==2), j = 0; ! 79: !(TEXT.valid && DATA.valid) && j < 2; ! 80: ++j) { ! 81: ! 82: for (section_seek = sizeof(FILHDR)+sizeof(AOUTHDR), i = 0; ! 83: i < fh.f_nscns; /* i < number of sections */ ! 84: section_seek += SCNHSZ, ++i) { ! 85: ! 86: iread(ip, &sh, section_seek, SCNHSZ); ! 87: switch ((int) sh.s_flags) { ! 88: case STYP_TEXT: ! 89: TEXT.valid = (1==1); ! 90: TEXT.message = "\r\nLoading COFF text.\r\n"; ! 91: TEXT.load_toseg = sys_base; ! 92: TEXT.load_tooffset = 0; ! 93: TEXT.load_offset = sh.s_scnptr; ! 94: TEXT.load_length = sh.s_size; ! 95: break; ! 96: ! 97: case STYP_DATA: ! 98: /* The text header must already have been read to ! 99: * put meaningful numbers here. ! 100: */ ! 101: if (TEXT.valid) { ! 102: DATA.valid = (1==1); ! 103: DATA.message = "\r\nLoading COFF data.\r\n"; ! 104: /* Round up to next paragraph beyond end ! 105: * of text. ! 106: */ ! 107: DATA.load_toseg = (sys_base + ! 108: (TEXT.load_length + 15) / 16); ! 109: DATA.load_tooffset = 0; ! 110: DATA.load_offset = sh.s_scnptr; ! 111: DATA.load_length = sh.s_size; ! 112: *data_seg = (sys_base + ! 113: (TEXT.load_length + 15) / 16); ! 114: } ! 115: break; ! 116: case STYP_BSS: ! 117: break; ! 118: default: ! 119: puts("Warning. Unrecognized COFF section.\r\n"); ! 120: break; ! 121: } /* switch (sh.s_flags) */ ! 122: ! 123: } /* for walk through headers */ ! 124: ! 125: } /* while haven't got both, at most twice */ ! 126: ! 127: if (!TEXT.valid) { ! 128: puts("Failed to find COFF text section.\r\n"); ! 129: return (1==2); ! 130: } ! 131: ! 132: if (!DATA.valid) { ! 133: puts("Failed to find COFF data section.\r\n"); ! 134: return (1==2); ! 135: } ! 136: ! 137: table[2].valid = (1==2); /* Terminate the list. */ ! 138: ! 139: return(1==1); ! 140: } ! 141: ! 142: ! 143: /* ! 144: * Symbol name. ! 145: */ ! 146: static char * ! 147: symName(sym, str_tab, work) ! 148: SYMENT *sym; ! 149: char *str_tab, *work; ! 150: { ! 151: if (!sym->_n._n_n._n_zeroes) ! 152: return (str_tab + sym->_n._n_n._n_offset - 4); ! 153: ! 154: memcpy(work, sym->_n._n_name, SYMNMLEN); ! 155: work[SYMNMLEN] = '\0'; ! 156: return (work); ! 157: } ! 158: ! 159: /* ! 160: * Look up the value of a single data symbol in a coff file, ! 161: * relative to the start of the data segment. ! 162: * ! 163: * We use the symbol "sdata" to find the start of the data segment-- ! 164: * this works for 386 COHERENT kernels but will not work in general. ! 165: * It should really fetch the address of the start of the data segment ! 166: * from the data section header. ! 167: */ ! 168: uint32 ! 169: wrap_coffnlist(fn, symbol) ! 170: char *fn; /* file name */ ! 171: char *symbol; /* symbol to look up */ ! 172: { ! 173: /* Something goes wrong with looking up symbol if ! 174: * nlp is automatic rather than static, even with a huge stack. ! 175: */ ! 176: static SYMENT nlp[2]; ! 177: uint32 retval; ! 178: ! 179: /* Start of the data segment. */ ! 180: strcpy(nlp[0]._n._n_name, "sdata"); ! 181: nlp[0].n_type = -1; ! 182: ! 183: nlp[1]._n._n_n._n_zeroes = 0; ! 184: nlp[1]._n._n_n._n_offset = sizeof(int32); ! 185: nlp[1].n_type = -1; ! 186: ! 187: coffnlist(fn, nlp, symbol, 2); ! 188: ! 189: retval = ((uint32)nlp[1].n_value) - ((uint32)nlp[0].n_value); ! 190: ! 191: if (0L == nlp[1].n_value) { ! 192: return(0L); ! 193: } else { ! 194: return(retval); ! 195: } ! 196: puts("Unreachable code in wrap_coffnlist().\r\n"); ! 197: return(0L); ! 198: } /* wrap_coffnlist() */ ! 199: ! 200: int ! 201: coffnlist(fn, nlp, names, count) ! 202: char *fn; /* file name */ ! 203: SYMENT *nlp; /* names to look up */ ! 204: char *names; /* long names */ ! 205: int count; /* size of passed table */ ! 206: { ! 207: FILHDR head; ! 208: int fp; ! 209: /* str_tab should be malloc'd. Blows up silently if longer than 2k. */ ! 210: #define STR_TAB_SIZE 2048 ! 211: char str_tab[STR_TAB_SIZE]; ! 212: long str_length; ! 213: int aux, i; ! 214: ! 215: if (-1 == (fp = open(fn, 0))) ! 216: return(0); ! 217: ! 218: if (FILHSZ != read(fp, &head, FILHSZ) || head.f_magic != I386MAGIC) { ! 219: close (fp); ! 220: return (0); ! 221: } ! 222: ! 223: lseek(fp, head.f_symptr + (SYMESZ * head.f_nsyms), 0); ! 224: ! 225: if (sizeof(str_length) != read(fp, &str_length, sizeof(str_length))) ! 226: str_length = 0; ! 227: if (str_length) { ! 228: uint16 len; ! 229: ! 230: len = str_length -= 4; ! 231: if (len != str_length || len > STR_TAB_SIZE) { ! 232: close (fp); ! 233: return (0); ! 234: } ! 235: ! 236: if (len != read(fp, str_tab, len)) { ! 237: close (fp); ! 238: return (0); ! 239: } ! 240: } ! 241: ! 242: lseek(fp, head.f_symptr, 0); ! 243: for (i = aux = 0; i < head.f_nsyms; i++) { ! 244: SYMENT sym; /* symbol read in */ ! 245: int taux, j; ! 246: ! 247: if (SYMESZ != read(fp, &sym, SYMESZ)) { ! 248: close (fp); ! 249: return (0); ! 250: } ! 251: ! 252: if (aux) { ! 253: aux--; ! 254: continue; ! 255: } ! 256: aux = sym.n_numaux; ! 257: for (j = taux = 0; j < count; j++) { ! 258: static char n1[SYMNMLEN + 1], n2[SYMNMLEN + 1]; ! 259: register SYMENT *np; ! 260: ! 261: if (taux) { ! 262: taux--; ! 263: continue; ! 264: } ! 265: np = nlp + j; ! 266: taux = np->n_numaux; ! 267: if (np->n_type != -1 || ! 268: strcmp(symName(np, names, n1), ! 269: symName(&sym, str_tab, n2))) ! 270: continue; ! 271: np->n_value = sym.n_value; ! 272: np->n_scnum = sym.n_scnum; ! 273: np->n_type = sym.n_type; ! 274: np->n_sclass = sym.n_sclass; ! 275: break; ! 276: } ! 277: } ! 278: close (fp); ! 279: return (1); ! 280: } ! 281: ! 282: #ifdef TEST ! 283: #include <stdio.h> ! 284: ! 285: main() ! 286: { ! 287: int i; ! 288: static SYMENT sym[3]; ! 289: static char ptr[]="rootdev"; ! 290: ! 291: strcpy(sym[0]._n._n_name, "NCLIST"); ! 292: sym[0].n_type = -1; ! 293: ! 294: strcpy(sym[1]._n._n_name, "sdata"); ! 295: sym[1].n_type = -1; ! 296: ! 297: sym[2]._n._n_n._n_zeroes = 0; ! 298: sym[2]._n._n_n._n_offset = sizeof(int32); ! 299: sym[2].n_type = -1; ! 300: ! 301: coffnlist("/at386", sym, ptr, 3); ! 302: ! 303: for (i = 0; i < 3; ++i) { ! 304: printf("sym[%d]._n._n_name: %s\n", i, sym[i]._n._n_name); ! 305: printf("sym[%d].n_value: %lx\n\n", i, sym[i].n_value); ! 306: } ! 307: ! 308: printf("\nrootdev as offset: %lx\n", ! 309: wrap_coffnlist("/at386", "rootdev")); ! 310: } ! 311: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.