1 /*BEGIN_LEGAL
2
3 Copyright (c) 2018 Intel Corporation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 END_LEGAL */
18 /// @file xed-disas.c
19
20
21 ////////////////////////////////////////////////////////////////////////////
22 #include "xed-internal-header.h"
23 #include "xed-decoded-inst.h"
24 #include "xed-decoded-inst-api.h"
25 #include "xed-decoded-inst-private.h"
26
27 #include "xed-disas.h"
28 #include "xed-disas-private.h"
29 #include "xed-util.h"
30 #include "xed-util-private.h"
31 #include "xed-format-options.h"
32 #include "xed-reg-class.h"
33
34 #include "xed-operand-ctype-enum.h"
35 #include "xed-operand-ctype-map.h"
36 #include "xed-init-pointer-names.h"
37 #include "xed-print-info.h"
38 #include "xed-convert-table-init.h" //generated
39 #include "xed-isa-set.h"
40 #include "xed-ild.h"
41
42 #include <string.h> // memset
43 #define XED_HEX_BUFLEN 200
44
45 int
xed_get_symbolic_disassembly(xed_print_info_t * pi,xed_uint64_t address,char * buffer,xed_uint_t buffer_length,xed_uint64_t * offset)46 xed_get_symbolic_disassembly(xed_print_info_t* pi,
47 xed_uint64_t address,
48 char* buffer,
49 xed_uint_t buffer_length,
50 xed_uint64_t* offset)
51
52 {
53 // use the common registered version of the callback if non is supplied
54 // by the user.
55 xed_disassembly_callback_fn_t fn = 0;
56 if (pi->disassembly_callback)
57 fn = pi->disassembly_callback;
58
59 if (fn) {
60 int r = (*fn)(address,
61 buffer,
62 buffer_length,
63 offset,
64 pi->context);
65 return r;
66 }
67 return 0;
68 }
69
70
71 ////////////////////////////////////////////////////
72
73
stringop_memop(const xed_decoded_inst_t * p,const xed_operand_t * o)74 static xed_bool_t stringop_memop(const xed_decoded_inst_t* p,
75 const xed_operand_t* o) {
76 xed_bool_t stringop = (xed_decoded_inst_get_category(p) ==
77 XED_CATEGORY_STRINGOP);
78 if (stringop) {
79 xed_operand_enum_t op_name = xed_operand_name(o);
80 if (op_name == XED_OPERAND_MEM0 || op_name == XED_OPERAND_MEM1)
81 return 1;
82 }
83 return 0;
84 }
85
xed_decoded_inst_explicit_memop(const xed_decoded_inst_t * p)86 static xed_bool_t xed_decoded_inst_explicit_memop(const xed_decoded_inst_t* p) {
87 const xed_inst_t* inst = p->_inst;
88 const unsigned int noperands = xed_inst_noperands(inst);
89 unsigned int i;
90 for( i=0;i<noperands;i++) {
91 const xed_operand_t* o = xed_inst_operand(inst,i);
92 switch(xed_operand_name(o)) {
93 case XED_OPERAND_MEM0:
94 case XED_OPERAND_MEM1:
95 case XED_OPERAND_AGEN:
96 if (xed_operand_operand_visibility(o) != XED_OPVIS_SUPPRESSED)
97 return 1;
98 if (stringop_memop(p,o))
99 return 1;
100 default:
101 break;
102 }
103 }
104 return 0;
105 }
106
107 static xed_bool_t
xed_decoded_inst_explicit_operand(const xed_decoded_inst_t * p)108 xed_decoded_inst_explicit_operand(const xed_decoded_inst_t* p)
109 {
110 const xed_inst_t* inst = p->_inst;
111 const unsigned int noperands = xed_inst_noperands(inst);
112 unsigned int i;
113 for( i=0;i<noperands;i++) {
114 const xed_operand_t* o = xed_inst_operand(inst,i);
115 if (xed_operand_operand_visibility(o) == XED_OPVIS_SUPPRESSED) {
116 /* we print stringop memops so no need to print the 66/67 prefixes */
117 if (stringop_memop(p,o))
118 return 1;
119 continue;
120 }
121
122 return 1;
123 }
124 return 0;
125 }
126
127
128 void
xed_decoded_inst_dump(const xed_decoded_inst_t * p,char * buf,int buflen)129 xed_decoded_inst_dump(const xed_decoded_inst_t* p, char* buf, int buflen)
130 {
131 char ibuf[XED_HEX_BUFLEN];
132 unsigned int i;
133 const xed_inst_t* xi = xed_decoded_inst_inst(p);
134 unsigned int noperands;
135 xed_bool_t okay;
136 char* t=buf;
137 int blen = buflen;
138 if (!xi) {
139 (void) xed_strncpy(buf,"NOT DECODED YET", blen);
140 return;
141 }
142 blen = xed_strncpy(t,
143 xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(p)),
144 blen);
145 blen = xed_strncat(t, " ",blen);
146 blen = xed_strncat(t,
147 xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(p)),
148 blen);
149
150 blen = xed_strncat(t, " ",blen);
151
152 t = buf + xed_strlen(buf);
153 xed_operand_values_print_short( xed_decoded_inst_operands_const(p), t, blen);
154 blen = buflen - xed_strlen(buf);
155
156 blen = xed_strncat(buf,"\n",blen);
157 noperands = xed_inst_noperands(xi);
158 for( i=0;i<noperands;i++) {
159 const xed_operand_t* op;
160 t = buf+xed_strlen(buf);
161 op = xed_inst_operand(xi,i);
162 blen = xed_itoa(t,i,blen);
163 blen = xed_strncat(buf,"\t\t",blen);
164 xed_operand_print(op,buf+xed_strlen(buf),blen);
165 blen = buflen - xed_strlen(buf);
166 blen = xed_strncat(buf,"\n",blen);
167 }
168
169 okay = xed_format_context(XED_SYNTAX_INTEL,
170 p,ibuf,sizeof(ibuf),0,0,0);
171 if (okay) {
172 blen = xed_strncat(buf,"YDIS: ",blen);
173 (void) xed_strncat(buf,ibuf,blen);
174 }
175 }
176
177
178 xed_bool_t
xed_decoded_inst_dump_xed_format(const xed_decoded_inst_t * p,char * buf,int buflen,xed_uint64_t runtime_address)179 xed_decoded_inst_dump_xed_format(const xed_decoded_inst_t* p,
180 char* buf,
181 int buflen,
182 xed_uint64_t runtime_address)
183 {
184 const xed_inst_t* xi = xed_decoded_inst_inst(p);
185 char* s;
186 const xed_operand_values_t* co = xed_decoded_inst_operands_const(p);
187 int blen = buflen;
188 if (!xi)
189 return 0;
190 if (blen < 16)
191 return 0;
192 blen = xed_strncpy(buf, xed_iclass_enum_t2str(xed_inst_iclass(xi)),blen);
193
194 // Find the end of the buffer so that we can put the disassembly in it.
195 blen = xed_strncat(buf, " ", blen);
196 s = buf + xed_strlen(buf);
197 xed_operand_values_print_short(co,s,blen);
198 return 1;
199 (void) runtime_address;
200 }
201
xed_decoded_inst_print_ptr_size(xed_uint_t bytes)202 static const char* xed_decoded_inst_print_ptr_size(xed_uint_t bytes) {
203 extern const char* xed_pointer_name[XED_MAX_POINTER_NAMES];
204 if (bytes < XED_MAX_POINTER_NAMES)
205 if (xed_pointer_name[bytes])
206 return xed_pointer_name[bytes];
207 return "";
208 }
209
instruction_suffix_att(const xed_decoded_inst_t * p)210 static const char* instruction_suffix_att(const xed_decoded_inst_t* p) {
211 extern const char* xed_pointer_name_suffix[XED_MAX_POINTER_NAMES];
212 if (xed_decoded_inst_number_of_memory_operands(p)) {
213 xed_uint_t bytes = xed_decoded_inst_get_memory_operand_length(p,0);
214 if (bytes < XED_MAX_POINTER_NAMES)
215 if (xed_pointer_name_suffix[bytes])
216 return xed_pointer_name_suffix[bytes];
217 }
218 return 0;
219 }
220
221 static xed_format_options_t xed_format_options = {
222 1, /* symblic names with hex address */
223 0, /* xml_a */
224 0, /* xml_f flags */
225 0, /* omit scale */
226 0, /* no_sign_extend_signed_immediates */
227 1, /* writemask with curly brackets, omit k0 */
228 1, /* lowercase hexadecimal */
229 };
230
xed_format_set_options(xed_format_options_t format_options)231 void xed_format_set_options(xed_format_options_t format_options) {
232 xed_format_options = format_options;
233 }
234
235
236 static int
xml_print_flags(const xed_decoded_inst_t * xedd,char * buf,int blen)237 xml_print_flags(const xed_decoded_inst_t* xedd, char* buf, int blen)
238 {
239 if (xed_decoded_inst_uses_rflags(xedd)) {
240 // KW complains because it thinks rfi could be null.
241 // Cannot happen by design.
242 const xed_simple_flag_t* rfi = xed_decoded_inst_get_rflags_info(xedd);
243 unsigned int nflags = xed_simple_flag_get_nflags(rfi);
244 unsigned int i;
245 blen = xed_strncat(buf,"<FLAGS>",blen);
246 for( i=0;i<nflags ;i++) {
247 char tbuf[XED_HEX_BUFLEN];
248 const xed_flag_action_t* fa = xed_simple_flag_get_flag_action(rfi,i);
249 if (i>0)
250 blen = xed_strncat(buf, " ",blen);
251 (void) xed_flag_action_print(fa,tbuf,XED_HEX_BUFLEN);
252 blen = xed_strncat(buf, tbuf,blen);
253
254 }
255 blen = xed_strncat(buf,"</FLAGS>",blen);
256 }
257 return blen;
258 }
259
260
261
262
xed_pi_strcat(xed_print_info_t * pi,char const * str)263 static void xed_pi_strcat(xed_print_info_t* pi,
264 char const* str)
265 {
266 pi->blen = xed_strncat(pi->buf, str, pi->blen);
267 }
268
269
270
xed_prefixes(xed_print_info_t * pi,char const * prefix)271 static void xed_prefixes(xed_print_info_t* pi,
272 char const* prefix)
273 {
274 if (pi->emitted == 0 && pi->format_options.xml_a)
275 xed_pi_strcat(pi,"<PREFIXES>");
276 if (pi->emitted)
277 xed_pi_strcat(pi," ");
278 xed_pi_strcat(pi,prefix);
279 pi->emitted=1;
280 }
281
282 static void
xml_print_end(xed_print_info_t * pi,char const * s)283 xml_print_end(xed_print_info_t* pi,
284 char const* s)
285 {
286 if (pi->format_options.xml_a) {
287 xed_pi_strcat(pi,"</");
288 xed_pi_strcat(pi,s);
289 xed_pi_strcat(pi,">");
290 }
291 }
292
293 static void
xed_decoded_inst_dump_common(xed_print_info_t * pi)294 xed_decoded_inst_dump_common(xed_print_info_t* pi)
295 {
296 const xed_operand_values_t* ov = xed_decoded_inst_operands_const(pi->p);
297
298 int long_mode = xed_operand_values_get_long_mode(ov);
299 const xed_uint32_t dmode = xed_decoded_inst_get_machine_mode_bits(pi->p);
300 int dmode16 = (dmode == 16);
301 int dmode32 = (dmode == 32);
302
303 if (xed_decoded_inst_has_mpx_prefix(pi->p))
304 xed_prefixes(pi,"bnd");
305 if (xed_decoded_inst_is_xacquire(pi->p))
306 xed_prefixes(pi,"xacquire");
307 if (xed_decoded_inst_is_xrelease(pi->p))
308 xed_prefixes(pi,"xrelease");
309 if (xed_operand_values_has_lock_prefix(ov))
310 xed_prefixes(pi,"lock");
311 if (xed_operand_values_has_real_rep(ov)) {
312 if (xed_operand_values_has_rep_prefix(ov))
313 xed_prefixes(pi,"rep");
314 if (xed_operand_values_has_repne_prefix(ov))
315 xed_prefixes(pi,"repne");
316 }
317 else if (xed_operand_values_branch_not_taken_hint(ov))
318 xed_prefixes(pi,"hint-not-taken");
319 else if (xed_operand_values_branch_taken_hint(ov))
320 xed_prefixes(pi,"hint-taken");
321
322 if (xed_operand_values_has_address_size_prefix(ov)) {
323 if (xed_decoded_inst_explicit_memop(pi->p) == 0) {
324 if (long_mode || dmode16)
325 xed_prefixes(pi,"addr32");
326 else
327 xed_prefixes(pi,"addr16");
328 }
329 }
330 if (xed_operand_values_has_operand_size_prefix(ov)) {
331 if (xed_decoded_inst_explicit_operand(pi->p) == 0) {
332 if (long_mode || dmode32)
333 xed_prefixes(pi,"data16");
334 else
335 xed_prefixes(pi,"data32");
336 }
337 }
338 if (pi->emitted)
339 xml_print_end(pi,"PREFIXES");
340 if (pi->emitted)
341 xed_pi_strcat(pi," ");
342
343 // reset the spacing-is-required indicator after handling prefixes
344 pi->emitted = 0;
345 }
346
347
instruction_name_att(const xed_decoded_inst_t * p)348 static const char* instruction_name_att(const xed_decoded_inst_t* p)
349
350 {
351 xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(p);
352 return xed_iform_to_iclass_string_att(iform);
353 }
354
instruction_name_intel(const xed_decoded_inst_t * p)355 static const char* instruction_name_intel(const xed_decoded_inst_t* p)
356 {
357 xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(p);
358 return xed_iform_to_iclass_string_intel(iform);
359 }
360
361
362 ///////////////////////////////////////////////////////////////////////////////
xed_print_cvt(const xed_decoded_inst_t * p,char * buf,int blen,xed_operand_convert_enum_t cvt)363 static int xed_print_cvt(const xed_decoded_inst_t* p,
364 char* buf,
365 int blen,
366 xed_operand_convert_enum_t cvt) {
367 // 32bit var is enough since the only operand wider than 32b disp/imm
368 // and we are not decorating those
369 xed_uint_t opvalue;
370 xed_operand_enum_t index_operand = xed_convert_table[cvt].opnd;
371 xed3_get_generic_operand(p,index_operand,&opvalue);
372 if (opvalue < xed_convert_table[cvt].limit) {
373 const char* s = xed_convert_table[cvt].table_name[ opvalue ];
374 blen = xed_strncat(buf,s,blen);
375 }
376 else
377 blen = xed_strncat(buf,"BADCVT",blen);
378 return blen;
379 }
380
xml_tag(char * buf,int blen,char const * tag,xed_uint_t value)381 static int xml_tag(char* buf, int blen, char const* tag, xed_uint_t value) {
382 char tbuf[XED_HEX_BUFLEN];
383
384 blen = xed_strncat(buf,"<",blen);
385 blen = xed_strncat(buf,tag,blen);
386 blen = xed_strncat(buf," bits=\"",blen);
387
388 xed_sprintf_uint32(tbuf, value, XED_HEX_BUFLEN);
389 blen = xed_strncat(buf,tbuf,blen);
390
391 blen = xed_strncat(buf,"\">",blen);
392 return blen;
393 }
394
xml_tag_pi(xed_print_info_t * pi,char const * tag,xed_uint_t value)395 static void xml_tag_pi(xed_print_info_t* pi,
396 char const* tag,
397 xed_uint_t value)
398 {
399 pi->blen = xml_tag(pi->buf, pi->blen, tag, value);
400 }
401
402
xed_operand_spacer(xed_print_info_t * pi)403 static void xed_operand_spacer(xed_print_info_t* pi) {
404 if (pi->emitted) {
405 pi->blen = xed_strncat(pi->buf,", ",pi->blen);
406 }
407 }
408
409
print_seg_prefix_for_suppressed_operands(xed_print_info_t * pi,const xed_operand_values_t * ov,const xed_operand_t * op)410 static void print_seg_prefix_for_suppressed_operands(
411 xed_print_info_t* pi,
412 const xed_operand_values_t* ov,
413 const xed_operand_t* op)
414 {
415 int i;
416 xed_operand_enum_t op_name = xed_operand_name(op);
417 /* suppressed memops with nondefault segments get their segment printed */
418 const xed_operand_enum_t names[] = { XED_OPERAND_MEM0,XED_OPERAND_MEM1};
419 for(i=0;i<2;i++) {
420 if (op_name == names[i]) {
421 xed_reg_enum_t seg = XED_REG_INVALID;
422 switch(i) {
423 case 0: seg = xed3_operand_get_seg0(ov); break;
424 case 1: seg = xed3_operand_get_seg1(ov); break;
425 }
426 if (seg != XED_REG_INVALID &&
427 xed_operand_values_using_default_segment(ov, i) == 0) {
428 xed_operand_spacer(pi);
429 if (pi->format_options.xml_a)
430 xed_pi_strcat(pi,"<OPERAND><REG bits=\"16\">");
431 pi->blen = xed_strncat_lower(pi->buf,
432 xed_reg_enum_t2str(seg),
433 pi->blen);
434 xml_print_end(pi,"REG");
435 xml_print_end(pi,"OPERAND");
436 pi->emitted = 1;
437 }
438 }
439 }
440 }
441
442 static void
xed_print_operand_decorations(xed_print_info_t * pi,xed_operand_t const * const op)443 xed_print_operand_decorations(
444 xed_print_info_t* pi,
445 xed_operand_t const* const op)
446 {
447 xed_uint32_t cvt_idx = op->_cvt_idx;
448
449 if (cvt_idx && cvt_idx < XED_MAX_CONVERT_PATTERNS) {
450 int i;
451 for( i=0; i<XED_MAX_DECORATIONS_PER_OPERAND; i++ ) {
452 xed_operand_convert_enum_t v = xed_operand_convert[cvt_idx][i];
453 if (v == XED_OPERAND_CONVERT_INVALID)
454 break;
455 pi->blen = xed_print_cvt(pi->p, pi->buf, pi->blen, v);
456 }
457 }
458 }
459
460
461 static void
xml_reg_prefix(xed_print_info_t * pi,xed_reg_enum_t reg)462 xml_reg_prefix(xed_print_info_t* pi, xed_reg_enum_t reg)
463 {
464 if (pi->format_options.xml_a)
465 xml_tag_pi(pi,
466 "REG",
467 xed_get_register_width_bits(reg));
468 }
469
470 static void
print_reg(xed_print_info_t * pi,xed_reg_enum_t reg)471 print_reg(xed_print_info_t* pi,
472 xed_reg_enum_t reg)
473 {
474 char const* s;
475
476 if (pi->syntax == XED_SYNTAX_ATT)
477 xed_pi_strcat(pi,"%");
478
479 if (reg == XED_REG_ST0 && pi->implicit)
480 s = "st";
481 else
482 s = xed_reg_enum_t2str(reg);
483
484 pi->blen = xed_strncat_lower(pi->buf, s, pi->blen);
485 }
486
487 static void
print_reg_xml(xed_print_info_t * pi,xed_reg_enum_t reg)488 print_reg_xml(xed_print_info_t* pi,
489 xed_reg_enum_t reg)
490 {
491 xml_reg_prefix(pi,reg);
492 print_reg(pi,reg);
493 xml_print_end(pi,"REG");
494 }
495
496
497 #if defined(XED_SUPPORTS_AVX512)
498 static xed_uint_t
operand_is_writemask(xed_operand_t const * const op)499 operand_is_writemask(
500 xed_operand_t const* const op)
501 {
502
503 xed_operand_enum_t op_name = xed_operand_name(op);
504 // for memops dests, writemask is REG0.
505 // for reg-dest instr, writemask is REG1.
506 if (op_name == XED_OPERAND_REG1 || op_name == XED_OPERAND_REG0)
507 if (xed_operand_nonterminal_name(op) == XED_NONTERMINAL_MASK1)
508 return 1;
509
510 return 0;
511 }
512
513 static void
print_decoration(xed_print_info_t * pi,xed_uint_t indx)514 print_decoration(xed_print_info_t* pi,
515 xed_uint_t indx)
516 {
517 xed_inst_t const* xi = xed_decoded_inst_inst(pi->p);
518 xed_operand_t const* const kop = xed_inst_operand(xi,indx);
519 xed_print_operand_decorations(pi, kop);
520 }
521
522
523
524 static xed_reg_enum_t
printing_writemasked_operand(xed_print_info_t * pi)525 printing_writemasked_operand(
526 xed_print_info_t* pi)
527 {
528 // return XED_REG_INVALID if next operand is not a writemask
529 // else return the XED_REG_K0...K7 if it is a writemask.
530 // (We treat k0 as a write mask, but it won't get printed)
531
532 // write masked operand must be first
533 if (pi->operand_indx > 0)
534 return XED_REG_INVALID;
535 else
536 {
537 xed_inst_t const* xi = xed_decoded_inst_inst(pi->p);
538 xed_uint_t noperands = xed_inst_noperands(xi);
539
540 // we have another operand
541 xed_uint_t nxt_opnd = pi->operand_indx + 1;
542 if (nxt_opnd < noperands)
543 {
544 xed_operand_t const* const op = xed_inst_operand(xi,nxt_opnd);
545 if (operand_is_writemask(op))
546 {
547 xed_operand_enum_t op_name = xed_operand_name(op);
548 xed_reg_enum_t reg;
549 xed3_get_generic_operand(pi->p,op_name,®);
550 return reg;
551 }
552
553 }
554 }
555 return XED_REG_INVALID;
556 }
557
558 static void
print_write_mask_reg(xed_print_info_t * pi,xed_reg_enum_t writemask)559 print_write_mask_reg(
560 xed_print_info_t* pi,
561 xed_reg_enum_t writemask)
562 {
563 // print the write mask if not k0
564 if (writemask != XED_REG_K0)
565 {
566 pi->blen = xed_strncat(pi->buf,"{",pi->blen);
567 print_reg(pi,writemask);
568 pi->blen = xed_strncat(pi->buf,"}",pi->blen);
569
570 // write mask operand might have decorations. print them.
571 print_decoration(pi, pi->operand_indx + 1);
572 }
573 }
574 #endif // XED_SUPPORTS_AVX512
575
576
577 static void
print_write_mask_generic(xed_print_info_t * pi)578 print_write_mask_generic(
579 xed_print_info_t* pi)
580 {
581 #if defined(XED_SUPPORTS_AVX512)
582 if (pi->format_options.write_mask_curly_k0)
583 {
584 xed_reg_enum_t writemask;
585 writemask = printing_writemasked_operand(pi);
586 if (writemask != XED_REG_INVALID)
587 {
588 print_write_mask_reg(pi, writemask);
589 // tell operand loop to skip emitting write mask operand on
590 // next iteration (for any write mask reg, k0 or otherwise)
591 pi->skip_operand = 1;
592 }
593 }
594 #endif
595 (void) pi;
596 }
597
598
599 static void
print_reg_writemask(xed_print_info_t * pi,xed_reg_enum_t reg)600 print_reg_writemask(
601 xed_print_info_t* pi,
602 xed_reg_enum_t reg)
603 {
604 xml_reg_prefix(pi,reg);
605 print_reg(pi,reg);
606 #if defined(XED_SUPPORTS_AVX512)
607 print_write_mask_generic(pi);
608 #endif
609 xml_print_end(pi,"REG");
610 }
611
612 #define XED_SYMBOL_LEN 512
613
614 static const xed_bool_t print_address=1;
615 static const xed_bool_t no_print_address=0;
616 static const xed_bool_t branch_displacement=0;
617 static const xed_bool_t memory_displacement=1;
618
619 static void
print_rel_sym(xed_print_info_t * pi,xed_bool_t arg_print_address,xed_bool_t arg_memory_displacement)620 print_rel_sym(xed_print_info_t* pi,
621 xed_bool_t arg_print_address,
622 xed_bool_t arg_memory_displacement)
623 {
624 xed_int64_t disp;
625 xed_uint64_t instruction_length = xed_decoded_inst_get_length(pi->p);
626 xed_uint64_t pc = pi->runtime_address + instruction_length;
627 xed_uint64_t effective_addr;
628 xed_bool_t long_mode, symbolic;
629 xed_uint_t bits_to_print;
630 char symbol[XED_SYMBOL_LEN];
631 xed_uint64_t offset;
632 const xed_bool_t leading_zeros = 0;
633
634 if (arg_memory_displacement)
635 disp = xed_decoded_inst_get_memory_displacement(pi->p,0); //first memop only
636 else
637 disp = xed_decoded_inst_get_branch_displacement(pi->p);
638
639 long_mode = xed_operand_values_get_long_mode(
640 xed_decoded_inst_operands_const(pi->p));
641
642 bits_to_print = long_mode ? 8*8 :4*8;
643
644 effective_addr = (xed_uint64_t) ((xed_int64_t)pc + disp);
645
646 symbolic = xed_get_symbolic_disassembly(pi,
647 effective_addr,
648 symbol,
649 XED_SYMBOL_LEN,
650 &offset);
651
652 if (arg_print_address) // print the numeric address
653 {
654 if (symbolic==0 ||
655 pi->format_options.hex_address_before_symbolic_name)
656 {
657 xed_pi_strcat(pi,"0x");
658 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
659 effective_addr,
660 bits_to_print,
661 leading_zeros,
662 pi->blen,
663 pi->format_options.lowercase_hex);
664 }
665 }
666
667 if (symbolic)
668 {
669 if (pi->format_options.xml_a)
670 xed_pi_strcat(pi," <");
671 else
672 xed_pi_strcat(pi," <");
673
674 xed_pi_strcat(pi,symbol);
675 if (offset)
676 {
677 xed_pi_strcat(pi,"+0x");
678 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
679 offset,
680 bits_to_print,
681 leading_zeros,
682 pi->blen,
683 pi->format_options.lowercase_hex);
684 }
685 if (pi->format_options.xml_a)
686 xed_pi_strcat(pi," >");
687 else
688 xed_pi_strcat(pi,">");
689 }
690 }
691
692 static void
xml_print_imm(xed_print_info_t * pi,unsigned int bits)693 xml_print_imm(xed_print_info_t* pi,
694 unsigned int bits)
695 {
696 if (pi->format_options.xml_a)
697 xml_tag_pi(pi, "IMM", bits);
698 }
699
700 static void
print_relbr(xed_print_info_t * pi)701 print_relbr(xed_print_info_t* pi)
702 {
703 if (pi->format_options.xml_a)
704 xed_pi_strcat(pi,"<RELBR>");
705
706 print_rel_sym(pi,print_address, branch_displacement);
707
708 xml_print_end(pi,"RELBR");
709 }
710
xed_print_operand(xed_print_info_t * pi)711 static void xed_print_operand( xed_print_info_t* pi )
712 {
713 const xed_inst_t* xi = xed_decoded_inst_inst(pi->p);
714 const xed_operand_values_t* ov = xed_decoded_inst_operands_const(pi->p);
715 const xed_operand_t* op = xed_inst_operand(xi,pi->operand_indx);
716 xed_operand_enum_t op_name = xed_operand_name(op);
717 const xed_bool_t leading_zeros = 0;
718
719 if (xed_operand_operand_visibility(op) == XED_OPVIS_SUPPRESSED) {
720 if (stringop_memop(pi->p,op)) {
721 /* allow a fall through to print the memop for stringops to
722 * match dumpbin */
723 }
724 else {
725 print_seg_prefix_for_suppressed_operands(pi, ov, op);
726 return;
727 }
728 }
729
730 // for mangling name of x87 implicit operand
731 pi->implicit = (xed_operand_operand_visibility(op) == XED_OPVIS_IMPLICIT);
732
733 xed_operand_spacer(pi);
734 pi->emitted = 1;
735 if (pi->format_options.xml_a)
736 xed_pi_strcat(pi,"<OPERAND>");
737
738 switch(xed_operand_name(op)) {
739 case XED_OPERAND_AGEN:
740 case XED_OPERAND_MEM0: {
741 xed_bool_t no_base_index = 0;
742 xed_reg_enum_t base = xed3_operand_get_base0(pi->p);
743 xed_reg_enum_t seg = xed3_operand_get_seg0(pi->p);
744 xed_reg_enum_t index = xed3_operand_get_index(pi->p);
745
746 xed_int64_t disp =
747 xed_operand_values_get_memory_displacement_int64(ov);
748 unsigned int disp_bits =
749 xed_operand_values_get_memory_displacement_length_bits(ov);
750
751 xed_bits_t scale = xed3_operand_get_scale(pi->p);
752 xed_bool_t started = 0;
753 xed_uint_t bytes =
754 xed_decoded_inst_operand_length_bits(pi->p, pi->operand_indx)>>3;
755 if (pi->format_options.xml_a) {
756 if (xed_operand_name(op) == XED_OPERAND_AGEN)
757 xed_pi_strcat(pi,"<AGEN>");
758 else
759 xml_tag_pi(pi, "MEM", bytes << 3);
760 }
761
762 if (xed_operand_name(op) != XED_OPERAND_AGEN)
763 pi->blen = xed_strncat_lower(
764 pi->buf,
765 xed_decoded_inst_print_ptr_size(bytes),
766 pi->blen);
767
768 xed_pi_strcat(pi,"ptr ");
769 if (seg != XED_REG_INVALID &&
770 !xed_operand_values_using_default_segment(ov, 0))
771 {
772 if (xed_operand_name(op) != XED_OPERAND_AGEN) {
773 pi->blen = xed_strncat_lower(pi->buf,
774 xed_reg_enum_t2str(seg),
775 pi->blen);
776 pi->blen = xed_strncat(pi->buf,":",pi->blen);
777 }
778 }
779
780 xed_pi_strcat(pi,"[");
781 if (base != XED_REG_INVALID) {
782 pi->blen = xed_strncat_lower(pi->buf,
783 xed_reg_enum_t2str(base),
784 pi->blen);
785 started = 1;
786 }
787
788 if (index != XED_REG_INVALID)
789 {
790 #if defined(XED_MPX)
791 if (xed_decoded_inst_get_attribute(
792 pi->p,
793 XED_ATTRIBUTE_INDEX_REG_IS_POINTER))
794 {
795 // MPX BNDLDX/BNDSTX instr are unusual in that they use
796 // the index reg as distinct operand.
797
798 pi->extra_index_operand = index;
799 }
800 else // normal path
801 #endif
802 {
803 if (started)
804 xed_pi_strcat(pi,"+");
805 started = 1;
806 pi->blen = xed_strncat_lower(pi->buf,
807 xed_reg_enum_t2str(index),
808 pi->blen);
809
810 if (scale != 1 || pi->format_options.omit_unit_scale==0) {
811 xed_pi_strcat(pi,"*");
812 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf),
813 XED_STATIC_CAST(xed_uint_t,scale),
814 pi->blen);
815 }
816 }
817 }
818
819 no_base_index = (base == XED_REG_INVALID) &&
820 (index == XED_REG_INVALID);
821
822 if (xed_operand_values_has_memory_displacement(ov))
823 {
824 if (disp_bits && (disp || no_base_index))
825 {
826 xed_uint_t negative = (disp < 0) ? 1 : 0;
827 if (started)
828 {
829 if (negative)
830 {
831 xed_pi_strcat(pi,"-");
832 disp = - disp;
833 }
834 else
835 xed_pi_strcat(pi,"+");
836 }
837 xed_pi_strcat(pi,"0x");
838 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
839 disp,
840 disp_bits,
841 leading_zeros,
842 pi->blen,
843 pi->format_options.lowercase_hex);
844 }
845 }
846 xed_pi_strcat(pi,"]");
847
848 print_write_mask_generic(pi);
849 if (base == XED_REG_RIP && xed_operand_values_has_memory_displacement(ov))
850 print_rel_sym(pi,no_print_address, memory_displacement);
851
852 if (xed_operand_name(op) == XED_OPERAND_AGEN)
853 xml_print_end(pi,"AGEN");
854 else
855 xml_print_end(pi,"MEM");
856 break;
857 }
858
859 case XED_OPERAND_MEM1: {
860 xed_reg_enum_t base = xed3_operand_get_base1(pi->p);
861 xed_reg_enum_t seg = xed3_operand_get_seg1(pi->p);
862 xed_uint_t bytes =
863 xed_decoded_inst_operand_length_bits(pi->p, pi->operand_indx)>>3;
864
865 if (pi->format_options.xml_a)
866 xml_tag_pi(pi, "MEM", bytes << 3);
867
868 pi->blen = xed_strncat_lower(pi->buf,
869 xed_decoded_inst_print_ptr_size(bytes),
870 pi->blen);
871
872 xed_pi_strcat(pi,"ptr ");
873
874 if (seg != XED_REG_INVALID &&
875 !xed_operand_values_using_default_segment(ov, 1))
876 {
877 pi->blen = xed_strncat_lower(pi->buf,
878 xed_reg_enum_t2str(seg),
879 pi->blen);
880 xed_pi_strcat(pi,":");
881 }
882 xed_pi_strcat(pi,"[");
883 if (base != XED_REG_INVALID)
884 pi->blen = xed_strncat_lower(pi->buf,
885 xed_reg_enum_t2str(base),
886 pi->blen);
887 xed_pi_strcat(pi,"]");
888 xml_print_end(pi,"MEM");
889 break;
890 }
891 case XED_OPERAND_IMM0: {
892 if ( xed3_operand_get_imm0signed(pi->p) &&
893 pi->format_options.no_sign_extend_signed_immediates == 0 )
894 {
895 // sign-extend imm to effective operand width
896 xed_int32_t imm;
897 unsigned int eff_bits = xed_decoded_inst_get_operand_width(pi->p);
898 imm = XED_STATIC_CAST(xed_int32_t,
899 xed_operand_values_get_immediate_int64(ov));
900 xml_print_imm(pi,eff_bits);
901 xed_pi_strcat(pi,"0x");
902 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
903 imm,
904 eff_bits,
905 leading_zeros,
906 pi->blen,
907 pi->format_options.lowercase_hex);
908 }
909 else {
910 // how many bits of imm hold imm values. Sometimes we use upper bits
911 // for other things (like register specifiers)
912 unsigned int real_bits = xed_decoded_inst_operand_element_size_bits(
913 pi->p,
914 pi->operand_indx);
915
916 xed_uint64_t imm = xed_operand_values_get_immediate_uint64(ov);
917 xml_print_imm(pi, real_bits);
918 xed_pi_strcat(pi,"0x");
919 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
920 imm,
921 real_bits,
922 leading_zeros,
923 pi->blen,
924 pi->format_options.lowercase_hex);
925 }
926 xml_print_end(pi,"IMM");
927 break;
928 }
929 case XED_OPERAND_IMM1: { // The ENTER instruction
930 xed_uint64_t imm = xed3_operand_get_uimm1(pi->p);
931 xml_print_imm(pi, 8);
932 xed_pi_strcat(pi,"0x");
933 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
934 imm,
935 8,
936 leading_zeros,
937 pi->blen,
938 pi->format_options.lowercase_hex);
939 xml_print_end(pi,"IMM");
940 break;
941 }
942
943 case XED_OPERAND_PTR: {
944 unsigned int disp =(unsigned int)
945 xed_operand_values_get_branch_displacement_int32(ov);
946
947 xed_bool_t long_mode = xed_operand_values_get_long_mode(
948 xed_decoded_inst_operands_const(pi->p));
949
950 xed_uint_t bits_to_print = long_mode ? 8*8 :4*8;
951 if (pi->format_options.xml_a)
952 xed_pi_strcat(pi,"<PTR>");
953
954 xed_pi_strcat(pi,"0x");
955 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
956 disp,
957 bits_to_print,
958 leading_zeros,
959 pi->blen,
960 pi->format_options.lowercase_hex);
961 xml_print_end(pi,"PTR");
962 break;
963
964 }
965 case XED_OPERAND_RELBR:
966 print_relbr(pi);
967 break;
968
969 default: {
970 xed_operand_ctype_enum_t ctype = xed_operand_get_ctype(op_name);
971 switch(ctype) {
972 case XED_OPERAND_CTYPE_XED_BITS_T: {
973 xed_bits_t b;
974 xed3_get_generic_operand(pi->p,op_name,&b);
975
976 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf),
977 XED_STATIC_CAST(xed_uint_t,b),
978 pi->blen);
979 break;
980 }
981 case XED_OPERAND_CTYPE_XED_UINT8_T: {
982 xed_uint32_t b;
983 xed3_get_generic_operand(pi->p,op_name,&b);
984 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf), b, pi->blen);
985
986 break;
987 }
988 case XED_OPERAND_CTYPE_XED_ERROR_ENUM_T: {
989 /* THIS DOES NOT HAPPEN */
990 xed_pi_strcat(pi,"NDY");
991 break;
992 }
993 case XED_OPERAND_CTYPE_XED_ICLASS_ENUM_T: {
994 /* THIS DOES NOT HAPPEN */
995 xed_iclass_enum_t b = xed3_operand_get_iclass(pi->p);
996 xed_pi_strcat(pi,xed_iclass_enum_t2str(b));
997 break;
998 }
999 case XED_OPERAND_CTYPE_XED_REG_ENUM_T: {
1000 /* THIS ONE IS IMPORTANT -- IT PRINTS THE REGISTERS */
1001 xed_reg_enum_t reg;
1002 xed3_get_generic_operand(pi->p,op_name,®);
1003 print_reg_writemask(pi,reg);
1004 break;
1005 }
1006
1007 default:
1008 xed_pi_strcat(pi, "NOT HANDLING CTYPE ");
1009 xed_pi_strcat(pi, xed_operand_ctype_enum_t2str(ctype));
1010 xed_assert(0);
1011 } // inner switch
1012 } // default case of outer switch
1013 } // outer switch
1014
1015
1016 xed_print_operand_decorations(pi, op);
1017 xml_print_end(pi,"OPERAND");
1018 }
1019
1020
1021 static void
setup_print_info(xed_print_info_t * pi)1022 setup_print_info(xed_print_info_t* pi)
1023 {
1024 // init the internal fields
1025 pi->emitted = 0;
1026 pi->operand_indx = 0;
1027 pi->skip_operand = 0;
1028 pi->implicit = 0;
1029 pi->extra_index_operand = XED_REG_INVALID;
1030
1031 pi->buf[0]=0; /* allow use of strcat for everything */
1032
1033 if (pi->format_options_valid==0) {
1034 // grab the defaults.
1035 pi->format_options_valid = 1;
1036 pi->format_options = xed_format_options;
1037 }
1038 }
1039
1040 //exported
xed_init_print_info(xed_print_info_t * pi)1041 void xed_init_print_info(xed_print_info_t* pi)
1042 {
1043 memset(pi, 0, sizeof(xed_print_info_t));
1044 pi->syntax = XED_SYNTAX_INTEL;
1045 }
1046
1047
1048 static xed_bool_t
xed_decoded_inst_dump_intel_format_internal(xed_print_info_t * pi)1049 xed_decoded_inst_dump_intel_format_internal(xed_print_info_t* pi)
1050 {
1051 unsigned int i;
1052 unsigned int noperands;
1053 const char* instruction_name=0 ;
1054 const xed_inst_t* xi = xed_decoded_inst_inst(pi->p);
1055
1056 if (!xi)
1057 return 0;
1058
1059 setup_print_info(pi);
1060
1061 if (pi->format_options.xml_a)
1062 xed_pi_strcat(pi,"<INS>");
1063
1064 xed_decoded_inst_dump_common(pi);
1065
1066 instruction_name = instruction_name_intel(pi->p);
1067 if (pi->format_options.xml_a)
1068 xed_pi_strcat(pi,"<ICLASS>");
1069 pi->blen = xed_strncat_lower(pi->buf, instruction_name, pi->blen);
1070 xml_print_end(pi,"ICLASS");
1071
1072 noperands = xed_inst_noperands(xi);
1073 // to avoid printing the space in the no-operands case, it is
1074 // sufficient to test noperands because the skip_operand and
1075 // extra_index_operand cases are guaranteed to have other printed
1076 // operands.
1077 if (noperands)
1078 xed_pi_strcat(pi," ");
1079
1080 /* print the operands */
1081
1082 for( i=0;i<noperands;i++)
1083 {
1084 if (pi->skip_operand)
1085 {
1086 pi->skip_operand = 0;
1087 }
1088 else
1089 {
1090 pi->operand_indx=i;
1091 xed_print_operand(pi);
1092 }
1093 }
1094
1095 if (pi->extra_index_operand != XED_REG_INVALID) {
1096 xed_operand_spacer(pi);
1097 if (pi->format_options.xml_a)
1098 xed_pi_strcat(pi,"<OPERAND>");
1099 print_reg_xml(pi,pi->extra_index_operand);
1100 xml_print_end(pi,"OPERAND");
1101 }
1102
1103
1104 if (pi->format_options.xml_f)
1105 pi->blen = xml_print_flags(pi->p, pi->buf, pi->blen);
1106 xml_print_end(pi,"INS");
1107 return 1;
1108 }
1109
1110
1111
1112 static xed_bool_t
xed_decoded_inst_dump_att_format_internal(xed_print_info_t * pi)1113 xed_decoded_inst_dump_att_format_internal(
1114 xed_print_info_t* pi)
1115 {
1116 int i,j,intel_way, noperands;
1117 const int leading_zeros=0;
1118 const xed_inst_t* xi = xed_decoded_inst_inst(pi->p);
1119 const xed_operand_values_t* ov = xed_decoded_inst_operands_const(pi->p);
1120 const char* instruction_name = 0;
1121 const char* suffix = 0;
1122
1123 if (!xi)
1124 return 0;
1125
1126 setup_print_info(pi);
1127 xed_decoded_inst_dump_common(pi);
1128
1129 instruction_name = instruction_name_att(pi->p);
1130 pi->blen = xed_strncat_lower(pi->buf, instruction_name, pi->blen);
1131 suffix = instruction_suffix_att(pi->p);
1132 if (suffix) {
1133 xed_pi_strcat(pi,suffix);
1134 }
1135
1136 noperands = xed_inst_noperands(xi);
1137 if (noperands)
1138 xed_pi_strcat(pi," ");
1139
1140 intel_way = 0;
1141 if (xed_inst_get_attribute(xi, XED_ATTRIBUTE_ATT_OPERAND_ORDER_EXCEPTION))
1142 intel_way = 1;
1143
1144 #if defined(XED_MPX)
1145 if (xed_decoded_inst_get_attribute(
1146 pi->p,
1147 XED_ATTRIBUTE_INDEX_REG_IS_POINTER))
1148 {
1149
1150 for( j=0;j<noperands;j++)
1151 {
1152 const xed_operand_t* op;
1153
1154 i = noperands - j - 1; // never intel_way
1155
1156 op = xed_inst_operand(xi,i);
1157 switch(xed_operand_name(op))
1158 {
1159 case XED_OPERAND_MEM0: {
1160 xed_reg_enum_t indx = xed3_operand_get_index(pi->p);
1161 xed_pi_strcat(pi,"%");
1162 pi->blen = xed_strncat_lower(pi->buf,
1163 xed_reg_enum_t2str(indx),
1164 pi->blen);
1165
1166 pi->emitted=1;
1167 } // case
1168 default:
1169 break; // ignore everything else
1170
1171 } // switch
1172 } //for
1173 }
1174 #endif
1175
1176 for( j=0;j<noperands;j++) {
1177 const xed_operand_t* op;
1178 xed_operand_enum_t op_name;
1179
1180 if (intel_way)
1181 i = j;
1182 else
1183 i = noperands - j - 1;
1184
1185 op = xed_inst_operand(xi,i);
1186 op_name = xed_operand_name(op);
1187
1188 // for mangling name of x87 implicit operand
1189 pi->implicit = (xed_operand_operand_visibility(op) == XED_OPVIS_IMPLICIT);
1190
1191 pi->operand_indx=i; // use the Intel numbering
1192 #if defined(XED_SUPPORTS_AVX512)
1193 if (pi->format_options.write_mask_curly_k0 &&
1194 operand_is_writemask(op))
1195 {
1196 continue;
1197 }
1198 #endif
1199
1200 if (xed_operand_operand_visibility(op) == XED_OPVIS_SUPPRESSED) {
1201 if (stringop_memop(pi->p,op)) {
1202 /* print the memop */
1203 }
1204 else {
1205 /* suppressed memops with nondefault segments get their
1206 * segment printed */
1207 if (xed_operand_name(op) == XED_OPERAND_MEM0) {
1208 if (xed_operand_values_using_default_segment(ov, 0) == 0) {
1209 xed_reg_enum_t seg = xed3_operand_get_seg0(pi->p);
1210 pi->blen = xed_strncat_lower(pi->buf,
1211 xed_reg_enum_t2str(seg),
1212 pi->blen);
1213 xed_pi_strcat(pi,":");
1214 pi->emitted=1;
1215 }
1216 }
1217 else if (xed_operand_name(op) == XED_OPERAND_MEM1) {
1218 if (xed_operand_values_using_default_segment(ov, 1) == 0) {
1219 xed_reg_enum_t seg = xed3_operand_get_seg1(pi->p);
1220 pi->blen = xed_strncat_lower(pi->buf,
1221 xed_reg_enum_t2str(seg),
1222 pi->blen);
1223 xed_pi_strcat(pi, ":");
1224 pi->emitted=1;
1225 }
1226 }
1227 continue;
1228 }
1229 }
1230
1231 if (pi->emitted)
1232 xed_pi_strcat(pi,", ");
1233 pi->emitted=1;
1234
1235 switch(xed_operand_name(op)) {
1236 case XED_OPERAND_AGEN:
1237 case XED_OPERAND_MEM0: {
1238 xed_reg_enum_t base = xed3_operand_get_base0(pi->p);
1239 xed_reg_enum_t seg = xed3_operand_get_seg0(pi->p);
1240 xed_reg_enum_t index = xed3_operand_get_index(pi->p);
1241 xed_int64_t disp =
1242 xed_operand_values_get_memory_displacement_int64(ov);
1243 unsigned int disp_bits =
1244 xed_operand_values_get_memory_displacement_length_bits(ov);
1245
1246 xed_bits_t scale = xed3_operand_get_scale(pi->p);
1247
1248 if (seg != XED_REG_INVALID &&
1249 !xed_operand_values_using_default_segment(ov, 0))
1250 {
1251 if (xed_operand_name(op) != XED_OPERAND_AGEN) {
1252 xed_pi_strcat(pi,"%");
1253 pi->blen = xed_strncat_lower(pi->buf,
1254 xed_reg_enum_t2str(seg),
1255 pi->blen);
1256 xed_pi_strcat(pi,":");
1257 }
1258 }
1259 if (xed_operand_values_has_memory_displacement(ov))
1260 {
1261 if (disp_bits && disp) {
1262 if (disp<0) {
1263 if ( (base != XED_REG_INVALID) ||
1264 (index != XED_REG_INVALID) ) {
1265 xed_pi_strcat(pi,"-");
1266 disp = - disp;
1267 }
1268 }
1269 xed_pi_strcat(pi,"0x");
1270 pi->blen =
1271 xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
1272 disp,
1273 disp_bits,
1274 leading_zeros,
1275 pi->blen,
1276 pi->format_options.lowercase_hex);
1277 }
1278 }
1279
1280 if (base != XED_REG_INVALID || index != XED_REG_INVALID)
1281 xed_pi_strcat(pi,"(");
1282 if (base != XED_REG_INVALID) {
1283 xed_pi_strcat(pi,"%");
1284 pi->blen = xed_strncat_lower(pi->buf,
1285 xed_reg_enum_t2str(base),
1286 pi->blen);
1287 }
1288 if (index != XED_REG_INVALID)
1289 {
1290 #if defined(XED_MPX)
1291 if (xed_decoded_inst_get_attribute(
1292 pi->p,
1293 XED_ATTRIBUTE_INDEX_REG_IS_POINTER))
1294 {
1295 // MPX BNDLDX/BNDSTX instr are unusual in that they use
1296 // the index reg as distinct operand.
1297
1298 // HANDLED ABOVE!
1299 }
1300 else
1301 #endif
1302 {
1303 xed_pi_strcat(pi,",%");
1304 pi->blen = xed_strncat_lower(pi->buf,
1305 xed_reg_enum_t2str(index),
1306 pi->blen);
1307 xed_pi_strcat(pi,",");
1308 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf),
1309 XED_STATIC_CAST(xed_uint_t,scale),
1310 pi->blen);
1311 }
1312 }
1313 if (base != XED_REG_INVALID || index != XED_REG_INVALID)
1314 xed_pi_strcat(pi,")");
1315
1316 print_write_mask_generic(pi);
1317 if (base == XED_REG_RIP && xed_operand_values_has_memory_displacement(ov))
1318 print_rel_sym(pi,no_print_address, memory_displacement);
1319
1320 break;
1321 }
1322
1323 case XED_OPERAND_MEM1: {
1324 xed_reg_enum_t base = xed3_operand_get_base1(pi->p);
1325 xed_reg_enum_t seg = xed3_operand_get_seg1(pi->p);
1326 if (seg != XED_REG_INVALID &&
1327 !xed_operand_values_using_default_segment(ov, 1))
1328 {
1329 xed_pi_strcat(pi,"%");
1330 pi->blen = xed_strncat_lower(pi->buf,
1331 xed_reg_enum_t2str(seg),
1332 pi->blen);
1333 xed_pi_strcat(pi,":");
1334 }
1335
1336 if (base != XED_REG_INVALID) {
1337 xed_pi_strcat(pi,"(%");
1338 pi->blen = xed_strncat_lower(pi->buf,
1339 xed_reg_enum_t2str(base),
1340 pi->blen);
1341 xed_pi_strcat(pi,")");
1342 }
1343 break;
1344 }
1345 case XED_OPERAND_IMM0: {
1346 xed_pi_strcat(pi,"$0x");
1347 if ( xed3_operand_get_imm0signed(pi->p) &&
1348 pi->format_options.no_sign_extend_signed_immediates == 0 )
1349 {
1350 // sign-extend imm to effective operand width
1351 unsigned int eff_bits = xed_decoded_inst_get_operand_width(pi->p);
1352 xed_int32_t imm = XED_STATIC_CAST(xed_int32_t,
1353 xed_operand_values_get_immediate_int64(ov));
1354 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
1355 imm,
1356 eff_bits,
1357 leading_zeros,
1358 pi->blen,
1359 pi->format_options.lowercase_hex);
1360 }
1361 else {
1362 // how many bits of imm hold imm values. Sometimes we use upper bits
1363 // for other things (like register specifiers)
1364 unsigned int real_bits = xed_decoded_inst_operand_element_size_bits(
1365 pi->p,
1366 pi->operand_indx);
1367 xed_uint64_t imm =xed_operand_values_get_immediate_uint64(ov);
1368 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
1369 imm,
1370 real_bits,
1371 leading_zeros,
1372 pi->blen,
1373 pi->format_options.lowercase_hex);
1374 }
1375 break;
1376 }
1377 case XED_OPERAND_IMM1: { // The ENTER instruction
1378 xed_uint64_t imm = xed3_operand_get_uimm1(pi->p);
1379 xed_pi_strcat(pi,"$0x");
1380 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
1381 imm,
1382 8,
1383 leading_zeros,
1384 pi->blen,
1385 pi->format_options.lowercase_hex);
1386 break;
1387 }
1388
1389 case XED_OPERAND_PTR: {
1390 unsigned int disp =
1391 xed_decoded_inst_get_branch_displacement(pi->p);
1392 xed_bool_t long_mode =
1393 xed_operand_values_get_long_mode(
1394 xed_decoded_inst_operands_const(pi->p));
1395
1396 xed_uint_t bits_to_print = long_mode ? 8*8 :4*8;
1397 xed_pi_strcat(pi,"$0x");
1398 pi->blen = xed_itoa_hex_ul(pi->buf+xed_strlen(pi->buf),
1399 disp,
1400 bits_to_print,
1401 leading_zeros,
1402 pi->blen,
1403 pi->format_options.lowercase_hex);
1404 break;
1405 }
1406
1407 case XED_OPERAND_RELBR:
1408 print_relbr(pi);
1409 break;
1410
1411 default: {
1412 xed_operand_ctype_enum_t ctype = xed_operand_get_ctype(op_name);
1413 switch(ctype) {
1414 case XED_OPERAND_CTYPE_XED_BITS_T: {
1415 xed_bits_t b;
1416 xed3_get_generic_operand(pi->p,op_name,&b);
1417
1418 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf),
1419 XED_STATIC_CAST(xed_uint_t,b),
1420 pi->blen);
1421 break;
1422 }
1423 case XED_OPERAND_CTYPE_XED_UINT8_T: {
1424 xed_uint32_t b;
1425 xed3_get_generic_operand(pi->p,op_name,&b);
1426 pi->blen = xed_itoa(pi->buf+xed_strlen(pi->buf),
1427 b,
1428 pi->blen);
1429 break;
1430 }
1431 case XED_OPERAND_CTYPE_XED_ERROR_ENUM_T: {
1432 /* DOES NOT OCCUR */
1433 xed_pi_strcat(pi,"NDY");
1434 break;
1435 }
1436 case XED_OPERAND_CTYPE_XED_ICLASS_ENUM_T: {
1437 /* DOES NOT OCCUR */
1438 xed_iclass_enum_t b = xed3_operand_get_iclass(pi->p);
1439 pi->blen = xed_strncat_lower(pi->buf,
1440 xed_iclass_enum_t2str(b),
1441 pi->blen);
1442 break;
1443 }
1444 case XED_OPERAND_CTYPE_XED_REG_ENUM_T: {
1445 /* THIS IS IMPORTANT - THIS IS WHERE REGISTERS GET
1446 * PRINTED */
1447 xed_reg_enum_t reg;
1448 xed3_get_generic_operand(pi->p,op_name,®);
1449 print_reg_writemask(pi, reg);
1450 break;
1451 }
1452
1453 default:
1454 xed_pi_strcat(pi,"NOT HANDLING CTYPE ");
1455 xed_pi_strcat(pi, xed_operand_ctype_enum_t2str(ctype));
1456 xed_assert(0);
1457 }
1458 }
1459 }
1460 xed_print_operand_decorations(pi, op);
1461 } /* for operands */
1462
1463
1464 return 1;
1465 }
1466
1467
1468 ////////////////////////////////////////////////////////////////////////////
1469 static xed_bool_t
validate_print_info(xed_print_info_t * pi)1470 validate_print_info(xed_print_info_t* pi)
1471 {
1472 if (pi->p == 0)
1473 return 1; // fail
1474 if (pi->buf == 0)
1475 return 1; // fail
1476 if (pi->blen < 16)
1477 return 1; // fail
1478 return 0;
1479 }
1480
1481
1482 xed_bool_t
xed_format_context(xed_syntax_enum_t syntax,const xed_decoded_inst_t * xedd,char * out_buffer,int buffer_len,xed_uint64_t runtime_instruction_address,void * context,xed_disassembly_callback_fn_t symbolic_callback)1483 xed_format_context(xed_syntax_enum_t syntax,
1484 const xed_decoded_inst_t* xedd,
1485 char* out_buffer,
1486 int buffer_len,
1487 xed_uint64_t runtime_instruction_address,
1488 void* context,
1489 xed_disassembly_callback_fn_t symbolic_callback)
1490 {
1491 xed_print_info_t pi;
1492 xed_init_print_info(&pi);
1493 pi.p = xedd;
1494 pi.blen = buffer_len;
1495 pi.buf = out_buffer;
1496
1497 // passed back to symbolic disassembly function
1498 pi.context = context;
1499 pi.disassembly_callback = symbolic_callback;
1500
1501 pi.runtime_address = runtime_instruction_address;
1502 pi.syntax = syntax;
1503 pi.format_options_valid = 0; // use defaults
1504 pi.buf[0]=0; //allow use of strcat
1505 return xed_format_generic(&pi);
1506 }
1507
1508
1509 // preferred interface (fewer parameters, most flexible)
1510
xed_format_generic(xed_print_info_t * pi)1511 xed_bool_t xed_format_generic( xed_print_info_t* pi )
1512 {
1513 if (validate_print_info(pi))
1514 return 0;
1515
1516 if (pi->syntax == XED_SYNTAX_INTEL)
1517 return xed_decoded_inst_dump_intel_format_internal(pi);
1518 else if (pi->syntax == XED_SYNTAX_ATT)
1519 return xed_decoded_inst_dump_att_format_internal(pi);
1520 else if (pi->syntax == XED_SYNTAX_XED)
1521 return xed_decoded_inst_dump_xed_format(pi->p,
1522 pi->buf,
1523 pi->blen,
1524 pi->runtime_address);
1525 return 0;
1526 }
1527