Commit | Line | Data |
---|---|---|
06297a93 MW |
1 | #include <ctype.h> |
2 | #include <errno.h> | |
3 | #include <limits.h> | |
4 | #include <stdarg.h> | |
5 | #include <stdio.h> | |
6 | #include <stdlib.h> | |
7 | #include <string.h> | |
8 | ||
9 | union reg { | |
10 | unsigned char *p; | |
11 | long i; | |
12 | long u; | |
13 | }; | |
14 | ||
15 | struct regs { | |
16 | union reg | |
17 | a, b, c, d, si, di, bp, f, | |
18 | r8, r9, r10, r11, r12, r13, r14, r15; | |
19 | }; | |
20 | ||
21 | struct seg { | |
22 | unsigned char *p; | |
23 | size_t sz; | |
24 | }; | |
25 | ||
26 | #define N(v) (sizeof(v)/sizeof((v)[0])) | |
27 | ||
28 | #define CTYPE_HACK(func, ch) func((unsigned char)(ch)) | |
29 | #define ISDIGIT(ch) CTYPE_HACK(isdigit, ch) | |
30 | #define ISSPACE(ch) CTYPE_HACK(isspace, ch) | |
31 | ||
32 | #define XCHG(_) \ | |
33 | _(x00) _(x01) _(x02) _(x03) _(x04) _(x05) _(x06) _(x07) \ | |
34 | _(x08) _(x09) _(x0a) _(x0b) _(x0c) _(x0d) _(x0e) _(x0f) \ | |
35 | _(x10) _(x11) _(x12) _(x13) _(x14) _(x15) _(x16) _(x17) \ | |
36 | _(x18) _(x19) _(x1a) _(x1b) _(x1c) _(x1d) _(x1e) _(x1f) \ | |
37 | _(x20) _(x21) _(x22) _(x23) _(x24) _(x25) _(x26) _(x27) \ | |
38 | _(x28) _(x29) _(x2a) _(x2b) _(x2c) _(x2d) _(x2e) _(x2f) \ | |
39 | _(x30) _(x31) _(x32) _(x33) _(x34) _(x35) _(x36) _(x37) \ | |
40 | _(x38) _(x39) _(x3a) _(x3b) _(x3c) _(x3d) _(x3e) _(x3f) | |
41 | ||
42 | #define DECL(x) extern const int x; | |
43 | XCHG(DECL) | |
44 | extern const int nop; | |
45 | ||
46 | static const int *x[] = { | |
47 | #define SLOT(x) &x, | |
48 | XCHG(SLOT) | |
49 | }; | |
50 | ||
51 | extern void call_example(const int *f, struct regs *r); | |
52 | ||
53 | static const char *prog = "???"; | |
54 | ||
55 | __attribute__((format(printf, 1, 2), noreturn)) | |
56 | static void barf(const char *m, ...) | |
57 | { | |
58 | va_list ap; | |
59 | ||
60 | va_start(ap, m); | |
61 | fprintf(stderr, "%s: ", prog); | |
62 | vfprintf(stderr, m, ap); | |
63 | putc('\n', stderr); | |
64 | va_end(ap); | |
65 | exit(127); | |
66 | } | |
67 | ||
68 | static void *xmalloc(size_t sz) | |
69 | { | |
70 | void *p; | |
71 | ||
72 | if (!sz) return (0); | |
73 | p = malloc(sz); | |
74 | if (!p) barf("malloc failed"); | |
75 | return (p); | |
76 | } | |
77 | ||
78 | #define DEF_PARSEINT(name, ty, strto) \ | |
79 | static ty parse_##name(const char *what, const char *p, ty min, ty max) \ | |
80 | { \ | |
81 | const char *pp = p; \ | |
82 | char *q; \ | |
83 | ty i; \ | |
84 | int err; \ | |
85 | \ | |
86 | if (ISSPACE(*p)) goto bad; \ | |
87 | err = errno; errno = 0; \ | |
88 | i = strto(p, &q, 0); \ | |
89 | if (errno) goto bad; \ | |
90 | if (*q) goto bad; \ | |
91 | if (i < min || i > max) goto bad; \ | |
92 | errno = err; \ | |
93 | return (i); \ | |
94 | \ | |
95 | bad: \ | |
96 | barf("bad %s `%s'", what, pp); \ | |
97 | } | |
98 | DEF_PARSEINT(long, long, strtol) | |
99 | DEF_PARSEINT(ulong, unsigned long, strtoul) | |
100 | ||
101 | static int hex_digit(char ch) | |
102 | { | |
103 | if ('0' <= ch && ch <= '9') return (ch - '0'); | |
104 | else if ('A' <= ch && ch <= 'F') return (ch - 'A' + 10); | |
105 | else if ('a' <= ch && ch <= 'f') return (ch - 'a' + 10); | |
106 | else return (-1); | |
107 | } | |
108 | ||
109 | static void setreg(union reg *r, | |
110 | struct seg **seg_inout, | |
111 | int *i_inout, int argc, char *argv[]) | |
112 | { | |
113 | struct seg *seg; | |
114 | const char *p, *pp; | |
115 | unsigned char *q; | |
116 | int hi, lo; | |
117 | size_t n; | |
118 | ||
119 | #define LONG_REG(p) (parse_long("signed register", (p), LONG_MIN, LONG_MAX)) | |
120 | #define ULONG_REG(p) (parse_ulong("unsigned register", (p), 0, ULONG_MAX)) | |
121 | ||
122 | p = *i_inout >= argc ? "-" : argv[(*i_inout)++]; | |
123 | switch (*p) { | |
124 | case '-': | |
125 | if (p[1]) r->i = LONG_REG(p); | |
126 | else r->u = 0xdeadbeefdeadbeef; | |
127 | break; | |
128 | case 'i': | |
129 | if (p[1] != ':') goto bad; | |
130 | r->i = LONG_REG(p + 2); | |
131 | break; | |
132 | case 'u': | |
133 | if (p[1] != ':') goto bad; | |
134 | r->u = ULONG_REG(p + 2); | |
135 | break; | |
136 | case 'c': | |
137 | if (p[1] != ':' || p[3]) goto bad; | |
138 | r->u = p[2]; | |
139 | break; | |
140 | case 's': | |
141 | if (p[1] != ':') goto bad; | |
142 | pp = p + 2; n = strlen(pp) + 1; | |
143 | seg = (*seg_inout)++; seg->p = xmalloc(n); seg->sz = n; | |
144 | memcpy(seg->p, pp, n); r->p = seg->p; | |
145 | break; | |
146 | case 'm': | |
147 | if (p[1] != ':') goto bad; | |
148 | pp = p + 2; n = strlen(pp); if (n%2) goto bad; | |
149 | seg = (*seg_inout)++; seg->p = q = xmalloc(n/2); seg->sz = n/2; | |
150 | while (n) { | |
151 | hi = hex_digit(pp[0]); lo = hex_digit(pp[1]); | |
152 | if (hi < 0 || lo < 0) goto bad; | |
153 | *q++ = 16*hi + lo; n -= 2; pp += 2; | |
154 | } | |
155 | r->p = seg->p; | |
156 | break; | |
157 | default: | |
158 | if (ISDIGIT(*p)) r->u = ULONG_REG(p); | |
159 | else if (*p == '+') r->i = LONG_REG(p); | |
160 | else if (*p == '\'' && p[2] == '\'' && !p[3]) r->u = p[1]; | |
161 | else goto bad; | |
162 | break; | |
163 | bad: | |
164 | barf("bad regspec `%s'", p); | |
165 | } | |
166 | ||
167 | #undef LONG_REG | |
168 | #undef ULONG_REG | |
169 | } | |
170 | ||
171 | static void dumpreg(const char *name, const union reg *r, | |
172 | const struct seg *seg, size_t nseg) | |
173 | { | |
174 | size_t i; | |
175 | ||
176 | printf("%3s = 0x%016lx = %20ld = %20lu", name, r->u, r->i, r->u); | |
177 | if (r->u >= ' ' && r->u <= '~') printf(" = '%c'", (int)r->u); | |
178 | for (i = 0; i < nseg; i++) { | |
179 | if (r->p == seg[i].p) | |
180 | printf(" = seg[%zu] base", i); | |
181 | else if (r->p == seg[i].p + seg[i].sz) | |
182 | printf(" = seg[%zu] limit", i); | |
183 | else if (seg[i].p < r->p && r->p < seg[i].p + seg[i].sz) | |
184 | printf(" = seg[%zu] + %zu", i, (size_t)(r->p - seg[i].p)); | |
185 | } | |
186 | putchar('\n'); | |
187 | } | |
188 | ||
189 | static void dumpseg(const struct seg *seg) | |
190 | { | |
191 | size_t i, j; | |
192 | unsigned char ch; | |
193 | ||
194 | for (i = 0; i < seg->sz; i += 8) { | |
195 | printf("\t%8zx :", i); | |
196 | for (j = 0; j < 8; j++) | |
197 | if (i + j >= seg->sz) printf(" **"); | |
198 | else printf(" %02x", seg->p[i + j]); | |
199 | printf(" : "); | |
200 | for (j = 0; j < 8; j++) | |
201 | if (i + j >= seg->sz) putchar('*'); | |
202 | else { | |
203 | ch = seg->p[i + j]; | |
204 | if (' ' <= ch && ch <= '~') putchar(ch); | |
205 | else putchar('.'); | |
206 | } | |
207 | putchar('\n'); | |
208 | } | |
209 | } | |
210 | ||
211 | int main(int argc, char *argv[]) | |
212 | { | |
213 | struct regs r; | |
214 | struct seg seg[16], *segp = seg; | |
215 | size_t nseg; | |
216 | int i, j; | |
217 | ||
218 | prog = strrchr(argv[0], '/'); if (prog) prog++; else prog = argv[0]; | |
219 | ||
220 | if (argc < 2) | |
221 | barf("usage: %s I [A B C D SI DI BP R8 R9 R10 R11 R12 R13 R14 R15 F]", | |
222 | prog); | |
223 | ||
224 | j = parse_long("program index", argv[1], -1, N(x) - 1); | |
225 | ||
226 | i = 2; | |
227 | setreg(&r.a, &segp, &i, argc, argv); | |
228 | setreg(&r.b, &segp, &i, argc, argv); | |
229 | setreg(&r.c, &segp, &i, argc, argv); | |
230 | setreg(&r.d, &segp, &i, argc, argv); | |
231 | setreg(&r.si, &segp, &i, argc, argv); | |
232 | setreg(&r.di, &segp, &i, argc, argv); | |
233 | setreg(&r.bp, &segp, &i, argc, argv); | |
234 | setreg(&r.r8, &segp, &i, argc, argv); | |
235 | setreg(&r.r9, &segp, &i, argc, argv); | |
236 | setreg(&r.r10, &segp, &i, argc, argv); | |
237 | setreg(&r.r11, &segp, &i, argc, argv); | |
238 | setreg(&r.r12, &segp, &i, argc, argv); | |
239 | setreg(&r.r13, &segp, &i, argc, argv); | |
240 | setreg(&r.r14, &segp, &i, argc, argv); | |
241 | setreg(&r.r15, &segp, &i, argc, argv); | |
242 | setreg(&r.f, &segp, &i, argc, argv); | |
243 | nseg = segp - seg; | |
244 | ||
245 | call_example(j < 0 ? &nop : x[j], &r); | |
246 | ||
247 | dumpreg("rax", &r.a, seg, nseg); | |
248 | dumpreg("rbx", &r.b, seg, nseg); | |
249 | dumpreg("rcx", &r.c, seg, nseg); | |
250 | dumpreg("rdx", &r.d, seg, nseg); | |
251 | dumpreg("rsi", &r.si, seg, nseg); | |
252 | dumpreg("rdi", &r.di, seg, nseg); | |
253 | dumpreg("rbp", &r.bp, seg, nseg); | |
254 | dumpreg("rbp", &r.bp, seg, nseg); | |
255 | dumpreg("r8", &r.r8, seg, nseg); | |
256 | dumpreg("r9", &r.r9, seg, nseg); | |
257 | dumpreg("r10", &r.r10, seg, nseg); | |
258 | dumpreg("r11", &r.r11, seg, nseg); | |
259 | dumpreg("r12", &r.r12, seg, nseg); | |
260 | dumpreg("r13", &r.r13, seg, nseg); | |
261 | dumpreg("r14", &r.r14, seg, nseg); | |
262 | dumpreg("r15", &r.r15, seg, nseg); | |
263 | ||
264 | #define CF (1 << 0) | |
265 | #define PF (1 << 2) | |
266 | #define ZF (1 << 6) | |
267 | #define SF (1 << 7) | |
268 | #define OF (1 << 11) | |
269 | ||
270 | dumpreg("f", &r.f, seg, nseg); | |
271 | printf("\tstatus: %ccf %cpf %caf %czf %csf %cdf %cof\n", | |
272 | (r.f.u >> 0)&1u ? '+' : '-', | |
273 | (r.f.u >> 2)&1u ? '+' : '-', | |
274 | (r.f.u >> 4)&1u ? '+' : '-', | |
275 | (r.f.u >> 6)&1u ? '+' : '-', | |
276 | (r.f.u >> 7)&1u ? '+' : '-', | |
277 | (r.f.u >> 10)&1u ? '+' : '-', | |
278 | (r.f.u >> 11)&1u ? '+' : '-'); | |
279 | printf("\tcond:"); | |
280 | if (r.f.u&CF) printf(" c/b/nae"); else printf(" nc/ae/nb"); | |
281 | if (r.f.u&ZF) printf(" e/z"); else printf(" ne/nz"); | |
282 | if (r.f.u&SF) printf(" s"); else printf(" ns"); | |
283 | if (r.f.u&OF) printf(" o"); else printf(" no"); | |
284 | if (r.f.u&PF) printf(" p"); else printf(" np"); | |
285 | if ((r.f.u&CF) || (r.f.u&ZF)) printf(" be/na"); else printf(" a/nbe"); | |
286 | if (!(r.f.u&OF) == !(r.f.u&SF)) printf(" ge/nl"); else printf(" l/nge"); | |
287 | if (!(r.f.u&OF) == !(r.f.u&SF) && !(r.f.u&ZF)) | |
288 | printf(" g/nle"); else printf(" le/ng"); | |
289 | putchar('\n'); | |
290 | printf("\tsystem: %ctf %cif iopl=%d %cnt " | |
291 | "%crf %cvm %cac %cvif %cvip %cid\n", | |
292 | (r.f.u >> 8)&1u ? '+' : '-', | |
293 | (r.f.u >> 9)&1u ? '+' : '-', | |
294 | (int)((r.f.u >> 12)&1u), | |
295 | (r.f.u >> 14)&1u ? '+' : '-', | |
296 | (r.f.u >> 16)&1u ? '+' : '-', | |
297 | (r.f.u >> 17)&1u ? '+' : '-', | |
298 | (r.f.u >> 18)&1u ? '+' : '-', | |
299 | (r.f.u >> 19)&1u ? '+' : '-', | |
300 | (r.f.u >> 20)&1u ? '+' : '-', | |
301 | (r.f.u >> 21)&1u ? '+' : '-'); | |
302 | ||
303 | #undef CF | |
304 | #undef PF | |
305 | #undef ZF | |
306 | #undef SF | |
307 | #undef OF | |
308 | ||
309 | for (i = 0; i < nseg; i++) | |
310 | { printf("seg[%d] (%p):\n", i, seg[i].p); dumpseg(&seg[i]); } | |
311 | ||
312 | return (0); | |
313 | } |