int rdl_verify(const char *filename) { FILE *fp; char buf[257]; int i; int32_t length; static char lastverified[256]; static int lastresult = -1; if (lastresult != -1 && !strcmp(filename, lastverified)) return lastresult; fp = fopen(filename, "rb"); strcpy(lastverified, filename); if (!fp) return (rdl_error = lastresult = 1); while (!feof(fp)) { i = 0; while (fread(buf + i, 1, 1, fp) == 1 && i < 257 && buf[i]) i++; if (feof(fp)) break; if (buf[0] == '.') { /* * A special module, eg a signature block or a directory. * Format of such a module is defined to be: * six char type identifier * int32_t count bytes content * content * so we can handle it uniformaly with RDOFF2 modules. */ nasm_read(buf, 6, fp); buf[6] = 0; /* Currently, nothing useful to do with signature block.. */ } else { nasm_read(buf, 6, fp); buf[6] = 0; if (strncmp(buf, "RDOFF", 5)) { fclose(fp); return rdl_error = lastresult = 2; } else if (buf[5] != '2') { fclose(fp); return rdl_error = lastresult = 3; } } nasm_read(&length, 4, fp); fseek(fp, length, SEEK_CUR); /* skip over the module */ } fclose(fp); return lastresult = 0; /* library in correct format */ }
int rdl_openmodule(struct librarynode *lib, int moduleno, rdffile * f) { char buf[512]; int i, cmod, t; int32_t length; lib->referenced++; if (!lib->fp) { lib->fp = fopen(lib->name, "rb"); if (!lib->fp) { lib->referenced--; return (rdl_error = 1); } } else rewind(lib->fp); cmod = -1; while (!feof(lib->fp)) { strcpy(buf, lib->name); i = strlen(buf); buf[i++] = '.'; t = i; while (fread(buf + i, 1, 1, lib->fp) == 1 && i < 512 && buf[i]) i++; buf[i] = 0; if (feof(lib->fp)) break; if (buf[t] != '.') /* special module - not counted in the numbering */ cmod++; /* of RDOFF modules - must be referred to by name */ if (cmod == moduleno) { rdl_error = 16 * rdfopenhere(f, lib->fp, &lib->referenced, buf); lib->referenced--; if (!lib->referenced) { fclose(lib->fp); lib->fp = NULL; } return rdl_error; } nasm_read(buf, 6, lib->fp); buf[6] = 0; if (buf[t] == '.') { /* do nothing */ } else if (strncmp(buf, "RDOFF", 5)) { if (!--lib->referenced) { fclose(lib->fp); lib->fp = NULL; } return rdl_error = 2; } else if (buf[5] != '2') { if (!--lib->referenced) { fclose(lib->fp); lib->fp = NULL; } return rdl_error = 3; } nasm_read(&length, 4, lib->fp); fseek(lib->fp, length, SEEK_CUR); /* skip over the module */ } if (!--lib->referenced) { fclose(lib->fp); lib->fp = NULL; } return rdl_error = 4; /* module not found */ }
static void print_header(int32_t length, int rdf_version) { char buf[129], t, l, s, flags; uint8_t reclen; int32_t o, ll; uint16_t rs; while (length > 0) { nasm_read(&t, 1, infile); if (rdf_version >= 2) { nasm_read(&reclen, 1, infile); } switch (t) { case RDFREC_GENERIC: /* generic record */ printf(" generic record (length=%d)\n", (int)reclen); fseek(infile, reclen, SEEK_CUR); break; case RDFREC_RELOC: /* relocation record */ case RDFREC_SEGRELOC: /* segment relocation */ nasm_read(&s, 1, infile); nasm_read(&o, 4, infile); nasm_read(&l, 1, infile); nasm_read(&rs, 2, infile); printf(" %s: location (%04x:%08"PRIx32"), length %d, " "referred seg %04x\n", t == 1 ? "relocation" : "seg relocation", (int)s, translateint32_t(o), (int)l, translateint16_t(rs)); if (rdf_version >= 2 && reclen != 8) printf(" warning: reclen != 8\n"); if (rdf_version == 1) length -= 9; if (rdf_version == 1 && t == 6) printf (" warning: seg relocation not supported in RDOFF1\n"); break; case RDFREC_IMPORT: /* import record */ case RDFREC_FARIMPORT: /* import far symbol */ nasm_read(&flags, 1, infile); nasm_read(&rs, 2, infile); ll = 0; if (rdf_version == 1) { do { nasm_read(&buf[ll], 1, infile); } while (buf[ll++]); } else { for (; ll < reclen - 3; ll++) nasm_read(&buf[ll], 1, infile); } if (t == 7) printf("far "); printf((flags & SYM_IMPORT) ? " import" : " extern"); if (flags & SYM_FUNCTION) printf(" proc"); if (flags & SYM_DATA) printf(" data"); printf(": segment %04x = %s\n", translateint16_t(rs), buf); if (rdf_version == 1) length -= ll + 3; if (rdf_version == 1 && t == 7) printf (" warning: far import not supported in RDOFF1\n"); break; case RDFREC_GLOBAL: /* export record */ nasm_read(&flags, 1, infile); nasm_read(&s, 1, infile); nasm_read(&o, 4, infile); ll = 0; if (rdf_version == 1) { do { nasm_read(&buf[ll], 1, infile); } while (buf[ll++]); } else { for (; ll < reclen - 6; ll++) nasm_read(&buf[ll], 1, infile); } printf((flags & SYM_GLOBAL) ? " export" : " public"); if (flags & SYM_FUNCTION) printf(" proc"); if (flags & SYM_DATA) printf(" data"); printf(": (%04x:%08"PRIx32") = %s\n", (int)s, translateint32_t(o), buf); if (rdf_version == 1) length -= ll + 6; break; case RDFREC_DLL: /* DLL and Module records */ case RDFREC_MODNAME: ll = 0; if (rdf_version == 1) { do { nasm_read(&buf[ll], 1, infile); } while (buf[ll++]); } else { for (; ll < reclen; ll++) nasm_read(&buf[ll], 1, infile); } if (t == 4) printf(" dll: %s\n", buf); else printf(" module: %s\n", buf); if (rdf_version == 1) length -= ll + 1; break; case RDFREC_BSS: /* BSS reservation */ nasm_read(&ll, 4, infile); printf(" bss reservation: %08"PRIx32" bytes\n", translateint32_t(ll)); if (rdf_version == 1) length -= 5; if (rdf_version > 1 && reclen != 4) printf(" warning: reclen != 4\n"); break; case RDFREC_COMMON:{ uint16_t seg, align; uint32_t size; nasm_read(&seg, 2, infile); nasm_read(&size, 4, infile); nasm_read(&align, 2, infile); for (ll = 0; ll < reclen - 8; ll++) nasm_read(buf + ll, 1, infile); printf(" common: segment %04x = %s, %"PRId32":%d\n", translateint16_t(seg), buf, translateint32_t(size), translateint16_t(align)); break; } default: printf(" unrecognized record (type %d", (int)t); if (rdf_version > 1) { printf(", length %d", (int)reclen); fseek(infile, reclen, SEEK_CUR); } else length--; printf(")\n"); } if (rdf_version != 1) length -= 2 + reclen; } }
int rdl_searchlib(struct librarynode *lib, const char *label, rdffile * f) { char buf[512]; int i, t; void *hdr; rdfheaderrec *r; int32_t l; rdl_error = 0; lib->referenced++; if (!lib->fp) { lib->fp = fopen(lib->name, "rb"); if (!lib->fp) { rdl_error = 1; return 0; } } else rewind(lib->fp); while (!feof(lib->fp)) { /* * read the module name from the file, and prepend * the library name and '.' to it. */ strcpy(buf, lib->name); i = strlen(lib->name); buf[i++] = '.'; t = i; while (fread(buf + i, 1, 1, lib->fp) == 1 && i < 512 && buf[i]) i++; buf[i] = 0; if (feof(lib->fp)) break; if (!strcmp(buf + t, ".dir")) { /* skip over directory */ nasm_read(&l, 4, lib->fp); fseek(lib->fp, l, SEEK_CUR); continue; } /* * open the RDOFF module */ if (rdfopenhere(f, lib->fp, &lib->referenced, buf)) { rdl_error = 16 * rdf_errno; return 0; } /* * read in the header, and scan for exported symbols */ hdr = nasm_malloc(f->header_len); rdfloadseg(f, RDOFF_HEADER, hdr); while ((r = rdfgetheaderrec(f))) { if (r->type != 3) /* not an export */ continue; if (!strcmp(r->e.label, label)) { /* match! */ nasm_free(hdr); /* reset to 'just open' */ f->header_loc = NULL; /* state... */ f->header_fp = 0; return 1; } } /* find start of next module... */ i = f->eof_offset; rdfclose(f); fseek(lib->fp, i, SEEK_SET); } /* * close the file if nobody else is using it */ lib->referenced--; if (!lib->referenced) { fclose(lib->fp); lib->fp = NULL; } return 0; }
int main(int argc, char **argv) { char id[7]; int32_t l; uint16_t s; int verbose = 0; int32_t offset; int foundnullsegment = 0; int version; int32_t segmentcontentlength = 0; int nsegments = 0; int32_t headerlength = 0; int32_t objectlength = 0; printf("RDOFF dump utility, version %s\n", PROGRAM_VERSION); printf("RDOFF2 revision %s\n", RDOFF2_REVISION); puts("Copyright (c) 1996,99 Julian R Hall\n" "Improvements and fixes (c) 2002-2004 RET & COM Research."); if (argc < 2) { fputs("Usage: rdfdump [-v] <filename>\n", stderr); exit(1); } rdoff_init(); if (!strcmp(argv[1], "-v")) { verbose = 1; if (argc < 3) { fputs("required parameter missing\n", stderr); exit(1); } argv++; } infile = fopen(argv[1], "rb"); if (!infile) { fprintf(stderr, "rdfdump: Could not open %s\n", argv[1]); exit(1); } nasm_read(id, 6, infile); if (strncmp(id, "RDOFF", 5)) { fputs("rdfdump: File does not contain valid RDOFF header\n", stderr); exit(1); } printf("File %s: RDOFF version %c\n\n", argv[1], id[5]); if (id[5] < '1' || id[5] > '2') { fprintf(stderr, "rdfdump: unknown RDOFF version '%c'\n", id[5]); exit(1); } version = id[5] - '0'; if (version > 1) { nasm_read(&l, 4, infile); objectlength = translateint32_t(l); printf("Object content size: %"PRId32" bytes\n", objectlength); } nasm_read(&l, 4, infile); headerlength = translateint32_t(l); printf("Header (%"PRId32" bytes):\n", headerlength); print_header(headerlength, version); if (version == 1) { nasm_read(&l, 4, infile); l = translateint32_t(l); printf("\nText segment length = %"PRId32" bytes\n", l); offset = 0; while (l--) { nasm_read(id, 1, infile); if (verbose) { if (offset % 16 == 0) printf("\n%08"PRIx32" ", offset); printf(" %02x", (int)(uint8_t)id[0]); offset++; } } if (verbose) printf("\n\n"); nasm_read(&l, 4, infile); l = translateint32_t(l); printf("Data segment length = %"PRId32" bytes\n", l); if (verbose) { offset = 0; while (l--) { nasm_read(id, 1, infile); if (offset % 16 == 0) printf("\n%08"PRIx32" ", offset); printf(" %02x", (int)(uint8_t)id[0]); offset++; } printf("\n"); } } else { do { nasm_read(&s, 2, infile); s = translateint16_t(s); if (!s) { printf("\nNULL segment\n"); foundnullsegment = 1; break; } printf("\nSegment:\n Type = %04X (%s)\n", (int)s, translatesegmenttype(s)); nsegments++; nasm_read(&s, 2, infile); printf(" Number = %04X\n", (int)translateint16_t(s)); nasm_read(&s, 2, infile); printf(" Resrvd = %04X\n", (int)translateint16_t(s)); nasm_read(&l, 4, infile); l = translateint32_t(l); printf(" Length = %"PRId32" bytes\n", l); segmentcontentlength += l; offset = 0; while (l--) { nasm_read(id, 1, infile); if (verbose) { if (offset % 16 == 0) printf("\n%08"PRIx32" ", offset); printf(" %02x", (int)(uint8_t)id[0]); offset++; } } if (verbose) printf("\n"); } while (!feof(infile)); if (!foundnullsegment) printf("\nWarning: unexpected end of file - " "NULL segment not found\n"); printf("\nTotal number of segments: %d\n", nsegments); printf("Total segment content length: %"PRId32" bytes\n", segmentcontentlength); /* calculate what the total object content length should have been */ l = segmentcontentlength + 10 * (nsegments + 1) + headerlength + 4; if (l != objectlength) printf("Warning: actual object length (%"PRId32") != " "stored object length (%"PRId32")\n", l, objectlength); } fclose(infile); return 0; }