Add support for one-byte relocations
[nasm/nasm.git] / misc / omfdump.c
blob322971e9f3aee0ebeb5fabaa03f0dbfb4f73dac2
1 /*
2 * omfdump.c
4 * Very simple program to dump the contents of an OMF (OBJ) file
6 * This assumes a littleendian, unaligned-load-capable host and a
7 * C compiler which handles basic C99.
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <inttypes.h>
13 #include <ctype.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #include <sys/stat.h>
19 const char *progname;
21 static const char *record_types[256] =
23 [0x80] = "THEADR",
24 [0x82] = "LHEADR",
25 [0x88] = "COMENT",
26 [0x8a] = "MODEND16",
27 [0x8b] = "MODEND32",
28 [0x8c] = "EXTDEF",
29 [0x90] = "PUBDEF16",
30 [0x91] = "PUBDEF32",
31 [0x94] = "LINNUM16",
32 [0x95] = "LINNUM32",
33 [0x96] = "LNAMES",
34 [0x98] = "SEGDEF16",
35 [0x99] = "SEGDEF32",
36 [0x9a] = "GRPDEF",
37 [0x9c] = "FIXUPP16",
38 [0x9d] = "FIXUPP32",
39 [0xa0] = "LEDATA16",
40 [0xa1] = "LEDATA32",
41 [0xa2] = "LIDATA16",
42 [0xa3] = "LIDATA32",
43 [0xb0] = "COMDEF",
44 [0xb2] = "BAKPAT16",
45 [0xb3] = "BAKPAT32",
46 [0xb4] = "LEXTDEF",
47 [0xb6] = "LPUBDEF16",
48 [0xb7] = "LPUBDEF32",
49 [0xb8] = "LCOMDEF",
50 [0xbc] = "CEXTDEF",
51 [0xc2] = "COMDAT16",
52 [0xc3] = "COMDAT32",
53 [0xc4] = "LINSYM16",
54 [0xc5] = "LINSYM32",
55 [0xc6] = "ALIAS",
56 [0xc8] = "NBKPAT16",
57 [0xc9] = "NBKPAT32",
58 [0xca] = "LLNAMES",
59 [0xcc] = "VERNUM",
60 [0xce] = "VENDEXT",
61 [0xf0] = "LIBHDR",
62 [0xf1] = "LIBEND",
65 typedef void (*dump_func)(uint8_t, const uint8_t *, size_t);
67 static void hexdump_data(unsigned int offset, const uint8_t *data, size_t n)
69 unsigned int i, j;
71 for (i = 0; i < n; i += 16) {
72 printf(" %04x: ", i+offset);
73 for (j = 0; j < 16; j++) {
74 if (i+j < n)
75 printf("%02x%c", data[i+j], (j == 7) ? '-' : ' ');
76 else
77 printf(" ");
79 printf(" : ");
80 for (j = 0; j < 16; j++) {
81 if (i+j < n)
82 putchar(isprint(data[i+j]) ? data[i+j] : '.');
84 putchar('\n');
88 static void dump_unknown(uint8_t type, const uint8_t *data, size_t n)
90 (void)type;
91 hexdump_data(0, data, n);
94 static void dump_coment(uint8_t type, const uint8_t *data, size_t n)
96 uint8_t class;
97 static const char *coment_class[256] = {
98 [0x00] = "Translator",
99 [0x01] = "Copyright",
100 [0x81] = "Library specifier",
101 [0x9c] = "MS-DOS version",
102 [0x9d] = "Memory model",
103 [0x9e] = "DOSSEG",
104 [0x9f] = "Library search",
105 [0xa0] = "OMF extensions",
106 [0xa1] = "New OMF extension",
107 [0xa2] = "Link pass separator",
108 [0xa3] = "LIBMOD",
109 [0xa4] = "EXESTR",
110 [0xa6] = "INCERR",
111 [0xa7] = "NOPAD",
112 [0xa8] = "WKEXT",
113 [0xa9] = "LZEXT",
114 [0xda] = "Comment",
115 [0xdb] = "Compiler",
116 [0xdc] = "Date",
117 [0xdd] = "Timestamp",
118 [0xdf] = "User",
119 [0xe9] = "Dependency file",
120 [0xff] = "Command line"
123 if (n < 2) {
124 dump_unknown(type, data, n);
125 return;
128 type = data[0];
129 class = data[1];
131 printf(" [NP=%d NL=%d UD=%02X] %02X %s\n",
132 (type >> 7) & 1,
133 (type >> 6) & 1,
134 type & 0x3f,
135 class,
136 coment_class[class] ? coment_class[class] : "???");
138 hexdump_data(2, data+2, n-2);
141 static const dump_func dump_type[256] =
143 [0x88] = dump_coment,
146 int dump_omf(int fd)
148 struct stat st;
149 size_t len, n;
150 uint8_t type;
151 const uint8_t *p, *data;
153 if (fstat(fd, &st))
154 return -1;
156 len = st.st_size;
158 data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
159 if (data == MAP_FAILED)
160 return -1;
162 p = data;
163 while (len >= 3) {
164 uint8_t csum;
165 int i;
167 type = p[0];
168 n = *(uint16_t *)(p+1);
170 printf("%02x %-10s %4zd bytes",
171 type,
172 record_types[type] ? record_types[type] : "???",
175 if (len < n+3) {
176 printf("\n (truncated, only %zd bytes left)\n", len-3);
177 break; /* Truncated */
180 p += 3; /* Header doesn't count in the length */
181 n--; /* Remove checksum byte */
183 csum = 0;
184 for (i = -3; i < (int)n; i++)
185 csum -= p[i];
187 printf(", checksum %02X", p[i]);
188 if (csum == p[i])
189 printf(" (valid)\n");
190 else
191 printf(" (actual = %02X)\n", csum);
193 if (dump_type[type])
194 dump_type[type](type, p, n);
195 else
196 dump_unknown(type, p, n);
198 p += n+1;
199 len -= (n+4);
202 munmap((void *)data, st.st_size);
203 return 0;
206 int main(int argc, char *argv[])
208 int fd;
209 int i;
211 progname = argv[0];
213 for (i = 1; i < argc; i++) {
214 fd = open(argv[i], O_RDONLY);
215 if (fd < 0 || dump_omf(fd)) {
216 perror(argv[i]);
217 return 1;
219 close(fd);
222 return 0;