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,&reg);
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," &lt;");
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," &gt;");
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,&reg);
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,&reg);
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