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