1*7304104dSAndroid Build Coastguard Worker /* Disassembler for x86.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2007.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker
34*7304104dSAndroid Build Coastguard Worker #include <assert.h>
35*7304104dSAndroid Build Coastguard Worker #include <config.h>
36*7304104dSAndroid Build Coastguard Worker #include <ctype.h>
37*7304104dSAndroid Build Coastguard Worker #include <errno.h>
38*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
39*7304104dSAndroid Build Coastguard Worker #include <stddef.h>
40*7304104dSAndroid Build Coastguard Worker #include <stdint.h>
41*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
42*7304104dSAndroid Build Coastguard Worker #include <string.h>
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker #include "libeblP.h"
45*7304104dSAndroid Build Coastguard Worker
46*7304104dSAndroid Build Coastguard Worker #define MACHINE_ENCODING LITTLE_ENDIAN
47*7304104dSAndroid Build Coastguard Worker #include "memory-access.h"
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker #include "i386_mne.h"
50*7304104dSAndroid Build Coastguard Worker
51*7304104dSAndroid Build Coastguard Worker #define MNESTRFIELD(line) MNESTRFIELD1 (line)
52*7304104dSAndroid Build Coastguard Worker #define MNESTRFIELD1(line) str##line
53*7304104dSAndroid Build Coastguard Worker static const union mnestr_t
54*7304104dSAndroid Build Coastguard Worker {
55*7304104dSAndroid Build Coastguard Worker struct
56*7304104dSAndroid Build Coastguard Worker {
57*7304104dSAndroid Build Coastguard Worker #define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
58*7304104dSAndroid Build Coastguard Worker #include MNEFILE
59*7304104dSAndroid Build Coastguard Worker #undef MNE
60*7304104dSAndroid Build Coastguard Worker };
61*7304104dSAndroid Build Coastguard Worker char str[0];
62*7304104dSAndroid Build Coastguard Worker } mnestr =
63*7304104dSAndroid Build Coastguard Worker {
64*7304104dSAndroid Build Coastguard Worker {
65*7304104dSAndroid Build Coastguard Worker #define MNE(name) #name,
66*7304104dSAndroid Build Coastguard Worker #include MNEFILE
67*7304104dSAndroid Build Coastguard Worker #undef MNE
68*7304104dSAndroid Build Coastguard Worker }
69*7304104dSAndroid Build Coastguard Worker };
70*7304104dSAndroid Build Coastguard Worker
71*7304104dSAndroid Build Coastguard Worker static const unsigned short int mneidx[] =
72*7304104dSAndroid Build Coastguard Worker {
73*7304104dSAndroid Build Coastguard Worker #define MNE(name) \
74*7304104dSAndroid Build Coastguard Worker [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
75*7304104dSAndroid Build Coastguard Worker #include MNEFILE
76*7304104dSAndroid Build Coastguard Worker #undef MNE
77*7304104dSAndroid Build Coastguard Worker };
78*7304104dSAndroid Build Coastguard Worker
79*7304104dSAndroid Build Coastguard Worker
80*7304104dSAndroid Build Coastguard Worker enum
81*7304104dSAndroid Build Coastguard Worker {
82*7304104dSAndroid Build Coastguard Worker idx_rex_b = 0,
83*7304104dSAndroid Build Coastguard Worker idx_rex_x,
84*7304104dSAndroid Build Coastguard Worker idx_rex_r,
85*7304104dSAndroid Build Coastguard Worker idx_rex_w,
86*7304104dSAndroid Build Coastguard Worker idx_rex,
87*7304104dSAndroid Build Coastguard Worker idx_cs,
88*7304104dSAndroid Build Coastguard Worker idx_ds,
89*7304104dSAndroid Build Coastguard Worker idx_es,
90*7304104dSAndroid Build Coastguard Worker idx_fs,
91*7304104dSAndroid Build Coastguard Worker idx_gs,
92*7304104dSAndroid Build Coastguard Worker idx_ss,
93*7304104dSAndroid Build Coastguard Worker idx_data16,
94*7304104dSAndroid Build Coastguard Worker idx_addr16,
95*7304104dSAndroid Build Coastguard Worker idx_rep,
96*7304104dSAndroid Build Coastguard Worker idx_repne,
97*7304104dSAndroid Build Coastguard Worker idx_lock
98*7304104dSAndroid Build Coastguard Worker };
99*7304104dSAndroid Build Coastguard Worker
100*7304104dSAndroid Build Coastguard Worker enum
101*7304104dSAndroid Build Coastguard Worker {
102*7304104dSAndroid Build Coastguard Worker #define prefbit(pref) has_##pref = 1 << idx_##pref
103*7304104dSAndroid Build Coastguard Worker prefbit (rex_b),
104*7304104dSAndroid Build Coastguard Worker prefbit (rex_x),
105*7304104dSAndroid Build Coastguard Worker prefbit (rex_r),
106*7304104dSAndroid Build Coastguard Worker prefbit (rex_w),
107*7304104dSAndroid Build Coastguard Worker prefbit (rex),
108*7304104dSAndroid Build Coastguard Worker prefbit (cs),
109*7304104dSAndroid Build Coastguard Worker prefbit (ds),
110*7304104dSAndroid Build Coastguard Worker prefbit (es),
111*7304104dSAndroid Build Coastguard Worker prefbit (fs),
112*7304104dSAndroid Build Coastguard Worker prefbit (gs),
113*7304104dSAndroid Build Coastguard Worker prefbit (ss),
114*7304104dSAndroid Build Coastguard Worker prefbit (data16),
115*7304104dSAndroid Build Coastguard Worker prefbit (addr16),
116*7304104dSAndroid Build Coastguard Worker prefbit (rep),
117*7304104dSAndroid Build Coastguard Worker prefbit (repne),
118*7304104dSAndroid Build Coastguard Worker prefbit (lock)
119*7304104dSAndroid Build Coastguard Worker #undef prefbit
120*7304104dSAndroid Build Coastguard Worker };
121*7304104dSAndroid Build Coastguard Worker #define SEGMENT_PREFIXES \
122*7304104dSAndroid Build Coastguard Worker (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
123*7304104dSAndroid Build Coastguard Worker
124*7304104dSAndroid Build Coastguard Worker #define prefix_cs 0x2e
125*7304104dSAndroid Build Coastguard Worker #define prefix_ds 0x3e
126*7304104dSAndroid Build Coastguard Worker #define prefix_es 0x26
127*7304104dSAndroid Build Coastguard Worker #define prefix_fs 0x64
128*7304104dSAndroid Build Coastguard Worker #define prefix_gs 0x65
129*7304104dSAndroid Build Coastguard Worker #define prefix_ss 0x36
130*7304104dSAndroid Build Coastguard Worker #define prefix_data16 0x66
131*7304104dSAndroid Build Coastguard Worker #define prefix_addr16 0x67
132*7304104dSAndroid Build Coastguard Worker #define prefix_rep 0xf3
133*7304104dSAndroid Build Coastguard Worker #define prefix_repne 0xf2
134*7304104dSAndroid Build Coastguard Worker #define prefix_lock 0xf0
135*7304104dSAndroid Build Coastguard Worker
136*7304104dSAndroid Build Coastguard Worker
137*7304104dSAndroid Build Coastguard Worker static const uint8_t known_prefixes[] =
138*7304104dSAndroid Build Coastguard Worker {
139*7304104dSAndroid Build Coastguard Worker #define newpref(pref) [idx_##pref] = prefix_##pref
140*7304104dSAndroid Build Coastguard Worker newpref (cs),
141*7304104dSAndroid Build Coastguard Worker newpref (ds),
142*7304104dSAndroid Build Coastguard Worker newpref (es),
143*7304104dSAndroid Build Coastguard Worker newpref (fs),
144*7304104dSAndroid Build Coastguard Worker newpref (gs),
145*7304104dSAndroid Build Coastguard Worker newpref (ss),
146*7304104dSAndroid Build Coastguard Worker newpref (data16),
147*7304104dSAndroid Build Coastguard Worker newpref (addr16),
148*7304104dSAndroid Build Coastguard Worker newpref (rep),
149*7304104dSAndroid Build Coastguard Worker newpref (repne),
150*7304104dSAndroid Build Coastguard Worker newpref (lock)
151*7304104dSAndroid Build Coastguard Worker #undef newpref
152*7304104dSAndroid Build Coastguard Worker };
153*7304104dSAndroid Build Coastguard Worker #define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
154*7304104dSAndroid Build Coastguard Worker
155*7304104dSAndroid Build Coastguard Worker
156*7304104dSAndroid Build Coastguard Worker #if 0
157*7304104dSAndroid Build Coastguard Worker static const char *prefix_str[] =
158*7304104dSAndroid Build Coastguard Worker {
159*7304104dSAndroid Build Coastguard Worker #define newpref(pref) [idx_##pref] = #pref
160*7304104dSAndroid Build Coastguard Worker newpref (cs),
161*7304104dSAndroid Build Coastguard Worker newpref (ds),
162*7304104dSAndroid Build Coastguard Worker newpref (es),
163*7304104dSAndroid Build Coastguard Worker newpref (fs),
164*7304104dSAndroid Build Coastguard Worker newpref (gs),
165*7304104dSAndroid Build Coastguard Worker newpref (ss),
166*7304104dSAndroid Build Coastguard Worker newpref (data16),
167*7304104dSAndroid Build Coastguard Worker newpref (addr16),
168*7304104dSAndroid Build Coastguard Worker newpref (rep),
169*7304104dSAndroid Build Coastguard Worker newpref (repne),
170*7304104dSAndroid Build Coastguard Worker newpref (lock)
171*7304104dSAndroid Build Coastguard Worker #undef newpref
172*7304104dSAndroid Build Coastguard Worker };
173*7304104dSAndroid Build Coastguard Worker #endif
174*7304104dSAndroid Build Coastguard Worker
175*7304104dSAndroid Build Coastguard Worker
176*7304104dSAndroid Build Coastguard Worker static const char amd3dnowstr[] =
177*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PAVGUSB 1
178*7304104dSAndroid Build Coastguard Worker "pavgusb\0"
179*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
180*7304104dSAndroid Build Coastguard Worker "pfadd\0"
181*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
182*7304104dSAndroid Build Coastguard Worker "pfsub\0"
183*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
184*7304104dSAndroid Build Coastguard Worker "pfsubr\0"
185*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
186*7304104dSAndroid Build Coastguard Worker "pfacc\0"
187*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
188*7304104dSAndroid Build Coastguard Worker "pfcmpge\0"
189*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
190*7304104dSAndroid Build Coastguard Worker "pfcmpgt\0"
191*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
192*7304104dSAndroid Build Coastguard Worker "pfcmpeq\0"
193*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
194*7304104dSAndroid Build Coastguard Worker "pfmin\0"
195*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
196*7304104dSAndroid Build Coastguard Worker "pfmax\0"
197*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
198*7304104dSAndroid Build Coastguard Worker "pi2fd\0"
199*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
200*7304104dSAndroid Build Coastguard Worker "pf2id\0"
201*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
202*7304104dSAndroid Build Coastguard Worker "pfrcp\0"
203*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
204*7304104dSAndroid Build Coastguard Worker "pfrsqrt\0"
205*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
206*7304104dSAndroid Build Coastguard Worker "pfmul\0"
207*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
208*7304104dSAndroid Build Coastguard Worker "pfrcpit1\0"
209*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
210*7304104dSAndroid Build Coastguard Worker "pfrsqit1\0"
211*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
212*7304104dSAndroid Build Coastguard Worker "pfrcpit2\0"
213*7304104dSAndroid Build Coastguard Worker #define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
214*7304104dSAndroid Build Coastguard Worker "pmulhrw";
215*7304104dSAndroid Build Coastguard Worker
216*7304104dSAndroid Build Coastguard Worker #define AMD3DNOW_LOW_IDX 0x0d
217*7304104dSAndroid Build Coastguard Worker #define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1)
218*7304104dSAndroid Build Coastguard Worker #define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX)
219*7304104dSAndroid Build Coastguard Worker static const unsigned char amd3dnow[] =
220*7304104dSAndroid Build Coastguard Worker {
221*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB,
222*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD,
223*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB,
224*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR,
225*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC,
226*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE,
227*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT,
228*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ,
229*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN,
230*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX,
231*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD,
232*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID,
233*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP,
234*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT,
235*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL,
236*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1,
237*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1,
238*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2,
239*7304104dSAndroid Build Coastguard Worker [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW
240*7304104dSAndroid Build Coastguard Worker };
241*7304104dSAndroid Build Coastguard Worker
242*7304104dSAndroid Build Coastguard Worker
243*7304104dSAndroid Build Coastguard Worker struct output_data
244*7304104dSAndroid Build Coastguard Worker {
245*7304104dSAndroid Build Coastguard Worker GElf_Addr addr;
246*7304104dSAndroid Build Coastguard Worker int *prefixes;
247*7304104dSAndroid Build Coastguard Worker size_t opoff1;
248*7304104dSAndroid Build Coastguard Worker size_t opoff2;
249*7304104dSAndroid Build Coastguard Worker size_t opoff3;
250*7304104dSAndroid Build Coastguard Worker char *bufp;
251*7304104dSAndroid Build Coastguard Worker size_t *bufcntp;
252*7304104dSAndroid Build Coastguard Worker size_t bufsize;
253*7304104dSAndroid Build Coastguard Worker const uint8_t *data;
254*7304104dSAndroid Build Coastguard Worker const uint8_t **param_start;
255*7304104dSAndroid Build Coastguard Worker const uint8_t *end;
256*7304104dSAndroid Build Coastguard Worker char *labelbuf;
257*7304104dSAndroid Build Coastguard Worker size_t labelbufsize;
258*7304104dSAndroid Build Coastguard Worker enum
259*7304104dSAndroid Build Coastguard Worker {
260*7304104dSAndroid Build Coastguard Worker addr_none = 0,
261*7304104dSAndroid Build Coastguard Worker addr_abs_symbolic,
262*7304104dSAndroid Build Coastguard Worker addr_abs_always,
263*7304104dSAndroid Build Coastguard Worker addr_rel_symbolic,
264*7304104dSAndroid Build Coastguard Worker addr_rel_always
265*7304104dSAndroid Build Coastguard Worker } symaddr_use;
266*7304104dSAndroid Build Coastguard Worker GElf_Addr symaddr;
267*7304104dSAndroid Build Coastguard Worker };
268*7304104dSAndroid Build Coastguard Worker
269*7304104dSAndroid Build Coastguard Worker
270*7304104dSAndroid Build Coastguard Worker #ifndef DISFILE
271*7304104dSAndroid Build Coastguard Worker # define DISFILE "i386_dis.h"
272*7304104dSAndroid Build Coastguard Worker #endif
273*7304104dSAndroid Build Coastguard Worker #include DISFILE
274*7304104dSAndroid Build Coastguard Worker
275*7304104dSAndroid Build Coastguard Worker
276*7304104dSAndroid Build Coastguard Worker #define ADD_CHAR(ch) \
277*7304104dSAndroid Build Coastguard Worker do { \
278*7304104dSAndroid Build Coastguard Worker if (unlikely (bufcnt == bufsize)) \
279*7304104dSAndroid Build Coastguard Worker goto enomem; \
280*7304104dSAndroid Build Coastguard Worker buf[bufcnt++] = (ch); \
281*7304104dSAndroid Build Coastguard Worker } while (0)
282*7304104dSAndroid Build Coastguard Worker
283*7304104dSAndroid Build Coastguard Worker #define ADD_STRING(str) \
284*7304104dSAndroid Build Coastguard Worker do { \
285*7304104dSAndroid Build Coastguard Worker const char *_str0 = (str); \
286*7304104dSAndroid Build Coastguard Worker size_t _len0 = strlen (_str0); \
287*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (_str0, _len0); \
288*7304104dSAndroid Build Coastguard Worker } while (0)
289*7304104dSAndroid Build Coastguard Worker
290*7304104dSAndroid Build Coastguard Worker #define ADD_NSTRING(str, len) \
291*7304104dSAndroid Build Coastguard Worker do { \
292*7304104dSAndroid Build Coastguard Worker const char *_str = (str); \
293*7304104dSAndroid Build Coastguard Worker size_t _len = (len); \
294*7304104dSAndroid Build Coastguard Worker if (unlikely (bufcnt + _len > bufsize)) \
295*7304104dSAndroid Build Coastguard Worker goto enomem; \
296*7304104dSAndroid Build Coastguard Worker memcpy (buf + bufcnt, _str, _len); \
297*7304104dSAndroid Build Coastguard Worker bufcnt += _len; \
298*7304104dSAndroid Build Coastguard Worker } while (0)
299*7304104dSAndroid Build Coastguard Worker
300*7304104dSAndroid Build Coastguard Worker
301*7304104dSAndroid Build Coastguard Worker int
i386_disasm(Ebl * ebl,const uint8_t ** startp,const uint8_t * end,GElf_Addr addr,const char * fmt,DisasmOutputCB_t outcb,DisasmGetSymCB_t symcb,void * outcbarg,void * symcbarg)302*7304104dSAndroid Build Coastguard Worker i386_disasm (Ebl *ebl __attribute__((unused)),
303*7304104dSAndroid Build Coastguard Worker const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
304*7304104dSAndroid Build Coastguard Worker const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
305*7304104dSAndroid Build Coastguard Worker void *outcbarg, void *symcbarg)
306*7304104dSAndroid Build Coastguard Worker {
307*7304104dSAndroid Build Coastguard Worker const char *save_fmt = fmt;
308*7304104dSAndroid Build Coastguard Worker
309*7304104dSAndroid Build Coastguard Worker #define BUFSIZE 512
310*7304104dSAndroid Build Coastguard Worker char initbuf[BUFSIZE];
311*7304104dSAndroid Build Coastguard Worker int prefixes;
312*7304104dSAndroid Build Coastguard Worker size_t bufcnt;
313*7304104dSAndroid Build Coastguard Worker size_t bufsize = BUFSIZE;
314*7304104dSAndroid Build Coastguard Worker char *buf = initbuf;
315*7304104dSAndroid Build Coastguard Worker const uint8_t *param_start;
316*7304104dSAndroid Build Coastguard Worker
317*7304104dSAndroid Build Coastguard Worker struct output_data output_data =
318*7304104dSAndroid Build Coastguard Worker {
319*7304104dSAndroid Build Coastguard Worker .prefixes = &prefixes,
320*7304104dSAndroid Build Coastguard Worker .bufp = buf,
321*7304104dSAndroid Build Coastguard Worker .bufsize = bufsize,
322*7304104dSAndroid Build Coastguard Worker .bufcntp = &bufcnt,
323*7304104dSAndroid Build Coastguard Worker .param_start = ¶m_start,
324*7304104dSAndroid Build Coastguard Worker .end = end
325*7304104dSAndroid Build Coastguard Worker };
326*7304104dSAndroid Build Coastguard Worker
327*7304104dSAndroid Build Coastguard Worker int retval = 0;
328*7304104dSAndroid Build Coastguard Worker while (1)
329*7304104dSAndroid Build Coastguard Worker {
330*7304104dSAndroid Build Coastguard Worker prefixes = 0;
331*7304104dSAndroid Build Coastguard Worker
332*7304104dSAndroid Build Coastguard Worker const uint8_t *data = *startp;
333*7304104dSAndroid Build Coastguard Worker const uint8_t *begin = data;
334*7304104dSAndroid Build Coastguard Worker
335*7304104dSAndroid Build Coastguard Worker /* Recognize all prefixes. */
336*7304104dSAndroid Build Coastguard Worker int last_prefix_bit = 0;
337*7304104dSAndroid Build Coastguard Worker while (data < end)
338*7304104dSAndroid Build Coastguard Worker {
339*7304104dSAndroid Build Coastguard Worker unsigned int i;
340*7304104dSAndroid Build Coastguard Worker for (i = idx_cs; i < nknown_prefixes; ++i)
341*7304104dSAndroid Build Coastguard Worker if (known_prefixes[i] == *data)
342*7304104dSAndroid Build Coastguard Worker break;
343*7304104dSAndroid Build Coastguard Worker if (i == nknown_prefixes)
344*7304104dSAndroid Build Coastguard Worker break;
345*7304104dSAndroid Build Coastguard Worker
346*7304104dSAndroid Build Coastguard Worker prefixes |= last_prefix_bit = 1 << i;
347*7304104dSAndroid Build Coastguard Worker
348*7304104dSAndroid Build Coastguard Worker ++data;
349*7304104dSAndroid Build Coastguard Worker }
350*7304104dSAndroid Build Coastguard Worker
351*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
352*7304104dSAndroid Build Coastguard Worker if (data < end && (*data & 0xf0) == 0x40)
353*7304104dSAndroid Build Coastguard Worker prefixes |= ((*data++) & 0xf) | has_rex;
354*7304104dSAndroid Build Coastguard Worker #endif
355*7304104dSAndroid Build Coastguard Worker
356*7304104dSAndroid Build Coastguard Worker bufcnt = 0;
357*7304104dSAndroid Build Coastguard Worker size_t cnt = 0;
358*7304104dSAndroid Build Coastguard Worker
359*7304104dSAndroid Build Coastguard Worker const uint8_t *curr = match_data;
360*7304104dSAndroid Build Coastguard Worker const uint8_t *const match_end = match_data + sizeof (match_data);
361*7304104dSAndroid Build Coastguard Worker
362*7304104dSAndroid Build Coastguard Worker assert (data <= end);
363*7304104dSAndroid Build Coastguard Worker if (data == end)
364*7304104dSAndroid Build Coastguard Worker {
365*7304104dSAndroid Build Coastguard Worker if (prefixes != 0)
366*7304104dSAndroid Build Coastguard Worker goto print_prefix;
367*7304104dSAndroid Build Coastguard Worker
368*7304104dSAndroid Build Coastguard Worker retval = -1;
369*7304104dSAndroid Build Coastguard Worker goto do_ret;
370*7304104dSAndroid Build Coastguard Worker }
371*7304104dSAndroid Build Coastguard Worker
372*7304104dSAndroid Build Coastguard Worker next_match:
373*7304104dSAndroid Build Coastguard Worker while (curr < match_end)
374*7304104dSAndroid Build Coastguard Worker {
375*7304104dSAndroid Build Coastguard Worker uint_fast8_t len = *curr++;
376*7304104dSAndroid Build Coastguard Worker uint_fast8_t clen = len >> 4;
377*7304104dSAndroid Build Coastguard Worker len &= 0xf;
378*7304104dSAndroid Build Coastguard Worker const uint8_t *next_curr = curr + clen + (len - clen) * 2;
379*7304104dSAndroid Build Coastguard Worker
380*7304104dSAndroid Build Coastguard Worker assert (len > 0);
381*7304104dSAndroid Build Coastguard Worker assert (curr + clen + 2 * (len - clen) <= match_end);
382*7304104dSAndroid Build Coastguard Worker
383*7304104dSAndroid Build Coastguard Worker const uint8_t *codep = data;
384*7304104dSAndroid Build Coastguard Worker int correct_prefix = 0;
385*7304104dSAndroid Build Coastguard Worker int opoff = 0;
386*7304104dSAndroid Build Coastguard Worker
387*7304104dSAndroid Build Coastguard Worker if (data > begin && codep[-1] == *curr && clen > 0)
388*7304104dSAndroid Build Coastguard Worker {
389*7304104dSAndroid Build Coastguard Worker /* We match a prefix byte. This is exactly one byte and
390*7304104dSAndroid Build Coastguard Worker is matched exactly, without a mask. */
391*7304104dSAndroid Build Coastguard Worker --len;
392*7304104dSAndroid Build Coastguard Worker --clen;
393*7304104dSAndroid Build Coastguard Worker opoff = 8;
394*7304104dSAndroid Build Coastguard Worker
395*7304104dSAndroid Build Coastguard Worker ++curr;
396*7304104dSAndroid Build Coastguard Worker
397*7304104dSAndroid Build Coastguard Worker if (last_prefix_bit == 0)
398*7304104dSAndroid Build Coastguard Worker goto invalid_op;
399*7304104dSAndroid Build Coastguard Worker correct_prefix = last_prefix_bit;
400*7304104dSAndroid Build Coastguard Worker }
401*7304104dSAndroid Build Coastguard Worker
402*7304104dSAndroid Build Coastguard Worker size_t avail = len;
403*7304104dSAndroid Build Coastguard Worker while (clen > 0)
404*7304104dSAndroid Build Coastguard Worker {
405*7304104dSAndroid Build Coastguard Worker if (*codep++ != *curr++)
406*7304104dSAndroid Build Coastguard Worker goto not;
407*7304104dSAndroid Build Coastguard Worker --avail;
408*7304104dSAndroid Build Coastguard Worker --clen;
409*7304104dSAndroid Build Coastguard Worker if (codep == end && avail > 0)
410*7304104dSAndroid Build Coastguard Worker goto do_ret;
411*7304104dSAndroid Build Coastguard Worker }
412*7304104dSAndroid Build Coastguard Worker
413*7304104dSAndroid Build Coastguard Worker while (avail > 0)
414*7304104dSAndroid Build Coastguard Worker {
415*7304104dSAndroid Build Coastguard Worker uint_fast8_t masked = *codep++ & *curr++;
416*7304104dSAndroid Build Coastguard Worker if (masked != *curr++)
417*7304104dSAndroid Build Coastguard Worker {
418*7304104dSAndroid Build Coastguard Worker not:
419*7304104dSAndroid Build Coastguard Worker curr = next_curr;
420*7304104dSAndroid Build Coastguard Worker ++cnt;
421*7304104dSAndroid Build Coastguard Worker bufcnt = 0;
422*7304104dSAndroid Build Coastguard Worker goto next_match;
423*7304104dSAndroid Build Coastguard Worker }
424*7304104dSAndroid Build Coastguard Worker
425*7304104dSAndroid Build Coastguard Worker --avail;
426*7304104dSAndroid Build Coastguard Worker if (codep == end && avail > 0)
427*7304104dSAndroid Build Coastguard Worker goto do_ret;
428*7304104dSAndroid Build Coastguard Worker }
429*7304104dSAndroid Build Coastguard Worker
430*7304104dSAndroid Build Coastguard Worker if (len > end - data)
431*7304104dSAndroid Build Coastguard Worker /* There is not enough data for the entire instruction. The
432*7304104dSAndroid Build Coastguard Worker caller can figure this out by looking at the pointer into
433*7304104dSAndroid Build Coastguard Worker the input data. */
434*7304104dSAndroid Build Coastguard Worker goto do_ret;
435*7304104dSAndroid Build Coastguard Worker
436*7304104dSAndroid Build Coastguard Worker if (correct_prefix != 0 && (prefixes & correct_prefix) == 0)
437*7304104dSAndroid Build Coastguard Worker goto invalid_op;
438*7304104dSAndroid Build Coastguard Worker prefixes ^= correct_prefix;
439*7304104dSAndroid Build Coastguard Worker
440*7304104dSAndroid Build Coastguard Worker if (0)
441*7304104dSAndroid Build Coastguard Worker {
442*7304104dSAndroid Build Coastguard Worker /* Resize the buffer. */
443*7304104dSAndroid Build Coastguard Worker char *oldbuf;
444*7304104dSAndroid Build Coastguard Worker enomem:
445*7304104dSAndroid Build Coastguard Worker oldbuf = buf;
446*7304104dSAndroid Build Coastguard Worker if (buf == initbuf)
447*7304104dSAndroid Build Coastguard Worker buf = malloc (2 * bufsize);
448*7304104dSAndroid Build Coastguard Worker else
449*7304104dSAndroid Build Coastguard Worker buf = realloc (buf, 2 * bufsize);
450*7304104dSAndroid Build Coastguard Worker if (buf == NULL)
451*7304104dSAndroid Build Coastguard Worker {
452*7304104dSAndroid Build Coastguard Worker buf = oldbuf;
453*7304104dSAndroid Build Coastguard Worker retval = ENOMEM;
454*7304104dSAndroid Build Coastguard Worker goto do_ret;
455*7304104dSAndroid Build Coastguard Worker }
456*7304104dSAndroid Build Coastguard Worker bufsize *= 2;
457*7304104dSAndroid Build Coastguard Worker
458*7304104dSAndroid Build Coastguard Worker output_data.bufp = buf;
459*7304104dSAndroid Build Coastguard Worker output_data.bufsize = bufsize;
460*7304104dSAndroid Build Coastguard Worker bufcnt = 0;
461*7304104dSAndroid Build Coastguard Worker
462*7304104dSAndroid Build Coastguard Worker if (data == end)
463*7304104dSAndroid Build Coastguard Worker {
464*7304104dSAndroid Build Coastguard Worker if (prefixes == 0)
465*7304104dSAndroid Build Coastguard Worker goto invalid_op;
466*7304104dSAndroid Build Coastguard Worker goto print_prefix;
467*7304104dSAndroid Build Coastguard Worker }
468*7304104dSAndroid Build Coastguard Worker
469*7304104dSAndroid Build Coastguard Worker /* gcc is not clever enough to see the following variables
470*7304104dSAndroid Build Coastguard Worker are not used uninitialized. */
471*7304104dSAndroid Build Coastguard Worker __asm (""
472*7304104dSAndroid Build Coastguard Worker : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
473*7304104dSAndroid Build Coastguard Worker "=mr" (next_curr), "=mr" (len));
474*7304104dSAndroid Build Coastguard Worker }
475*7304104dSAndroid Build Coastguard Worker
476*7304104dSAndroid Build Coastguard Worker size_t prefix_size = 0;
477*7304104dSAndroid Build Coastguard Worker
478*7304104dSAndroid Build Coastguard Worker // XXXonly print as prefix if valid?
479*7304104dSAndroid Build Coastguard Worker if ((prefixes & has_lock) != 0)
480*7304104dSAndroid Build Coastguard Worker {
481*7304104dSAndroid Build Coastguard Worker ADD_STRING ("lock ");
482*7304104dSAndroid Build Coastguard Worker prefix_size += 5;
483*7304104dSAndroid Build Coastguard Worker }
484*7304104dSAndroid Build Coastguard Worker
485*7304104dSAndroid Build Coastguard Worker if (instrtab[cnt].rep)
486*7304104dSAndroid Build Coastguard Worker {
487*7304104dSAndroid Build Coastguard Worker if ((prefixes & has_rep) != 0)
488*7304104dSAndroid Build Coastguard Worker {
489*7304104dSAndroid Build Coastguard Worker ADD_STRING ("rep ");
490*7304104dSAndroid Build Coastguard Worker prefix_size += 4;
491*7304104dSAndroid Build Coastguard Worker }
492*7304104dSAndroid Build Coastguard Worker }
493*7304104dSAndroid Build Coastguard Worker else if (instrtab[cnt].repe
494*7304104dSAndroid Build Coastguard Worker && (prefixes & (has_rep | has_repne)) != 0)
495*7304104dSAndroid Build Coastguard Worker {
496*7304104dSAndroid Build Coastguard Worker if ((prefixes & has_repne) != 0)
497*7304104dSAndroid Build Coastguard Worker {
498*7304104dSAndroid Build Coastguard Worker ADD_STRING ("repne ");
499*7304104dSAndroid Build Coastguard Worker prefix_size += 6;
500*7304104dSAndroid Build Coastguard Worker }
501*7304104dSAndroid Build Coastguard Worker else if ((prefixes & has_rep) != 0)
502*7304104dSAndroid Build Coastguard Worker {
503*7304104dSAndroid Build Coastguard Worker ADD_STRING ("repe ");
504*7304104dSAndroid Build Coastguard Worker prefix_size += 5;
505*7304104dSAndroid Build Coastguard Worker }
506*7304104dSAndroid Build Coastguard Worker }
507*7304104dSAndroid Build Coastguard Worker else if ((prefixes & (has_rep | has_repne)) != 0)
508*7304104dSAndroid Build Coastguard Worker {
509*7304104dSAndroid Build Coastguard Worker uint_fast8_t byte;
510*7304104dSAndroid Build Coastguard Worker print_prefix:
511*7304104dSAndroid Build Coastguard Worker bufcnt = 0;
512*7304104dSAndroid Build Coastguard Worker byte = *begin;
513*7304104dSAndroid Build Coastguard Worker /* This is a prefix byte. Print it. */
514*7304104dSAndroid Build Coastguard Worker switch (byte)
515*7304104dSAndroid Build Coastguard Worker {
516*7304104dSAndroid Build Coastguard Worker case prefix_rep:
517*7304104dSAndroid Build Coastguard Worker ADD_STRING ("rep");
518*7304104dSAndroid Build Coastguard Worker break;
519*7304104dSAndroid Build Coastguard Worker case prefix_repne:
520*7304104dSAndroid Build Coastguard Worker ADD_STRING ("repne");
521*7304104dSAndroid Build Coastguard Worker break;
522*7304104dSAndroid Build Coastguard Worker case prefix_cs:
523*7304104dSAndroid Build Coastguard Worker ADD_STRING ("cs");
524*7304104dSAndroid Build Coastguard Worker break;
525*7304104dSAndroid Build Coastguard Worker case prefix_ds:
526*7304104dSAndroid Build Coastguard Worker ADD_STRING ("ds");
527*7304104dSAndroid Build Coastguard Worker break;
528*7304104dSAndroid Build Coastguard Worker case prefix_es:
529*7304104dSAndroid Build Coastguard Worker ADD_STRING ("es");
530*7304104dSAndroid Build Coastguard Worker break;
531*7304104dSAndroid Build Coastguard Worker case prefix_fs:
532*7304104dSAndroid Build Coastguard Worker ADD_STRING ("fs");
533*7304104dSAndroid Build Coastguard Worker break;
534*7304104dSAndroid Build Coastguard Worker case prefix_gs:
535*7304104dSAndroid Build Coastguard Worker ADD_STRING ("gs");
536*7304104dSAndroid Build Coastguard Worker break;
537*7304104dSAndroid Build Coastguard Worker case prefix_ss:
538*7304104dSAndroid Build Coastguard Worker ADD_STRING ("ss");
539*7304104dSAndroid Build Coastguard Worker break;
540*7304104dSAndroid Build Coastguard Worker case prefix_data16:
541*7304104dSAndroid Build Coastguard Worker ADD_STRING ("data16");
542*7304104dSAndroid Build Coastguard Worker break;
543*7304104dSAndroid Build Coastguard Worker case prefix_addr16:
544*7304104dSAndroid Build Coastguard Worker ADD_STRING ("addr16");
545*7304104dSAndroid Build Coastguard Worker break;
546*7304104dSAndroid Build Coastguard Worker case prefix_lock:
547*7304104dSAndroid Build Coastguard Worker ADD_STRING ("lock");
548*7304104dSAndroid Build Coastguard Worker break;
549*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
550*7304104dSAndroid Build Coastguard Worker case 0x40 ... 0x4f:
551*7304104dSAndroid Build Coastguard Worker ADD_STRING ("rex");
552*7304104dSAndroid Build Coastguard Worker if (byte != 0x40)
553*7304104dSAndroid Build Coastguard Worker {
554*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('.');
555*7304104dSAndroid Build Coastguard Worker if (byte & 0x8)
556*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('w');
557*7304104dSAndroid Build Coastguard Worker if (byte & 0x4)
558*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('r');
559*7304104dSAndroid Build Coastguard Worker if (byte & 0x3)
560*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('x');
561*7304104dSAndroid Build Coastguard Worker if (byte & 0x1)
562*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('b');
563*7304104dSAndroid Build Coastguard Worker }
564*7304104dSAndroid Build Coastguard Worker break;
565*7304104dSAndroid Build Coastguard Worker #endif
566*7304104dSAndroid Build Coastguard Worker default:
567*7304104dSAndroid Build Coastguard Worker /* Cannot happen. */
568*7304104dSAndroid Build Coastguard Worker puts ("unknown prefix");
569*7304104dSAndroid Build Coastguard Worker abort ();
570*7304104dSAndroid Build Coastguard Worker }
571*7304104dSAndroid Build Coastguard Worker data = begin + 1;
572*7304104dSAndroid Build Coastguard Worker ++addr;
573*7304104dSAndroid Build Coastguard Worker
574*7304104dSAndroid Build Coastguard Worker goto out;
575*7304104dSAndroid Build Coastguard Worker }
576*7304104dSAndroid Build Coastguard Worker
577*7304104dSAndroid Build Coastguard Worker /* We have a match. First determine how many bytes are
578*7304104dSAndroid Build Coastguard Worker needed for the addressing mode. */
579*7304104dSAndroid Build Coastguard Worker param_start = codep;
580*7304104dSAndroid Build Coastguard Worker if (instrtab[cnt].modrm)
581*7304104dSAndroid Build Coastguard Worker {
582*7304104dSAndroid Build Coastguard Worker uint_fast8_t modrm = codep[-1];
583*7304104dSAndroid Build Coastguard Worker
584*7304104dSAndroid Build Coastguard Worker #ifndef X86_64
585*7304104dSAndroid Build Coastguard Worker if (likely ((prefixes & has_addr16) != 0))
586*7304104dSAndroid Build Coastguard Worker {
587*7304104dSAndroid Build Coastguard Worker /* Account for displacement. */
588*7304104dSAndroid Build Coastguard Worker if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
589*7304104dSAndroid Build Coastguard Worker param_start += 2;
590*7304104dSAndroid Build Coastguard Worker else if ((modrm & 0xc0) == 0x40)
591*7304104dSAndroid Build Coastguard Worker param_start += 1;
592*7304104dSAndroid Build Coastguard Worker }
593*7304104dSAndroid Build Coastguard Worker else
594*7304104dSAndroid Build Coastguard Worker #endif
595*7304104dSAndroid Build Coastguard Worker {
596*7304104dSAndroid Build Coastguard Worker /* Account for SIB. */
597*7304104dSAndroid Build Coastguard Worker if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
598*7304104dSAndroid Build Coastguard Worker param_start += 1;
599*7304104dSAndroid Build Coastguard Worker
600*7304104dSAndroid Build Coastguard Worker /* Account for displacement. */
601*7304104dSAndroid Build Coastguard Worker if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
602*7304104dSAndroid Build Coastguard Worker || ((modrm & 0xc7) == 0x4
603*7304104dSAndroid Build Coastguard Worker && param_start < end
604*7304104dSAndroid Build Coastguard Worker && (codep[0] & 0x7) == 0x5))
605*7304104dSAndroid Build Coastguard Worker param_start += 4;
606*7304104dSAndroid Build Coastguard Worker else if ((modrm & 0xc0) == 0x40)
607*7304104dSAndroid Build Coastguard Worker param_start += 1;
608*7304104dSAndroid Build Coastguard Worker }
609*7304104dSAndroid Build Coastguard Worker
610*7304104dSAndroid Build Coastguard Worker if (unlikely (param_start > end))
611*7304104dSAndroid Build Coastguard Worker goto not;
612*7304104dSAndroid Build Coastguard Worker }
613*7304104dSAndroid Build Coastguard Worker
614*7304104dSAndroid Build Coastguard Worker output_data.addr = addr + (data - begin);
615*7304104dSAndroid Build Coastguard Worker output_data.data = data;
616*7304104dSAndroid Build Coastguard Worker
617*7304104dSAndroid Build Coastguard Worker unsigned long string_end_idx = 0;
618*7304104dSAndroid Build Coastguard Worker fmt = save_fmt;
619*7304104dSAndroid Build Coastguard Worker const char *deferred_start = NULL;
620*7304104dSAndroid Build Coastguard Worker size_t deferred_len = 0;
621*7304104dSAndroid Build Coastguard Worker // XXX Can we get this from color.c?
622*7304104dSAndroid Build Coastguard Worker static const char color_off[] = "\e[0m";
623*7304104dSAndroid Build Coastguard Worker while (*fmt != '\0')
624*7304104dSAndroid Build Coastguard Worker {
625*7304104dSAndroid Build Coastguard Worker if (*fmt != '%')
626*7304104dSAndroid Build Coastguard Worker {
627*7304104dSAndroid Build Coastguard Worker char ch = *fmt++;
628*7304104dSAndroid Build Coastguard Worker if (ch == '\\')
629*7304104dSAndroid Build Coastguard Worker {
630*7304104dSAndroid Build Coastguard Worker switch ((ch = *fmt++))
631*7304104dSAndroid Build Coastguard Worker {
632*7304104dSAndroid Build Coastguard Worker case '0' ... '7':
633*7304104dSAndroid Build Coastguard Worker {
634*7304104dSAndroid Build Coastguard Worker int val = ch - '0';
635*7304104dSAndroid Build Coastguard Worker ch = *fmt;
636*7304104dSAndroid Build Coastguard Worker if (ch >= '0' && ch <= '7')
637*7304104dSAndroid Build Coastguard Worker {
638*7304104dSAndroid Build Coastguard Worker val *= 8;
639*7304104dSAndroid Build Coastguard Worker val += ch - '0';
640*7304104dSAndroid Build Coastguard Worker ch = *++fmt;
641*7304104dSAndroid Build Coastguard Worker if (ch >= '0' && ch <= '7' && val < 32)
642*7304104dSAndroid Build Coastguard Worker {
643*7304104dSAndroid Build Coastguard Worker val *= 8;
644*7304104dSAndroid Build Coastguard Worker val += ch - '0';
645*7304104dSAndroid Build Coastguard Worker ++fmt;
646*7304104dSAndroid Build Coastguard Worker }
647*7304104dSAndroid Build Coastguard Worker }
648*7304104dSAndroid Build Coastguard Worker ch = val;
649*7304104dSAndroid Build Coastguard Worker }
650*7304104dSAndroid Build Coastguard Worker break;
651*7304104dSAndroid Build Coastguard Worker
652*7304104dSAndroid Build Coastguard Worker case 'n':
653*7304104dSAndroid Build Coastguard Worker ch = '\n';
654*7304104dSAndroid Build Coastguard Worker break;
655*7304104dSAndroid Build Coastguard Worker
656*7304104dSAndroid Build Coastguard Worker case 't':
657*7304104dSAndroid Build Coastguard Worker ch = '\t';
658*7304104dSAndroid Build Coastguard Worker break;
659*7304104dSAndroid Build Coastguard Worker
660*7304104dSAndroid Build Coastguard Worker default:
661*7304104dSAndroid Build Coastguard Worker retval = EINVAL;
662*7304104dSAndroid Build Coastguard Worker goto do_ret;
663*7304104dSAndroid Build Coastguard Worker }
664*7304104dSAndroid Build Coastguard Worker }
665*7304104dSAndroid Build Coastguard Worker else if (ch == '\e' && *fmt == '[')
666*7304104dSAndroid Build Coastguard Worker {
667*7304104dSAndroid Build Coastguard Worker deferred_start = fmt - 1;
668*7304104dSAndroid Build Coastguard Worker do
669*7304104dSAndroid Build Coastguard Worker ++fmt;
670*7304104dSAndroid Build Coastguard Worker while (*fmt != 'm' && *fmt != '\0');
671*7304104dSAndroid Build Coastguard Worker
672*7304104dSAndroid Build Coastguard Worker if (*fmt == 'm')
673*7304104dSAndroid Build Coastguard Worker {
674*7304104dSAndroid Build Coastguard Worker deferred_len = ++fmt - deferred_start;
675*7304104dSAndroid Build Coastguard Worker continue;
676*7304104dSAndroid Build Coastguard Worker }
677*7304104dSAndroid Build Coastguard Worker
678*7304104dSAndroid Build Coastguard Worker fmt = deferred_start + 1;
679*7304104dSAndroid Build Coastguard Worker deferred_start = NULL;
680*7304104dSAndroid Build Coastguard Worker }
681*7304104dSAndroid Build Coastguard Worker ADD_CHAR (ch);
682*7304104dSAndroid Build Coastguard Worker continue;
683*7304104dSAndroid Build Coastguard Worker }
684*7304104dSAndroid Build Coastguard Worker ++fmt;
685*7304104dSAndroid Build Coastguard Worker
686*7304104dSAndroid Build Coastguard Worker int width = 0;
687*7304104dSAndroid Build Coastguard Worker while (isdigit (*fmt))
688*7304104dSAndroid Build Coastguard Worker width = width * 10 + (*fmt++ - '0');
689*7304104dSAndroid Build Coastguard Worker
690*7304104dSAndroid Build Coastguard Worker int prec = 0;
691*7304104dSAndroid Build Coastguard Worker if (*fmt == '.')
692*7304104dSAndroid Build Coastguard Worker while (isdigit (*++fmt))
693*7304104dSAndroid Build Coastguard Worker prec = prec * 10 + (*fmt - '0');
694*7304104dSAndroid Build Coastguard Worker
695*7304104dSAndroid Build Coastguard Worker size_t start_idx = bufcnt;
696*7304104dSAndroid Build Coastguard Worker size_t non_printing = 0;
697*7304104dSAndroid Build Coastguard Worker switch (*fmt++)
698*7304104dSAndroid Build Coastguard Worker {
699*7304104dSAndroid Build Coastguard Worker char mnebuf[16];
700*7304104dSAndroid Build Coastguard Worker const char *str;
701*7304104dSAndroid Build Coastguard Worker
702*7304104dSAndroid Build Coastguard Worker case 'm':
703*7304104dSAndroid Build Coastguard Worker /* Mnemonic. */
704*7304104dSAndroid Build Coastguard Worker
705*7304104dSAndroid Build Coastguard Worker if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
706*7304104dSAndroid Build Coastguard Worker {
707*7304104dSAndroid Build Coastguard Worker switch (*data)
708*7304104dSAndroid Build Coastguard Worker {
709*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
710*7304104dSAndroid Build Coastguard Worker case 0x90:
711*7304104dSAndroid Build Coastguard Worker if (prefixes & has_rex_b)
712*7304104dSAndroid Build Coastguard Worker goto not;
713*7304104dSAndroid Build Coastguard Worker str = "nop";
714*7304104dSAndroid Build Coastguard Worker break;
715*7304104dSAndroid Build Coastguard Worker #endif
716*7304104dSAndroid Build Coastguard Worker
717*7304104dSAndroid Build Coastguard Worker case 0x98:
718*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
719*7304104dSAndroid Build Coastguard Worker if (prefixes == (has_rex_w | has_rex))
720*7304104dSAndroid Build Coastguard Worker {
721*7304104dSAndroid Build Coastguard Worker str = "cltq";
722*7304104dSAndroid Build Coastguard Worker break;
723*7304104dSAndroid Build Coastguard Worker }
724*7304104dSAndroid Build Coastguard Worker #endif
725*7304104dSAndroid Build Coastguard Worker if (prefixes & ~has_data16)
726*7304104dSAndroid Build Coastguard Worker goto print_prefix;
727*7304104dSAndroid Build Coastguard Worker str = prefixes & has_data16 ? "cbtw" : "cwtl";
728*7304104dSAndroid Build Coastguard Worker break;
729*7304104dSAndroid Build Coastguard Worker
730*7304104dSAndroid Build Coastguard Worker case 0x99:
731*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
732*7304104dSAndroid Build Coastguard Worker if (prefixes == (has_rex_w | has_rex))
733*7304104dSAndroid Build Coastguard Worker {
734*7304104dSAndroid Build Coastguard Worker str = "cqto";
735*7304104dSAndroid Build Coastguard Worker break;
736*7304104dSAndroid Build Coastguard Worker }
737*7304104dSAndroid Build Coastguard Worker #endif
738*7304104dSAndroid Build Coastguard Worker if (prefixes & ~has_data16)
739*7304104dSAndroid Build Coastguard Worker goto print_prefix;
740*7304104dSAndroid Build Coastguard Worker str = prefixes & has_data16 ? "cwtd" : "cltd";
741*7304104dSAndroid Build Coastguard Worker break;
742*7304104dSAndroid Build Coastguard Worker
743*7304104dSAndroid Build Coastguard Worker case 0xe3:
744*7304104dSAndroid Build Coastguard Worker if (prefixes & ~has_addr16)
745*7304104dSAndroid Build Coastguard Worker goto print_prefix;
746*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
747*7304104dSAndroid Build Coastguard Worker str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
748*7304104dSAndroid Build Coastguard Worker #else
749*7304104dSAndroid Build Coastguard Worker str = prefixes & has_addr16 ? "jcxz" : "jecxz";
750*7304104dSAndroid Build Coastguard Worker #endif
751*7304104dSAndroid Build Coastguard Worker break;
752*7304104dSAndroid Build Coastguard Worker
753*7304104dSAndroid Build Coastguard Worker case 0x0f:
754*7304104dSAndroid Build Coastguard Worker if (data[1] == 0x0f)
755*7304104dSAndroid Build Coastguard Worker {
756*7304104dSAndroid Build Coastguard Worker /* AMD 3DNOW. We need one more byte. */
757*7304104dSAndroid Build Coastguard Worker if (param_start >= end)
758*7304104dSAndroid Build Coastguard Worker goto not;
759*7304104dSAndroid Build Coastguard Worker if (*param_start < AMD3DNOW_LOW_IDX
760*7304104dSAndroid Build Coastguard Worker || *param_start > AMD3DNOW_HIGH_IDX)
761*7304104dSAndroid Build Coastguard Worker goto not;
762*7304104dSAndroid Build Coastguard Worker unsigned int idx
763*7304104dSAndroid Build Coastguard Worker = amd3dnow[AMD3DNOW_IDX (*param_start)];
764*7304104dSAndroid Build Coastguard Worker if (idx == 0)
765*7304104dSAndroid Build Coastguard Worker goto not;
766*7304104dSAndroid Build Coastguard Worker str = amd3dnowstr + idx - 1;
767*7304104dSAndroid Build Coastguard Worker /* Eat the immediate byte indicating the
768*7304104dSAndroid Build Coastguard Worker operation. */
769*7304104dSAndroid Build Coastguard Worker ++param_start;
770*7304104dSAndroid Build Coastguard Worker break;
771*7304104dSAndroid Build Coastguard Worker }
772*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
773*7304104dSAndroid Build Coastguard Worker if (data[1] == 0xc7)
774*7304104dSAndroid Build Coastguard Worker {
775*7304104dSAndroid Build Coastguard Worker str = ((prefixes & has_rex_w)
776*7304104dSAndroid Build Coastguard Worker ? "cmpxchg16b" : "cmpxchg8b");
777*7304104dSAndroid Build Coastguard Worker break;
778*7304104dSAndroid Build Coastguard Worker }
779*7304104dSAndroid Build Coastguard Worker #endif
780*7304104dSAndroid Build Coastguard Worker if (data[1] == 0xc2)
781*7304104dSAndroid Build Coastguard Worker {
782*7304104dSAndroid Build Coastguard Worker if (param_start >= end)
783*7304104dSAndroid Build Coastguard Worker goto not;
784*7304104dSAndroid Build Coastguard Worker if (*param_start > 7)
785*7304104dSAndroid Build Coastguard Worker goto not;
786*7304104dSAndroid Build Coastguard Worker static const char cmpops[][9] =
787*7304104dSAndroid Build Coastguard Worker {
788*7304104dSAndroid Build Coastguard Worker [0] = "cmpeq",
789*7304104dSAndroid Build Coastguard Worker [1] = "cmplt",
790*7304104dSAndroid Build Coastguard Worker [2] = "cmple",
791*7304104dSAndroid Build Coastguard Worker [3] = "cmpunord",
792*7304104dSAndroid Build Coastguard Worker [4] = "cmpneq",
793*7304104dSAndroid Build Coastguard Worker [5] = "cmpnlt",
794*7304104dSAndroid Build Coastguard Worker [6] = "cmpnle",
795*7304104dSAndroid Build Coastguard Worker [7] = "cmpord"
796*7304104dSAndroid Build Coastguard Worker };
797*7304104dSAndroid Build Coastguard Worker char *cp = stpcpy (mnebuf, cmpops[*param_start]);
798*7304104dSAndroid Build Coastguard Worker if (correct_prefix & (has_rep | has_repne))
799*7304104dSAndroid Build Coastguard Worker *cp++ = 's';
800*7304104dSAndroid Build Coastguard Worker else
801*7304104dSAndroid Build Coastguard Worker *cp++ = 'p';
802*7304104dSAndroid Build Coastguard Worker if (correct_prefix & (has_data16 | has_repne))
803*7304104dSAndroid Build Coastguard Worker *cp++ = 'd';
804*7304104dSAndroid Build Coastguard Worker else
805*7304104dSAndroid Build Coastguard Worker *cp++ = 's';
806*7304104dSAndroid Build Coastguard Worker *cp = '\0';
807*7304104dSAndroid Build Coastguard Worker str = mnebuf;
808*7304104dSAndroid Build Coastguard Worker /* Eat the immediate byte indicating the
809*7304104dSAndroid Build Coastguard Worker operation. */
810*7304104dSAndroid Build Coastguard Worker ++param_start;
811*7304104dSAndroid Build Coastguard Worker break;
812*7304104dSAndroid Build Coastguard Worker }
813*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
814*7304104dSAndroid Build Coastguard Worker default:
815*7304104dSAndroid Build Coastguard Worker str = "INVALID not handled";
816*7304104dSAndroid Build Coastguard Worker break;
817*7304104dSAndroid Build Coastguard Worker }
818*7304104dSAndroid Build Coastguard Worker }
819*7304104dSAndroid Build Coastguard Worker else
820*7304104dSAndroid Build Coastguard Worker str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
821*7304104dSAndroid Build Coastguard Worker
822*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
823*7304104dSAndroid Build Coastguard Worker {
824*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (deferred_start, deferred_len);
825*7304104dSAndroid Build Coastguard Worker non_printing += deferred_len;
826*7304104dSAndroid Build Coastguard Worker }
827*7304104dSAndroid Build Coastguard Worker
828*7304104dSAndroid Build Coastguard Worker ADD_STRING (str);
829*7304104dSAndroid Build Coastguard Worker
830*7304104dSAndroid Build Coastguard Worker switch (instrtab[cnt].suffix)
831*7304104dSAndroid Build Coastguard Worker {
832*7304104dSAndroid Build Coastguard Worker case suffix_none:
833*7304104dSAndroid Build Coastguard Worker break;
834*7304104dSAndroid Build Coastguard Worker
835*7304104dSAndroid Build Coastguard Worker case suffix_w:
836*7304104dSAndroid Build Coastguard Worker if ((codep[-1] & 0xc0) != 0xc0)
837*7304104dSAndroid Build Coastguard Worker {
838*7304104dSAndroid Build Coastguard Worker char ch;
839*7304104dSAndroid Build Coastguard Worker
840*7304104dSAndroid Build Coastguard Worker if (data[0] & 1)
841*7304104dSAndroid Build Coastguard Worker {
842*7304104dSAndroid Build Coastguard Worker if (prefixes & has_data16)
843*7304104dSAndroid Build Coastguard Worker ch = 'w';
844*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
845*7304104dSAndroid Build Coastguard Worker else if (prefixes & has_rex_w)
846*7304104dSAndroid Build Coastguard Worker ch = 'q';
847*7304104dSAndroid Build Coastguard Worker #endif
848*7304104dSAndroid Build Coastguard Worker else
849*7304104dSAndroid Build Coastguard Worker ch = 'l';
850*7304104dSAndroid Build Coastguard Worker }
851*7304104dSAndroid Build Coastguard Worker else
852*7304104dSAndroid Build Coastguard Worker ch = 'b';
853*7304104dSAndroid Build Coastguard Worker
854*7304104dSAndroid Build Coastguard Worker ADD_CHAR (ch);
855*7304104dSAndroid Build Coastguard Worker }
856*7304104dSAndroid Build Coastguard Worker break;
857*7304104dSAndroid Build Coastguard Worker
858*7304104dSAndroid Build Coastguard Worker case suffix_w0:
859*7304104dSAndroid Build Coastguard Worker if ((codep[-1] & 0xc0) != 0xc0)
860*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('l');
861*7304104dSAndroid Build Coastguard Worker break;
862*7304104dSAndroid Build Coastguard Worker
863*7304104dSAndroid Build Coastguard Worker case suffix_w1:
864*7304104dSAndroid Build Coastguard Worker if ((data[0] & 0x4) == 0)
865*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('l');
866*7304104dSAndroid Build Coastguard Worker break;
867*7304104dSAndroid Build Coastguard Worker
868*7304104dSAndroid Build Coastguard Worker case suffix_W:
869*7304104dSAndroid Build Coastguard Worker if (prefixes & has_data16)
870*7304104dSAndroid Build Coastguard Worker {
871*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('w');
872*7304104dSAndroid Build Coastguard Worker prefixes &= ~has_data16;
873*7304104dSAndroid Build Coastguard Worker }
874*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
875*7304104dSAndroid Build Coastguard Worker else
876*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('q');
877*7304104dSAndroid Build Coastguard Worker #endif
878*7304104dSAndroid Build Coastguard Worker break;
879*7304104dSAndroid Build Coastguard Worker
880*7304104dSAndroid Build Coastguard Worker case suffix_W1:
881*7304104dSAndroid Build Coastguard Worker if (prefixes & has_data16)
882*7304104dSAndroid Build Coastguard Worker {
883*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('w');
884*7304104dSAndroid Build Coastguard Worker prefixes &= ~has_data16;
885*7304104dSAndroid Build Coastguard Worker }
886*7304104dSAndroid Build Coastguard Worker #ifdef X86_64
887*7304104dSAndroid Build Coastguard Worker else if (prefixes & has_rex_w)
888*7304104dSAndroid Build Coastguard Worker ADD_CHAR ('q');
889*7304104dSAndroid Build Coastguard Worker #endif
890*7304104dSAndroid Build Coastguard Worker break;
891*7304104dSAndroid Build Coastguard Worker
892*7304104dSAndroid Build Coastguard Worker case suffix_tttn:;
893*7304104dSAndroid Build Coastguard Worker static const char tttn[16][3] =
894*7304104dSAndroid Build Coastguard Worker {
895*7304104dSAndroid Build Coastguard Worker "o", "no", "b", "ae", "e", "ne", "be", "a",
896*7304104dSAndroid Build Coastguard Worker "s", "ns", "p", "np", "l", "ge", "le", "g"
897*7304104dSAndroid Build Coastguard Worker };
898*7304104dSAndroid Build Coastguard Worker ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
899*7304104dSAndroid Build Coastguard Worker break;
900*7304104dSAndroid Build Coastguard Worker
901*7304104dSAndroid Build Coastguard Worker case suffix_D:
902*7304104dSAndroid Build Coastguard Worker if ((codep[-1] & 0xc0) != 0xc0)
903*7304104dSAndroid Build Coastguard Worker ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
904*7304104dSAndroid Build Coastguard Worker break;
905*7304104dSAndroid Build Coastguard Worker
906*7304104dSAndroid Build Coastguard Worker default:
907*7304104dSAndroid Build Coastguard Worker printf("unknown suffix %d\n", instrtab[cnt].suffix);
908*7304104dSAndroid Build Coastguard Worker abort ();
909*7304104dSAndroid Build Coastguard Worker }
910*7304104dSAndroid Build Coastguard Worker
911*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
912*7304104dSAndroid Build Coastguard Worker {
913*7304104dSAndroid Build Coastguard Worker ADD_STRING (color_off);
914*7304104dSAndroid Build Coastguard Worker non_printing += strlen (color_off);
915*7304104dSAndroid Build Coastguard Worker }
916*7304104dSAndroid Build Coastguard Worker
917*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
918*7304104dSAndroid Build Coastguard Worker break;
919*7304104dSAndroid Build Coastguard Worker
920*7304104dSAndroid Build Coastguard Worker case 'o':
921*7304104dSAndroid Build Coastguard Worker if (prec == 1 && instrtab[cnt].fct1 != 0)
922*7304104dSAndroid Build Coastguard Worker {
923*7304104dSAndroid Build Coastguard Worker /* First parameter. */
924*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
925*7304104dSAndroid Build Coastguard Worker {
926*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (deferred_start, deferred_len);
927*7304104dSAndroid Build Coastguard Worker non_printing += deferred_len;
928*7304104dSAndroid Build Coastguard Worker }
929*7304104dSAndroid Build Coastguard Worker
930*7304104dSAndroid Build Coastguard Worker if (instrtab[cnt].str1 != 0)
931*7304104dSAndroid Build Coastguard Worker ADD_STRING (op1_str
932*7304104dSAndroid Build Coastguard Worker + op1_str_idx[instrtab[cnt].str1 - 1]);
933*7304104dSAndroid Build Coastguard Worker
934*7304104dSAndroid Build Coastguard Worker output_data.opoff1 = (instrtab[cnt].off1_1
935*7304104dSAndroid Build Coastguard Worker + OFF1_1_BIAS - opoff);
936*7304104dSAndroid Build Coastguard Worker output_data.opoff2 = (instrtab[cnt].off1_2
937*7304104dSAndroid Build Coastguard Worker + OFF1_2_BIAS - opoff);
938*7304104dSAndroid Build Coastguard Worker output_data.opoff3 = (instrtab[cnt].off1_3
939*7304104dSAndroid Build Coastguard Worker + OFF1_3_BIAS - opoff);
940*7304104dSAndroid Build Coastguard Worker int r = op1_fct[instrtab[cnt].fct1] (&output_data);
941*7304104dSAndroid Build Coastguard Worker if (r < 0)
942*7304104dSAndroid Build Coastguard Worker goto not;
943*7304104dSAndroid Build Coastguard Worker if (r > 0)
944*7304104dSAndroid Build Coastguard Worker goto enomem;
945*7304104dSAndroid Build Coastguard Worker
946*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
947*7304104dSAndroid Build Coastguard Worker {
948*7304104dSAndroid Build Coastguard Worker ADD_STRING (color_off);
949*7304104dSAndroid Build Coastguard Worker non_printing += strlen (color_off);
950*7304104dSAndroid Build Coastguard Worker }
951*7304104dSAndroid Build Coastguard Worker
952*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
953*7304104dSAndroid Build Coastguard Worker }
954*7304104dSAndroid Build Coastguard Worker else if (prec == 2 && instrtab[cnt].fct2 != 0)
955*7304104dSAndroid Build Coastguard Worker {
956*7304104dSAndroid Build Coastguard Worker /* Second parameter. */
957*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
958*7304104dSAndroid Build Coastguard Worker {
959*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (deferred_start, deferred_len);
960*7304104dSAndroid Build Coastguard Worker non_printing += deferred_len;
961*7304104dSAndroid Build Coastguard Worker }
962*7304104dSAndroid Build Coastguard Worker
963*7304104dSAndroid Build Coastguard Worker if (instrtab[cnt].str2 != 0)
964*7304104dSAndroid Build Coastguard Worker ADD_STRING (op2_str
965*7304104dSAndroid Build Coastguard Worker + op2_str_idx[instrtab[cnt].str2 - 1]);
966*7304104dSAndroid Build Coastguard Worker
967*7304104dSAndroid Build Coastguard Worker output_data.opoff1 = (instrtab[cnt].off2_1
968*7304104dSAndroid Build Coastguard Worker + OFF2_1_BIAS - opoff);
969*7304104dSAndroid Build Coastguard Worker output_data.opoff2 = (instrtab[cnt].off2_2
970*7304104dSAndroid Build Coastguard Worker + OFF2_2_BIAS - opoff);
971*7304104dSAndroid Build Coastguard Worker output_data.opoff3 = (instrtab[cnt].off2_3
972*7304104dSAndroid Build Coastguard Worker + OFF2_3_BIAS - opoff);
973*7304104dSAndroid Build Coastguard Worker int r = op2_fct[instrtab[cnt].fct2] (&output_data);
974*7304104dSAndroid Build Coastguard Worker if (r < 0)
975*7304104dSAndroid Build Coastguard Worker goto not;
976*7304104dSAndroid Build Coastguard Worker if (r > 0)
977*7304104dSAndroid Build Coastguard Worker goto enomem;
978*7304104dSAndroid Build Coastguard Worker
979*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
980*7304104dSAndroid Build Coastguard Worker {
981*7304104dSAndroid Build Coastguard Worker ADD_STRING (color_off);
982*7304104dSAndroid Build Coastguard Worker non_printing += strlen (color_off);
983*7304104dSAndroid Build Coastguard Worker }
984*7304104dSAndroid Build Coastguard Worker
985*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
986*7304104dSAndroid Build Coastguard Worker }
987*7304104dSAndroid Build Coastguard Worker else if (prec == 3 && instrtab[cnt].fct3 != 0)
988*7304104dSAndroid Build Coastguard Worker {
989*7304104dSAndroid Build Coastguard Worker /* Third parameter. */
990*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
991*7304104dSAndroid Build Coastguard Worker {
992*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (deferred_start, deferred_len);
993*7304104dSAndroid Build Coastguard Worker non_printing += deferred_len;
994*7304104dSAndroid Build Coastguard Worker }
995*7304104dSAndroid Build Coastguard Worker
996*7304104dSAndroid Build Coastguard Worker if (instrtab[cnt].str3 != 0)
997*7304104dSAndroid Build Coastguard Worker ADD_STRING (op3_str
998*7304104dSAndroid Build Coastguard Worker + op3_str_idx[instrtab[cnt].str3 - 1]);
999*7304104dSAndroid Build Coastguard Worker
1000*7304104dSAndroid Build Coastguard Worker output_data.opoff1 = (instrtab[cnt].off3_1
1001*7304104dSAndroid Build Coastguard Worker + OFF3_1_BIAS - opoff);
1002*7304104dSAndroid Build Coastguard Worker output_data.opoff2 = (instrtab[cnt].off3_2
1003*7304104dSAndroid Build Coastguard Worker + OFF3_2_BIAS - opoff);
1004*7304104dSAndroid Build Coastguard Worker #ifdef OFF3_3_BITS
1005*7304104dSAndroid Build Coastguard Worker output_data.opoff3 = (instrtab[cnt].off3_3
1006*7304104dSAndroid Build Coastguard Worker + OFF3_3_BIAS - opoff);
1007*7304104dSAndroid Build Coastguard Worker #else
1008*7304104dSAndroid Build Coastguard Worker output_data.opoff3 = 0;
1009*7304104dSAndroid Build Coastguard Worker #endif
1010*7304104dSAndroid Build Coastguard Worker int r = op3_fct[instrtab[cnt].fct3] (&output_data);
1011*7304104dSAndroid Build Coastguard Worker if (r < 0)
1012*7304104dSAndroid Build Coastguard Worker goto not;
1013*7304104dSAndroid Build Coastguard Worker if (r > 0)
1014*7304104dSAndroid Build Coastguard Worker goto enomem;
1015*7304104dSAndroid Build Coastguard Worker
1016*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
1017*7304104dSAndroid Build Coastguard Worker {
1018*7304104dSAndroid Build Coastguard Worker ADD_STRING (color_off);
1019*7304104dSAndroid Build Coastguard Worker non_printing += strlen (color_off);
1020*7304104dSAndroid Build Coastguard Worker }
1021*7304104dSAndroid Build Coastguard Worker
1022*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
1023*7304104dSAndroid Build Coastguard Worker }
1024*7304104dSAndroid Build Coastguard Worker else
1025*7304104dSAndroid Build Coastguard Worker start_idx = bufcnt = string_end_idx;
1026*7304104dSAndroid Build Coastguard Worker break;
1027*7304104dSAndroid Build Coastguard Worker
1028*7304104dSAndroid Build Coastguard Worker case 'e':
1029*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
1030*7304104dSAndroid Build Coastguard Worker break;
1031*7304104dSAndroid Build Coastguard Worker
1032*7304104dSAndroid Build Coastguard Worker case 'a':
1033*7304104dSAndroid Build Coastguard Worker /* Pad to requested column. */
1034*7304104dSAndroid Build Coastguard Worker while (bufcnt - non_printing < (size_t) width)
1035*7304104dSAndroid Build Coastguard Worker ADD_CHAR (' ');
1036*7304104dSAndroid Build Coastguard Worker width = 0;
1037*7304104dSAndroid Build Coastguard Worker break;
1038*7304104dSAndroid Build Coastguard Worker
1039*7304104dSAndroid Build Coastguard Worker case 'l':
1040*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
1041*7304104dSAndroid Build Coastguard Worker {
1042*7304104dSAndroid Build Coastguard Worker ADD_NSTRING (deferred_start, deferred_len);
1043*7304104dSAndroid Build Coastguard Worker non_printing += deferred_len;
1044*7304104dSAndroid Build Coastguard Worker }
1045*7304104dSAndroid Build Coastguard Worker
1046*7304104dSAndroid Build Coastguard Worker if (output_data.labelbuf != NULL
1047*7304104dSAndroid Build Coastguard Worker && output_data.labelbuf[0] != '\0')
1048*7304104dSAndroid Build Coastguard Worker {
1049*7304104dSAndroid Build Coastguard Worker ADD_STRING (output_data.labelbuf);
1050*7304104dSAndroid Build Coastguard Worker output_data.labelbuf[0] = '\0';
1051*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
1052*7304104dSAndroid Build Coastguard Worker }
1053*7304104dSAndroid Build Coastguard Worker else if (output_data.symaddr_use != addr_none)
1054*7304104dSAndroid Build Coastguard Worker {
1055*7304104dSAndroid Build Coastguard Worker GElf_Addr symaddr = output_data.symaddr;
1056*7304104dSAndroid Build Coastguard Worker if (output_data.symaddr_use >= addr_rel_symbolic)
1057*7304104dSAndroid Build Coastguard Worker symaddr += addr + param_start - begin;
1058*7304104dSAndroid Build Coastguard Worker
1059*7304104dSAndroid Build Coastguard Worker // XXX Lookup symbol based on symaddr
1060*7304104dSAndroid Build Coastguard Worker const char *symstr = NULL;
1061*7304104dSAndroid Build Coastguard Worker if (symcb != NULL
1062*7304104dSAndroid Build Coastguard Worker && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
1063*7304104dSAndroid Build Coastguard Worker &output_data.labelbuf,
1064*7304104dSAndroid Build Coastguard Worker &output_data.labelbufsize, symcbarg) == 0)
1065*7304104dSAndroid Build Coastguard Worker symstr = output_data.labelbuf;
1066*7304104dSAndroid Build Coastguard Worker
1067*7304104dSAndroid Build Coastguard Worker size_t bufavail = bufsize - bufcnt;
1068*7304104dSAndroid Build Coastguard Worker int r = 0;
1069*7304104dSAndroid Build Coastguard Worker if (symstr != NULL)
1070*7304104dSAndroid Build Coastguard Worker r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
1071*7304104dSAndroid Build Coastguard Worker symstr);
1072*7304104dSAndroid Build Coastguard Worker else if (output_data.symaddr_use == addr_abs_always
1073*7304104dSAndroid Build Coastguard Worker || output_data.symaddr_use == addr_rel_always)
1074*7304104dSAndroid Build Coastguard Worker r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
1075*7304104dSAndroid Build Coastguard Worker (uint64_t) symaddr);
1076*7304104dSAndroid Build Coastguard Worker
1077*7304104dSAndroid Build Coastguard Worker assert (r >= 0);
1078*7304104dSAndroid Build Coastguard Worker if ((size_t) r >= bufavail)
1079*7304104dSAndroid Build Coastguard Worker goto enomem;
1080*7304104dSAndroid Build Coastguard Worker bufcnt += r;
1081*7304104dSAndroid Build Coastguard Worker string_end_idx = bufcnt;
1082*7304104dSAndroid Build Coastguard Worker
1083*7304104dSAndroid Build Coastguard Worker output_data.symaddr_use = addr_none;
1084*7304104dSAndroid Build Coastguard Worker }
1085*7304104dSAndroid Build Coastguard Worker if (deferred_start != NULL)
1086*7304104dSAndroid Build Coastguard Worker {
1087*7304104dSAndroid Build Coastguard Worker ADD_STRING (color_off);
1088*7304104dSAndroid Build Coastguard Worker non_printing += strlen (color_off);
1089*7304104dSAndroid Build Coastguard Worker }
1090*7304104dSAndroid Build Coastguard Worker break;
1091*7304104dSAndroid Build Coastguard Worker
1092*7304104dSAndroid Build Coastguard Worker default:
1093*7304104dSAndroid Build Coastguard Worker abort ();
1094*7304104dSAndroid Build Coastguard Worker }
1095*7304104dSAndroid Build Coastguard Worker
1096*7304104dSAndroid Build Coastguard Worker deferred_start = NULL;
1097*7304104dSAndroid Build Coastguard Worker
1098*7304104dSAndroid Build Coastguard Worker /* Pad according to the specified width. */
1099*7304104dSAndroid Build Coastguard Worker while (bufcnt + prefix_size - non_printing < start_idx + width)
1100*7304104dSAndroid Build Coastguard Worker ADD_CHAR (' ');
1101*7304104dSAndroid Build Coastguard Worker prefix_size = 0;
1102*7304104dSAndroid Build Coastguard Worker }
1103*7304104dSAndroid Build Coastguard Worker
1104*7304104dSAndroid Build Coastguard Worker if ((prefixes & SEGMENT_PREFIXES) != 0)
1105*7304104dSAndroid Build Coastguard Worker goto print_prefix;
1106*7304104dSAndroid Build Coastguard Worker
1107*7304104dSAndroid Build Coastguard Worker assert (string_end_idx != ~0ul);
1108*7304104dSAndroid Build Coastguard Worker bufcnt = string_end_idx;
1109*7304104dSAndroid Build Coastguard Worker
1110*7304104dSAndroid Build Coastguard Worker addr += param_start - begin;
1111*7304104dSAndroid Build Coastguard Worker data = param_start;
1112*7304104dSAndroid Build Coastguard Worker
1113*7304104dSAndroid Build Coastguard Worker goto out;
1114*7304104dSAndroid Build Coastguard Worker }
1115*7304104dSAndroid Build Coastguard Worker
1116*7304104dSAndroid Build Coastguard Worker /* Invalid (or at least unhandled) opcode. */
1117*7304104dSAndroid Build Coastguard Worker invalid_op:
1118*7304104dSAndroid Build Coastguard Worker if (prefixes != 0)
1119*7304104dSAndroid Build Coastguard Worker goto print_prefix;
1120*7304104dSAndroid Build Coastguard Worker /* Make sure we get past the unrecognized opcode if we haven't yet. */
1121*7304104dSAndroid Build Coastguard Worker if (*startp == data)
1122*7304104dSAndroid Build Coastguard Worker ++data;
1123*7304104dSAndroid Build Coastguard Worker ADD_STRING ("(bad)");
1124*7304104dSAndroid Build Coastguard Worker addr += data - begin;
1125*7304104dSAndroid Build Coastguard Worker
1126*7304104dSAndroid Build Coastguard Worker out:
1127*7304104dSAndroid Build Coastguard Worker if (bufcnt == bufsize)
1128*7304104dSAndroid Build Coastguard Worker goto enomem;
1129*7304104dSAndroid Build Coastguard Worker buf[bufcnt] = '\0';
1130*7304104dSAndroid Build Coastguard Worker
1131*7304104dSAndroid Build Coastguard Worker *startp = data;
1132*7304104dSAndroid Build Coastguard Worker retval = outcb (buf, bufcnt, outcbarg);
1133*7304104dSAndroid Build Coastguard Worker if (retval != 0)
1134*7304104dSAndroid Build Coastguard Worker goto do_ret;
1135*7304104dSAndroid Build Coastguard Worker }
1136*7304104dSAndroid Build Coastguard Worker
1137*7304104dSAndroid Build Coastguard Worker do_ret:
1138*7304104dSAndroid Build Coastguard Worker free (output_data.labelbuf);
1139*7304104dSAndroid Build Coastguard Worker if (buf != initbuf)
1140*7304104dSAndroid Build Coastguard Worker free (buf);
1141*7304104dSAndroid Build Coastguard Worker
1142*7304104dSAndroid Build Coastguard Worker return retval;
1143*7304104dSAndroid Build Coastguard Worker }
1144