2002-12-04 08:49:37 +08:00
|
|
|
/*
|
|
|
|
* rdfdump.c - dump RDOFF file header.
|
|
|
|
*/
|
|
|
|
|
2007-10-03 12:53:51 +08:00
|
|
|
#include "compiler.h"
|
|
|
|
|
2002-05-01 04:51:32 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2004-09-15 14:54:34 +08:00
|
|
|
#define RDOFF_UTILS
|
2002-05-01 04:51:32 +08:00
|
|
|
|
2004-09-15 14:54:34 +08:00
|
|
|
#include "rdoff.h"
|
2002-05-01 04:51:32 +08:00
|
|
|
|
2004-09-15 14:54:34 +08:00
|
|
|
#define PROGRAM_VERSION "2.3"
|
2002-05-01 04:51:32 +08:00
|
|
|
|
2004-09-15 14:54:34 +08:00
|
|
|
FILE *infile;
|
2002-05-01 04:58:18 +08:00
|
|
|
|
2007-04-12 10:40:54 +08:00
|
|
|
void print_header(int32_t length, int rdf_version)
|
2002-12-04 08:49:37 +08:00
|
|
|
{
|
2007-04-14 00:47:53 +08:00
|
|
|
char buf[129], t, l, s, flags;
|
2007-04-12 10:40:54 +08:00
|
|
|
uint8_t reclen;
|
|
|
|
int32_t o, ll;
|
2007-04-13 00:54:50 +08:00
|
|
|
uint16_t rs;
|
2003-12-12 14:18:07 +08:00
|
|
|
|
|
|
|
while (length > 0) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fread(&t, 1, 1, infile);
|
|
|
|
if (rdf_version >= 2) {
|
|
|
|
fread(&reclen, 1, 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 */
|
|
|
|
fread(&s, 1, 1, infile);
|
|
|
|
fread(&o, 4, 1, infile);
|
|
|
|
fread(&l, 1, 1, infile);
|
|
|
|
fread(&rs, 2, 1, infile);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf(" %s: location (%04x:%08"PRIx32"), length %d, "
|
2005-01-16 06:15:51 +08:00
|
|
|
"referred seg %04x\n",
|
|
|
|
t == 1 ? "relocation" : "seg relocation", (int)s,
|
2007-04-12 10:40:54 +08:00
|
|
|
translateint32_t(o), (int)l, translateint16_t(rs));
|
2005-01-16 06:15:51 +08:00
|
|
|
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 */
|
|
|
|
fread(&flags, 1, 1, infile);
|
|
|
|
fread(&rs, 2, 1, infile);
|
|
|
|
ll = 0;
|
|
|
|
|
|
|
|
if (rdf_version == 1) {
|
|
|
|
do {
|
|
|
|
fread(&buf[ll], 1, 1, infile);
|
|
|
|
} while (buf[ll++]);
|
|
|
|
} else {
|
|
|
|
for (; ll < reclen - 3; ll++)
|
|
|
|
fread(&buf[ll], 1, 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");
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(": segment %04x = %s\n", translateint16_t(rs), buf);
|
2005-01-16 06:15:51 +08:00
|
|
|
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 */
|
|
|
|
fread(&flags, 1, 1, infile);
|
|
|
|
fread(&s, 1, 1, infile);
|
|
|
|
fread(&o, 4, 1, infile);
|
|
|
|
ll = 0;
|
|
|
|
|
|
|
|
if (rdf_version == 1) {
|
|
|
|
do {
|
|
|
|
fread(&buf[ll], 1, 1, infile);
|
|
|
|
} while (buf[ll++]);
|
|
|
|
} else {
|
|
|
|
for (; ll < reclen - 6; ll++)
|
|
|
|
fread(&buf[ll], 1, 1, infile);
|
|
|
|
}
|
|
|
|
printf((flags & SYM_GLOBAL) ? " export" : " public");
|
|
|
|
if (flags & SYM_FUNCTION)
|
|
|
|
printf(" proc");
|
|
|
|
if (flags & SYM_DATA)
|
|
|
|
printf(" data");
|
2007-04-14 09:24:14 +08:00
|
|
|
printf(": (%04x:%08"PRIx32") = %s\n", (int)s, translateint32_t(o), buf);
|
2005-01-16 06:15:51 +08:00
|
|
|
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 {
|
|
|
|
fread(&buf[ll], 1, 1, infile);
|
|
|
|
} while (buf[ll++]);
|
|
|
|
} else {
|
|
|
|
for (; ll < reclen; ll++)
|
|
|
|
fread(&buf[ll], 1, 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 */
|
|
|
|
fread(&ll, 4, 1, infile);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf(" bss reservation: %08"PRIx32" bytes\n", translateint32_t(ll));
|
2005-01-16 06:15:51 +08:00
|
|
|
if (rdf_version == 1)
|
|
|
|
length -= 5;
|
|
|
|
if (rdf_version > 1 && reclen != 4)
|
|
|
|
printf(" warning: reclen != 4\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RDFREC_COMMON:{
|
2007-04-12 10:40:54 +08:00
|
|
|
uint16_t seg, align;
|
|
|
|
uint32_t size;
|
2005-01-16 06:15:51 +08:00
|
|
|
|
|
|
|
fread(&seg, 2, 1, infile);
|
|
|
|
fread(&size, 4, 1, infile);
|
|
|
|
fread(&align, 2, 1, infile);
|
|
|
|
for (ll = 0; ll < reclen - 8; ll++)
|
|
|
|
fread(buf + ll, 1, 1, infile);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf(" common: segment %04x = %s, %"PRId32":%d\n",
|
2007-04-12 10:40:54 +08:00
|
|
|
translateint16_t(seg), buf, translateint32_t(size),
|
|
|
|
translateint16_t(align));
|
2005-01-16 06:15:51 +08:00
|
|
|
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;
|
2002-05-01 04:51:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-13 00:54:50 +08:00
|
|
|
int main(int argc, char **argv)
|
2004-09-15 14:54:34 +08:00
|
|
|
{
|
2007-04-14 00:47:53 +08:00
|
|
|
char id[7];
|
2007-04-12 10:40:54 +08:00
|
|
|
int32_t l;
|
2007-04-13 00:54:50 +08:00
|
|
|
uint16_t s;
|
2004-09-15 14:54:34 +08:00
|
|
|
int verbose = 0;
|
2007-04-12 10:40:54 +08:00
|
|
|
int32_t offset;
|
2004-09-15 14:54:34 +08:00
|
|
|
int foundnullsegment = 0;
|
|
|
|
int version;
|
2007-04-12 10:40:54 +08:00
|
|
|
int32_t segmentcontentlength = 0;
|
2004-09-15 14:54:34 +08:00
|
|
|
int nsegments = 0;
|
2007-04-12 10:40:54 +08:00
|
|
|
int32_t headerlength = 0;
|
|
|
|
int32_t objectlength = 0;
|
2004-09-15 14:54:34 +08:00
|
|
|
|
|
|
|
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"
|
2005-01-16 06:15:51 +08:00
|
|
|
"Improvements and fixes (c) 2002-2004 RET & COM Research.");
|
2004-09-15 14:54:34 +08:00
|
|
|
|
|
|
|
if (argc < 2) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fputs("Usage: rdfdump [-v] <filename>\n", stderr);
|
|
|
|
exit(1);
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "-v")) {
|
2005-01-16 06:15:51 +08:00
|
|
|
verbose = 1;
|
|
|
|
if (argc < 3) {
|
|
|
|
fputs("required parameter missing\n", stderr);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
argv++;
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
infile = fopen(argv[1], "rb");
|
|
|
|
if (!infile) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fprintf(stderr, "rdfdump: Could not open %s\n", argv[1]);
|
|
|
|
exit(1);
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fread(id, 6, 1, infile);
|
|
|
|
if (strncmp(id, "RDOFF", 5)) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fputs("rdfdump: File does not contain valid RDOFF header\n",
|
|
|
|
stderr);
|
|
|
|
exit(1);
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
printf("File %s: RDOFF version %c\n\n", argv[1], id[5]);
|
|
|
|
if (id[5] < '1' || id[5] > '2') {
|
2005-01-16 06:15:51 +08:00
|
|
|
fprintf(stderr, "rdfdump: unknown RDOFF version '%c'\n", id[5]);
|
|
|
|
exit(1);
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
version = id[5] - '0';
|
|
|
|
|
|
|
|
if (version > 1) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fread(&l, 4, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
objectlength = translateint32_t(l);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("Object content size: %"PRId32" bytes\n", objectlength);
|
2004-09-15 14:54:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fread(&l, 4, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
headerlength = translateint32_t(l);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("Header (%"PRId32" bytes):\n", headerlength);
|
2004-09-15 14:54:34 +08:00
|
|
|
print_header(headerlength, version);
|
|
|
|
|
|
|
|
if (version == 1) {
|
2005-01-16 06:15:51 +08:00
|
|
|
fread(&l, 4, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
l = translateint32_t(l);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("\nText segment length = %"PRId32" bytes\n", l);
|
2005-01-16 06:15:51 +08:00
|
|
|
offset = 0;
|
|
|
|
while (l--) {
|
|
|
|
fread(id, 1, 1, infile);
|
|
|
|
if (verbose) {
|
|
|
|
if (offset % 16 == 0)
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("\n%08"PRIx32" ", offset);
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(" %02x", (int)(uint8_t)id[0]);
|
2005-01-16 06:15:51 +08:00
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (verbose)
|
|
|
|
printf("\n\n");
|
|
|
|
|
|
|
|
fread(&l, 4, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
l = translateint32_t(l);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("Data segment length = %"PRId32" bytes\n", l);
|
2005-01-16 06:15:51 +08:00
|
|
|
|
|
|
|
if (verbose) {
|
|
|
|
offset = 0;
|
|
|
|
while (l--) {
|
|
|
|
fread(id, 1, 1, infile);
|
|
|
|
if (offset % 16 == 0)
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("\n%08"PRIx32" ", offset);
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(" %02x", (int)(uint8_t)id[0]);
|
2005-01-16 06:15:51 +08:00
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
2004-09-15 14:54:34 +08:00
|
|
|
} else {
|
2005-01-16 06:15:51 +08:00
|
|
|
do {
|
|
|
|
fread(&s, 2, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
s = translateint16_t(s);
|
2005-01-16 06:15:51 +08:00
|
|
|
if (!s) {
|
|
|
|
printf("\nNULL segment\n");
|
|
|
|
foundnullsegment = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printf("\nSegment:\n Type = %04X (%s)\n", (int)s,
|
|
|
|
translatesegmenttype(s));
|
|
|
|
nsegments++;
|
|
|
|
|
|
|
|
fread(&s, 2, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(" Number = %04X\n", (int)translateint16_t(s));
|
2005-01-16 06:15:51 +08:00
|
|
|
fread(&s, 2, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(" Resrvd = %04X\n", (int)translateint16_t(s));
|
2005-01-16 06:15:51 +08:00
|
|
|
fread(&l, 4, 1, infile);
|
2007-04-12 10:40:54 +08:00
|
|
|
l = translateint32_t(l);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf(" Length = %"PRId32" bytes\n", l);
|
2005-01-16 06:15:51 +08:00
|
|
|
segmentcontentlength += l;
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
while (l--) {
|
|
|
|
fread(id, 1, 1, infile);
|
|
|
|
if (verbose) {
|
|
|
|
if (offset % 16 == 0)
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("\n%08"PRIx32" ", offset);
|
2007-04-12 10:40:54 +08:00
|
|
|
printf(" %02x", (int)(uint8_t)id[0]);
|
2005-01-16 06:15:51 +08:00
|
|
|
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);
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("Total segment content length: %"PRId32" bytes\n",
|
2005-01-16 06:15:51 +08:00
|
|
|
segmentcontentlength);
|
|
|
|
|
|
|
|
/* calculate what the total object content length should have been */
|
|
|
|
l = segmentcontentlength + 10 * (nsegments + 1) + headerlength + 4;
|
|
|
|
if (l != objectlength)
|
2007-04-14 09:24:14 +08:00
|
|
|
printf("Warning: actual object length (%"PRId32") != "
|
|
|
|
"stored object length (%"PRId32")\n", l, objectlength);
|
2002-05-01 04:51:32 +08:00
|
|
|
}
|
2004-09-15 14:54:34 +08:00
|
|
|
fclose(infile);
|
|
|
|
return 0;
|
2002-05-01 04:51:32 +08:00
|
|
|
}
|