x86_format.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "libdis.h"
  5. #include <inttypes.h>
  6. #ifdef _MSC_VER
  7. #define snprintf _snprintf
  8. #define inline __inline
  9. #endif
  10. /*
  11. * concatenation macros. STRNCATF concatenates a format string, buf
  12. * only with one argument.
  13. */
  14. #define STRNCAT( buf, str, len ) do { \
  15. int _i = strlen(str), _blen = strlen(buf), _len = len - 1; \
  16. if ( len ) { \
  17. strncat( buf, str, _len ); \
  18. if ( _len <= _i ) { \
  19. buf[_blen+_len] = '\0'; \
  20. len = 0; \
  21. } else { \
  22. len -= _i; \
  23. } \
  24. } \
  25. } while( 0 )
  26. #define STRNCATF( buf, fmt, data, len ) do { \
  27. char _tmp[MAX_OP_STRING]; \
  28. \
  29. snprintf( _tmp, sizeof _tmp, fmt, data ); \
  30. STRNCAT( buf, _tmp, len ); \
  31. } while( 0 )
  32. #define PRINT_DISPLACEMENT( ea ) do { \
  33. if ( ea->disp_size && ea->disp ) { \
  34. if ( ea->disp_sign ) { \
  35. STRNCATF( buf, "-0x%" PRIX32, -ea->disp, len ); \
  36. } else { \
  37. STRNCATF( buf, "0x%" PRIX32, ea->disp, len ); \
  38. } \
  39. } \
  40. } while( 0 )
  41. static char *prefix_strings[] = {
  42. "", /* no prefix */
  43. "repz ", /* the trailing spaces make it easy to prepend to mnemonic */
  44. "repnz ",
  45. "lock ",
  46. "branch delay " /* unused in x86 */
  47. };
  48. static int format_insn_prefix_str( enum x86_insn_prefix prefix, char *buf,
  49. int len ) {
  50. int len_orig = len;
  51. /* concat all prefix strings */
  52. if ( prefix & 1 ) { STRNCAT( buf, prefix_strings[1], len ); }
  53. if ( prefix & 2 ) { STRNCAT( buf, prefix_strings[2], len ); }
  54. if ( prefix & 4 ) { STRNCAT( buf, prefix_strings[3], len ); }
  55. if ( prefix & 8 ) { STRNCAT( buf, prefix_strings[4], len ); }
  56. /* return the number of characters added */
  57. return (len_orig - len);
  58. }
  59. /*
  60. * sprint's an operand's data to string str.
  61. */
  62. static void get_operand_data_str( x86_op_t *op, char *str, int len ){
  63. if ( op->flags.op_signed ) {
  64. switch ( op->datatype ) {
  65. case op_byte:
  66. snprintf( str, len, "%" PRId8, op->data.sbyte );
  67. return;
  68. case op_word:
  69. snprintf( str, len, "%" PRId16, op->data.sword );
  70. return;
  71. case op_qword:
  72. snprintf( str, len, "%" PRId64, op->data.sqword );
  73. return;
  74. default:
  75. snprintf( str, len, "%" PRId32, op->data.sdword );
  76. return;
  77. }
  78. }
  79. //else
  80. switch ( op->datatype ) {
  81. case op_byte:
  82. snprintf( str, len, "0x%02" PRIX8, op->data.byte );
  83. return;
  84. case op_word:
  85. snprintf( str, len, "0x%04" PRIX16, op->data.word );
  86. return;
  87. case op_qword:
  88. snprintf( str, len, "0x%08" PRIX64,op->data.sqword );
  89. return;
  90. default:
  91. snprintf( str, len, "0x%08" PRIX32, op->data.dword );
  92. return;
  93. }
  94. }
  95. /*
  96. * sprints register types to a string. the register types can be ORed
  97. * together.
  98. */
  99. static void get_operand_regtype_str( int regtype, char *str, int len )
  100. {
  101. static struct {
  102. char *name;
  103. int value;
  104. } operand_regtypes[] = {
  105. {"reg_gen" , 0x00001},
  106. {"reg_in" , 0x00002},
  107. {"reg_out" , 0x00004},
  108. {"reg_local" , 0x00008},
  109. {"reg_fpu" , 0x00010},
  110. {"reg_seg" , 0x00020},
  111. {"reg_simd" , 0x00040},
  112. {"reg_sys" , 0x00080},
  113. {"reg_sp" , 0x00100},
  114. {"reg_fp" , 0x00200},
  115. {"reg_pc" , 0x00400},
  116. {"reg_retaddr", 0x00800},
  117. {"reg_cond" , 0x01000},
  118. {"reg_zero" , 0x02000},
  119. {"reg_ret" , 0x04000},
  120. {"reg_src" , 0x10000},
  121. {"reg_dest" , 0x20000},
  122. {"reg_count" , 0x40000},
  123. {NULL, 0}, //end
  124. };
  125. unsigned int i;
  126. memset( str, 0, len );
  127. //go thru every type in the enum
  128. for ( i = 0; operand_regtypes[i].name; i++ ) {
  129. //skip if type is not set
  130. if(! (regtype & operand_regtypes[i].value) )
  131. continue;
  132. //not the first time around
  133. if( str[0] ) {
  134. STRNCAT( str, " ", len );
  135. }
  136. STRNCAT(str, operand_regtypes[i].name, len );
  137. }
  138. }
  139. static int format_expr( x86_ea_t *ea, char *buf, int len,
  140. enum x86_asm_format format ) {
  141. char str[MAX_OP_STRING];
  142. if ( format == att_syntax ) {
  143. if (ea->base.name[0] || ea->index.name[0] || ea->scale) {
  144. PRINT_DISPLACEMENT(ea);
  145. STRNCAT( buf, "(", len );
  146. if ( ea->base.name[0]) {
  147. STRNCATF( buf, "%%%s", ea->base.name, len );
  148. }
  149. if ( ea->index.name[0]) {
  150. STRNCATF( buf, ",%%%s", ea->index.name, len );
  151. if ( ea->scale > 1 ) {
  152. STRNCATF( buf, ",%d", ea->scale, len );
  153. }
  154. }
  155. /* handle the syntactic exception */
  156. if ( ! ea->base.name[0] &&
  157. ! ea->index.name[0] ) {
  158. STRNCATF( buf, ",%d", ea->scale, len );
  159. }
  160. STRNCAT( buf, ")", len );
  161. } else
  162. STRNCATF( buf, "0x%" PRIX32, ea->disp, len );
  163. } else if ( format == xml_syntax ){
  164. if ( ea->base.name[0]) {
  165. STRNCAT (buf, "\t\t\t<base>\n", len);
  166. get_operand_regtype_str (ea->base.type, str,
  167. sizeof str);
  168. STRNCAT (buf, "\t\t\t\t<register ", len);
  169. STRNCATF (buf, "name=\"%s\" ", ea->base.name, len);
  170. STRNCATF (buf, "type=\"%s\" ", str, len);
  171. STRNCATF (buf, "size=%d/>\n", ea->base.size, len);
  172. STRNCAT (buf, "\t\t\t</base>\n", len);
  173. }
  174. if ( ea->index.name[0]) {
  175. STRNCAT (buf, "\t\t\t<index>\n", len);
  176. get_operand_regtype_str (ea->index.type, str,
  177. sizeof str);
  178. STRNCAT (buf, "\t\t\t\t<register ", len);
  179. STRNCATF (buf, "name=\"%s\" ", ea->index.name, len);
  180. STRNCATF (buf, "type=\"%s\" ", str, len);
  181. STRNCATF (buf, "size=%d/>\n", ea->index.size, len);
  182. STRNCAT (buf, "\t\t\t</index>\n", len);
  183. }
  184. //scale
  185. STRNCAT (buf, "\t\t\t<scale>\n", len);
  186. STRNCAT (buf, "\t\t\t\t<immediate ", len);
  187. STRNCATF (buf, "value=\"%d\"/>\n", ea->scale, len);
  188. STRNCAT (buf, "\t\t\t</scale>\n", len);
  189. if ( ea->disp_size ) {
  190. STRNCAT (buf, "\t\t\t<displacement>\n", len);
  191. if ( ea->disp_size > 1 && ! ea->disp_sign ) {
  192. STRNCAT (buf, "\t\t\t\t<address ", len);
  193. STRNCATF (buf, "value=\"0x%" PRIX32 "\"/>\n", ea->disp,
  194. len);
  195. } else {
  196. STRNCAT (buf, "\t\t\t\t<immediate ", len);
  197. STRNCATF (buf, "value=%" PRId32 "/>\n", ea->disp, len);
  198. }
  199. STRNCAT (buf, "\t\t\t</displacement>\n", len);
  200. }
  201. } else if ( format == raw_syntax ) {
  202. PRINT_DISPLACEMENT(ea);
  203. STRNCAT( buf, "(", len );
  204. STRNCATF( buf, "%s,", ea->base.name, len );
  205. STRNCATF( buf, "%s,", ea->index.name, len );
  206. STRNCATF( buf, "%d", ea->scale, len );
  207. STRNCAT( buf, ")", len );
  208. } else {
  209. STRNCAT( buf, "[", len );
  210. if ( ea->base.name[0] ) {
  211. STRNCAT( buf, ea->base.name, len );
  212. if ( ea->index.name[0] ||
  213. (ea->disp_size && ! ea->disp_sign) ) {
  214. STRNCAT( buf, "+", len );
  215. }
  216. }
  217. if ( ea->index.name[0] ) {
  218. STRNCAT( buf, ea->index.name, len );
  219. if ( ea->scale > 1 )
  220. {
  221. STRNCATF( buf, "*%" PRId32, ea->scale, len );
  222. }
  223. if ( ea->disp_size && ! ea->disp_sign )
  224. {
  225. STRNCAT( buf, "+", len );
  226. }
  227. }
  228. if ( ea->disp_size || (! ea->index.name[0] &&
  229. ! ea->base.name[0] ) )
  230. {
  231. PRINT_DISPLACEMENT(ea);
  232. }
  233. STRNCAT( buf, "]", len );
  234. }
  235. return( strlen(buf) );
  236. }
  237. static int format_seg( x86_op_t *op, char *buf, int len,
  238. enum x86_asm_format format ) {
  239. int len_orig = len;
  240. char *reg = "";
  241. if (! op || ! buf || ! len || ! op->flags.whole) {
  242. return(0);
  243. }
  244. if ( op->type != op_offset && op->type != op_expression ){
  245. return(0);
  246. }
  247. if (! (int) op->flags.op_seg) {
  248. return(0);
  249. }
  250. switch (op->flags.op_seg) {
  251. case x86_op_flags::op_es_seg: reg = "es"; break;
  252. case x86_op_flags::op_cs_seg: reg = "cs"; break;
  253. case x86_op_flags::op_ss_seg: reg = "ss"; break;
  254. case x86_op_flags::op_ds_seg: reg = "ds"; break;
  255. case x86_op_flags::op_fs_seg: reg = "fs"; break;
  256. case x86_op_flags::op_gs_seg: reg = "gs"; break;
  257. default:
  258. break;
  259. }
  260. if (! reg[0] ) {
  261. return( 0 );
  262. }
  263. switch( format ) {
  264. case xml_syntax:
  265. STRNCAT( buf, "\t\t\t<segment ", len );
  266. STRNCATF( buf, "value=\"%s\"/>\n", reg, len );
  267. break;
  268. case att_syntax:
  269. STRNCATF( buf, "%%%s:", reg, len );
  270. break;
  271. default:
  272. STRNCATF( buf, "%s:", reg, len );
  273. break;
  274. }
  275. return( len_orig - len ); /* return length of appended string */
  276. }
  277. static char *get_operand_datatype_str( x86_op_t *op ){
  278. static char *types[] = {
  279. "sbyte", /* 0 */
  280. "sword",
  281. "sqword",
  282. "sdword",
  283. "sdqword", /* 4 */
  284. "byte",
  285. "word",
  286. "qword",
  287. "dword", /* 8 */
  288. "dqword",
  289. "sreal",
  290. "dreal",
  291. "extreal", /* 12 */
  292. "bcd",
  293. "ssimd",
  294. "dsimd",
  295. "sssimd", /* 16 */
  296. "sdsimd",
  297. "descr32",
  298. "descr16",
  299. "pdescr32", /* 20 */
  300. "pdescr16",
  301. "bounds16",
  302. "bounds32",
  303. "fpu_env16",
  304. "fpu_env32", /* 25 */
  305. "fpu_state16",
  306. "fpu_state32",
  307. "fp_reg_set"
  308. };
  309. /* handle signed values first */
  310. if ( op->flags.op_signed ) {
  311. switch (op->datatype) {
  312. case op_byte: return types[0];
  313. case op_word: return types[1];
  314. case op_qword: return types[2];
  315. case op_dqword: return types[4];
  316. default: return types[3];
  317. }
  318. }
  319. switch (op->datatype) {
  320. case op_byte: return types[5];
  321. case op_word: return types[6];
  322. case op_qword: return types[7];
  323. case op_dqword: return types[9];
  324. case op_sreal: return types[10];
  325. case op_dreal: return types[11];
  326. case op_extreal: return types[12];
  327. case op_bcd: return types[13];
  328. case op_ssimd: return types[14];
  329. case op_dsimd: return types[15];
  330. case op_sssimd: return types[16];
  331. case op_sdsimd: return types[17];
  332. case op_descr32: return types[18];
  333. case op_descr16: return types[19];
  334. case op_pdescr32: return types[20];
  335. case op_pdescr16: return types[21];
  336. case op_bounds16: return types[22];
  337. case op_bounds32: return types[23];
  338. case op_fpustate16: return types[24];
  339. case op_fpustate32: return types[25];
  340. case op_fpuenv16: return types[26];
  341. case op_fpuenv32: return types[27];
  342. case op_fpregset: return types[28];
  343. default: return types[8];
  344. }
  345. }
  346. static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
  347. int len) {
  348. static struct {
  349. char *name;
  350. int value;
  351. } insn_flags[] = {
  352. { "carry_set ", 0x0001 },
  353. { "zero_set ", 0x0002 },
  354. { "oflow_set ", 0x0004 },
  355. { "dir_set ", 0x0008 },
  356. { "sign_set ", 0x0010 },
  357. { "parity_set ", 0x0020 },
  358. { "carry_or_zero_set ", 0x0040 },
  359. { "zero_set_or_sign_ne_oflow ", 0x0080 },
  360. { "carry_clear ", 0x0100 },
  361. { "zero_clear ", 0x0200 },
  362. { "oflow_clear ", 0x0400 },
  363. { "dir_clear ", 0x0800 },
  364. { "sign_clear ", 0x1000 },
  365. { "parity_clear ", 0x2000 },
  366. { "sign_eq_oflow ", 0x4000 },
  367. { "sign_ne_oflow ", 0x8000 },
  368. { NULL, 0x0000 }, //end
  369. };
  370. unsigned int i;
  371. int len_orig = len;
  372. for (i = 0; insn_flags[i].name; i++) {
  373. if (! (flags & insn_flags[i].value) )
  374. continue;
  375. STRNCAT( buf, insn_flags[i].name, len );
  376. }
  377. return( len_orig - len );
  378. }
  379. static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
  380. static char *types[] = {
  381. "", // 0
  382. "controlflow",// 1
  383. "arithmetic", // 2
  384. "logic", // 3
  385. "stack", // 4
  386. "comparison", // 5
  387. "move", // 6
  388. "string", // 7
  389. "bit_manip", // 8
  390. "flag_manip", // 9
  391. "fpu", // 10
  392. "", // 11
  393. "", // 12
  394. "interrupt", // 13
  395. "system", // 14
  396. "other", // 15
  397. };
  398. if ( gp > sizeof (types)/sizeof(types[0]) )
  399. return "";
  400. return types[gp];
  401. }
  402. static char *get_insn_type_str( enum x86_insn_type type ) {
  403. static struct {
  404. char *name;
  405. int value;
  406. } types[] = {
  407. /* insn_controlflow */
  408. { "jmp", 0x1001 },
  409. { "jcc", 0x1002 },
  410. { "call", 0x1003 },
  411. { "callcc", 0x1004 },
  412. { "return", 0x1005 },
  413. { "loop", 0x1006 },
  414. /* insn_arithmetic */
  415. { "add", 0x2001 },
  416. { "sub", 0x2002 },
  417. { "mul", 0x2003 },
  418. { "div", 0x2004 },
  419. { "inc", 0x2005 },
  420. { "dec", 0x2006 },
  421. { "shl", 0x2007 },
  422. { "shr", 0x2008 },
  423. { "rol", 0x2009 },
  424. { "ror", 0x200A },
  425. /* insn_logic */
  426. { "and", 0x3001 },
  427. { "or", 0x3002 },
  428. { "xor", 0x3003 },
  429. { "not", 0x3004 },
  430. { "neg", 0x3005 },
  431. /* insn_stack */
  432. { "push", 0x4001 },
  433. { "pop", 0x4002 },
  434. { "pushregs", 0x4003 },
  435. { "popregs", 0x4004 },
  436. { "pushflags", 0x4005 },
  437. { "popflags", 0x4006 },
  438. { "enter", 0x4007 },
  439. { "leave", 0x4008 },
  440. /* insn_comparison */
  441. { "test", 0x5001 },
  442. { "cmp", 0x5002 },
  443. /* insn_move */
  444. { "mov", 0x6001 }, /* move */
  445. { "movcc", 0x6002 }, /* conditional move */
  446. { "xchg", 0x6003 }, /* exchange */
  447. { "xchgcc", 0x6004 }, /* conditional exchange */
  448. /* insn_string */
  449. { "strcmp", 0x7001 },
  450. { "strload", 0x7002 },
  451. { "strmov", 0x7003 },
  452. { "strstore", 0x7004 },
  453. { "translate", 0x7005 }, /* xlat */
  454. /* insn_bit_manip */
  455. { "bittest", 0x8001 },
  456. { "bitset", 0x8002 },
  457. { "bitclear", 0x8003 },
  458. /* insn_flag_manip */
  459. { "clear_carry", 0x9001 },
  460. { "clear_zero", 0x9002 },
  461. { "clear_oflow", 0x9003 },
  462. { "clear_dir", 0x9004 },
  463. { "clear_sign", 0x9005 },
  464. { "clear_parity", 0x9006 },
  465. { "set_carry", 0x9007 },
  466. { "set_zero", 0x9008 },
  467. { "set_oflow", 0x9009 },
  468. { "set_dir", 0x900A },
  469. { "set_sign", 0x900B },
  470. { "set_parity", 0x900C },
  471. { "tog_carry", 0x9010 },
  472. { "tog_zero", 0x9020 },
  473. { "tog_oflow", 0x9030 },
  474. { "tog_dir", 0x9040 },
  475. { "tog_sign", 0x9050 },
  476. { "tog_parity", 0x9060 },
  477. /* insn_fpu */
  478. { "fmov", 0xA001 },
  479. { "fmovcc", 0xA002 },
  480. { "fneg", 0xA003 },
  481. { "fabs", 0xA004 },
  482. { "fadd", 0xA005 },
  483. { "fsub", 0xA006 },
  484. { "fmul", 0xA007 },
  485. { "fdiv", 0xA008 },
  486. { "fsqrt", 0xA009 },
  487. { "fcmp", 0xA00A },
  488. { "fcos", 0xA00C },
  489. { "fldpi", 0xA00D },
  490. { "fldz", 0xA00E },
  491. { "ftan", 0xA00F },
  492. { "fsine", 0xA010 },
  493. { "fsys", 0xA020 },
  494. /* insn_interrupt */
  495. { "int", 0xD001 },
  496. { "intcc", 0xD002 }, /* not present in x86 ISA */
  497. { "iret", 0xD003 },
  498. { "bound", 0xD004 },
  499. { "debug", 0xD005 },
  500. { "trace", 0xD006 },
  501. { "invalid_op", 0xD007 },
  502. { "oflow", 0xD008 },
  503. /* insn_system */
  504. { "halt", 0xE001 },
  505. { "in", 0xE002 }, /* input from port/bus */
  506. { "out", 0xE003 }, /* output to port/bus */
  507. { "cpuid", 0xE004 },
  508. /* insn_other */
  509. { "nop", 0xF001 },
  510. { "bcdconv", 0xF002 }, /* convert to or from BCD */
  511. { "szconv", 0xF003 }, /* change size of operand */
  512. { NULL, 0 }, //end
  513. };
  514. unsigned int i;
  515. //go thru every type in the enum
  516. for ( i = 0; types[i].name; i++ ) {
  517. if ( types[i].value == type )
  518. return types[i].name;
  519. }
  520. return "";
  521. }
  522. static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
  523. static char *intel[] = {
  524. "", // 0
  525. "8086", // 1
  526. "80286", // 2
  527. "80386", // 3
  528. "80387", // 4
  529. "80486", // 5
  530. "Pentium", // 6
  531. "Pentium Pro", // 7
  532. "Pentium 2", // 8
  533. "Pentium 3", // 9
  534. "Pentium 4" // 10
  535. };
  536. if ( cpu <= sizeof(intel)/sizeof(intel[0]) ) {
  537. return intel[cpu];
  538. } else if ( cpu == 16 ) {
  539. return "K6";
  540. } else if ( cpu == 32 ) {
  541. return "K7";
  542. } else if ( cpu == 48 ) {
  543. return "Athlon";
  544. }
  545. return "";
  546. }
  547. static char *get_insn_isa_str( enum x86_insn_isa isa ) {
  548. static char *subset[] = {
  549. NULL, // 0
  550. "General Purpose", // 1
  551. "Floating Point", // 2
  552. "FPU Management", // 3
  553. "MMX", // 4
  554. "SSE", // 5
  555. "SSE2", // 6
  556. "SSE3", // 7
  557. "3DNow!", // 8
  558. "System" // 9
  559. };
  560. if ( isa > sizeof (subset)/sizeof(subset[0]) ) {
  561. return "";
  562. }
  563. return subset[isa];
  564. }
  565. static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf,
  566. int len){
  567. char str[MAX_OP_STRING];
  568. memset (str, 0, sizeof str);
  569. switch ( op->type ) {
  570. case op_register:
  571. STRNCATF( buf, "%%%s", op->data.reg.name, len );
  572. break;
  573. case op_immediate:
  574. get_operand_data_str( op, str, sizeof str );
  575. STRNCATF( buf, "$%s", str, len );
  576. break;
  577. case op_relative_near:
  578. STRNCATF( buf, "0x%08X",
  579. (unsigned int)(op->data.sbyte +
  580. insn->addr + insn->size), len );
  581. break;
  582. case op_relative_far:
  583. if (op->datatype == op_word) {
  584. STRNCATF( buf, "0x%08X",
  585. (unsigned int)(op->data.sword +
  586. insn->addr + insn->size), len );
  587. } else {
  588. STRNCATF( buf, "0x%08X",
  589. (unsigned int)(op->data.sdword +
  590. insn->addr + insn->size), len );
  591. }
  592. break;
  593. case op_absolute:
  594. /* ATT uses the syntax $section, $offset */
  595. STRNCATF( buf, "$0x%04" PRIX16 ", ", op->data.absolute.segment,
  596. len );
  597. if (op->datatype == op_descr16) {
  598. STRNCATF( buf, "$0x%04" PRIX16,
  599. op->data.absolute.offset.off16, len );
  600. } else {
  601. STRNCATF( buf, "$0x%08" PRIX32,
  602. op->data.absolute.offset.off32, len );
  603. }
  604. break;
  605. case op_offset:
  606. /* ATT requires a '*' before JMP/CALL ops */
  607. if (insn->type == insn_jmp || insn->type == insn_call)
  608. STRNCAT( buf, "*", len );
  609. len -= format_seg( op, buf, len, att_syntax );
  610. STRNCATF( buf, "0x%08" PRIX32, op->data.sdword, len );
  611. break;
  612. case op_expression:
  613. /* ATT requires a '*' before JMP/CALL ops */
  614. if (insn->type == insn_jmp || insn->type == insn_call)
  615. STRNCAT( buf, "*", len );
  616. len -= format_seg( op, buf, len, att_syntax );
  617. len -= format_expr( &op->data.expression, buf, len,
  618. att_syntax );
  619. break;
  620. case op_unused:
  621. case op_unknown:
  622. /* return 0-truncated buffer */
  623. break;
  624. }
  625. return ( strlen( buf ) );
  626. }
  627. static int format_operand_native( x86_op_t *op, x86_insn_t *insn, char *buf,
  628. int len){
  629. char str[MAX_OP_STRING];
  630. switch (op->type) {
  631. case op_register:
  632. STRNCAT( buf, op->data.reg.name, len );
  633. break;
  634. case op_immediate:
  635. get_operand_data_str( op, str, sizeof str );
  636. STRNCAT( buf, str, len );
  637. break;
  638. case op_relative_near:
  639. STRNCATF( buf, "0x%08" PRIX32,
  640. (unsigned int)(op->data.sbyte +
  641. insn->addr + insn->size), len );
  642. break;
  643. case op_relative_far:
  644. if ( op->datatype == op_word ) {
  645. STRNCATF( buf, "0x%08" PRIX32,
  646. (unsigned int)(op->data.sword +
  647. insn->addr + insn->size), len );
  648. break;
  649. } else {
  650. STRNCATF( buf, "0x%08" PRIX32, op->data.sdword +
  651. insn->addr + insn->size, len );
  652. }
  653. break;
  654. case op_absolute:
  655. STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
  656. len );
  657. if (op->datatype == op_descr16) {
  658. STRNCATF( buf, "0x%04" PRIX16,
  659. op->data.absolute.offset.off16, len );
  660. } else {
  661. STRNCATF( buf, "0x%08" PRIX32,
  662. op->data.absolute.offset.off32, len );
  663. }
  664. break;
  665. case op_offset:
  666. len -= format_seg( op, buf, len, native_syntax );
  667. STRNCATF( buf, "[0x%08" PRIX32 "]", op->data.sdword, len );
  668. break;
  669. case op_expression:
  670. len -= format_seg( op, buf, len, native_syntax );
  671. len -= format_expr( &op->data.expression, buf, len,
  672. native_syntax );
  673. break;
  674. case op_unused:
  675. case op_unknown:
  676. /* return 0-truncated buffer */
  677. break;
  678. }
  679. return( strlen( buf ) );
  680. }
  681. static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
  682. int len){
  683. char str[MAX_OP_STRING] = "\0";
  684. switch (op->type) {
  685. case op_register:
  686. get_operand_regtype_str( op->data.reg.type, str,
  687. sizeof str );
  688. STRNCAT( buf, "\t\t<register ", len );
  689. STRNCATF( buf, "name=\"%s\" ", op->data.reg.name, len );
  690. STRNCATF( buf, "type=\"%s\" ", str, len );
  691. STRNCATF( buf, "size=%d/>\n", op->data.reg.size, len );
  692. break;
  693. case op_immediate:
  694. get_operand_data_str( op, str, sizeof str );
  695. STRNCAT( buf, "\t\t<immediate ", len );
  696. STRNCATF( buf, "type=\"%s\" ",
  697. get_operand_datatype_str (op), len );
  698. STRNCATF( buf, "value=\"%s\"/>\n", str, len );
  699. break;
  700. case op_relative_near:
  701. STRNCAT( buf, "\t\t<relative_offset ", len );
  702. STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
  703. (unsigned int)(op->data.sbyte +
  704. insn->addr + insn->size), len );
  705. break;
  706. case op_relative_far:
  707. STRNCAT( buf, "\t\t<relative_offset ", len );
  708. if (op->datatype == op_word) {
  709. STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
  710. (unsigned int)(op->data.sword +
  711. insn->addr + insn->size), len);
  712. break;
  713. } else {
  714. STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
  715. op->data.sdword + insn->addr + insn->size,
  716. len );
  717. }
  718. break;
  719. case op_absolute:
  720. STRNCATF( buf,
  721. "\t\t<absolute_address segment=\"0x%04" PRIX16 "\"",
  722. op->data.absolute.segment, len );
  723. if (op->datatype == op_descr16) {
  724. STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">",
  725. op->data.absolute.offset.off16, len );
  726. } else {
  727. STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">",
  728. op->data.absolute.offset.off32, len );
  729. }
  730. STRNCAT( buf, "\t\t</absolute_address>\n", len );
  731. break;
  732. case op_expression:
  733. STRNCAT( buf, "\t\t<address_expression>\n", len );
  734. len -= format_seg( op, buf, len, xml_syntax );
  735. len -= format_expr( &op->data.expression, buf, len,
  736. xml_syntax );
  737. STRNCAT( buf, "\t\t</address_expression>\n", len );
  738. break;
  739. case op_offset:
  740. STRNCAT( buf, "\t\t<segment_offset>\n", len );
  741. len -= format_seg( op, buf, len, xml_syntax );
  742. STRNCAT( buf, "\t\t\t<address ", len);
  743. STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
  744. op->data.sdword, len );
  745. STRNCAT( buf, "\t\t</segment_offset>\n", len );
  746. break;
  747. case op_unused:
  748. case op_unknown:
  749. /* return 0-truncated buffer */
  750. break;
  751. }
  752. return( strlen( buf ) );
  753. }
  754. static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
  755. int len){
  756. char str[MAX_OP_RAW_STRING];
  757. char *datatype = get_operand_datatype_str(op);
  758. switch (op->type) {
  759. case op_register:
  760. get_operand_regtype_str( op->data.reg.type, str,
  761. sizeof str );
  762. STRNCAT( buf, "reg|", len );
  763. STRNCATF( buf, "%s|", datatype, len );
  764. STRNCATF( buf, "%s:", op->data.reg.name, len );
  765. STRNCATF( buf, "%s:", str, len );
  766. STRNCATF( buf, "%d|", op->data.reg.size, len );
  767. break;
  768. case op_immediate:
  769. get_operand_data_str( op, str, sizeof str );
  770. STRNCAT( buf, "immediate|", len );
  771. STRNCATF( buf, "%s|", datatype, len );
  772. STRNCATF( buf, "%s|", str, len );
  773. break;
  774. case op_relative_near:
  775. /* NOTE: in raw format, we print the
  776. * relative offset, not the actual
  777. * address of the jump target */
  778. STRNCAT( buf, "relative|", len );
  779. STRNCATF( buf, "%s|", datatype, len );
  780. STRNCATF( buf, "%" PRId8 "|", op->data.sbyte, len );
  781. break;
  782. case op_relative_far:
  783. STRNCAT( buf, "relative|", len );
  784. STRNCATF( buf, "%s|", datatype, len );
  785. if (op->datatype == op_word) {
  786. STRNCATF( buf, "%" PRId16 "|", op->data.sword, len);
  787. break;
  788. } else {
  789. STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len );
  790. }
  791. break;
  792. case op_absolute:
  793. STRNCAT( buf, "absolute_address|", len );
  794. STRNCATF( buf, "%s|", datatype, len );
  795. STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
  796. len );
  797. if (op->datatype == op_descr16) {
  798. STRNCATF( buf, "0x%04" PRIX16 "|",
  799. op->data.absolute.offset.off16, len );
  800. } else {
  801. STRNCATF( buf, "0x%08" PRIX32 "|",
  802. op->data.absolute.offset.off32, len );
  803. }
  804. break;
  805. case op_expression:
  806. STRNCAT( buf, "address_expression|", len );
  807. STRNCATF( buf, "%s|", datatype, len );
  808. len -= format_seg( op, buf, len, native_syntax );
  809. len -= format_expr( &op->data.expression, buf, len,
  810. raw_syntax );
  811. STRNCAT( buf, "|", len );
  812. break;
  813. case op_offset:
  814. STRNCAT( buf, "segment_offset|", len );
  815. STRNCATF( buf, "%s|", datatype, len );
  816. len -= format_seg( op, buf, len, xml_syntax );
  817. STRNCATF( buf, "%08" PRIX32 "|", op->data.sdword, len );
  818. break;
  819. case op_unused:
  820. case op_unknown:
  821. /* return 0-truncated buffer */
  822. break;
  823. }
  824. return( strlen( buf ) );
  825. }
  826. int x86_op_t::x86_format_operand(char *buf, int len,
  827. enum x86_asm_format format ){
  828. x86_insn_t *_insn;
  829. if ( ! this || ! buf || len < 1 ) {
  830. return(0);
  831. }
  832. /* insn is stored in x86_op_t since .21-pre3 */
  833. _insn = (x86_insn_t *) insn;
  834. memset( buf, 0, len );
  835. switch ( format ) {
  836. case att_syntax:
  837. return format_operand_att( this, _insn, buf, len );
  838. case xml_syntax:
  839. return format_operand_xml( this, _insn, buf, len );
  840. case raw_syntax:
  841. return format_operand_raw( this, _insn, buf, len );
  842. case native_syntax:
  843. case intel_syntax:
  844. default:
  845. return format_operand_native( this, _insn, buf, len );
  846. }
  847. }
  848. char * x86_op_t::format( enum x86_asm_format format ) {
  849. char *buf, *str;
  850. size_t len;
  851. switch ( format ) {
  852. case xml_syntax:
  853. len = MAX_OP_XML_STRING;
  854. break;
  855. case raw_syntax:
  856. len = MAX_OP_RAW_STRING;
  857. break;
  858. case native_syntax:
  859. case intel_syntax:
  860. case att_syntax:
  861. case unknown_syntax:
  862. default:
  863. len = MAX_OP_STRING;
  864. break;
  865. }
  866. buf = (char * ) calloc( len + 1, 1 );
  867. x86_format_operand( buf, len, format );
  868. /* drop buffer down to a reasonable size */
  869. str = strdup( buf );
  870. free(buf);
  871. return str;
  872. }
  873. #define is_imm_jmp(op) (op->type == op_absolute || \
  874. op->type == op_immediate || \
  875. op->type == op_offset)
  876. #define is_memory_op(op) (op->type == op_absolute || \
  877. op->type == op_expression || \
  878. op->type == op_offset)
  879. static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
  880. int size = 0;
  881. char *suffix;
  882. if (! insn || ! buf || ! len )
  883. return(0);
  884. memset( buf, 0, len );
  885. /* do long jump/call prefix */
  886. if ( insn->type == insn_jmp || insn->type == insn_call ) {
  887. if (! is_imm_jmp( insn->x86_operand_1st() ) ||
  888. (insn->x86_operand_1st())->datatype != op_byte ) {
  889. /* far jump/call, use "l" prefix */
  890. STRNCAT( buf, "l", len );
  891. }
  892. STRNCAT( buf, insn->mnemonic, len );
  893. return ( strlen( buf ) );
  894. }
  895. /* do mnemonic */
  896. STRNCAT( buf, insn->mnemonic, len );
  897. /* do suffixes for memory operands */
  898. if (!(insn->note & insn_note_nosuffix) &&
  899. (insn->group == x86_insn_t::insn_arithmetic ||
  900. insn->group == x86_insn_t::insn_logic ||
  901. insn->group == x86_insn_t::insn_move ||
  902. insn->group == x86_insn_t::insn_stack ||
  903. insn->group == x86_insn_t::insn_string ||
  904. insn->group == x86_insn_t::insn_comparison ||
  905. insn->type == insn_in ||
  906. insn->type == insn_out
  907. )) {
  908. if ( insn->x86_operand_count( op_explicit ) > 0 &&
  909. is_memory_op( insn->x86_operand_1st() ) ){
  910. size = insn->x86_operand_1st()->x86_operand_size();
  911. } else if ( insn->x86_operand_count( op_explicit ) > 1 &&
  912. is_memory_op( insn->x86_operand_2nd() ) ){
  913. size = insn->x86_operand_2nd()->x86_operand_size();
  914. }
  915. }
  916. if ( size == 1 ) suffix = "b";
  917. else if ( size == 2 ) suffix = "w";
  918. else if ( size == 4 ) suffix = "l";
  919. else if ( size == 8 ) suffix = "q";
  920. else suffix = "";
  921. STRNCAT( buf, suffix, len );
  922. return ( strlen( buf ) );
  923. }
  924. int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
  925. enum x86_asm_format format){
  926. char str[MAX_OP_STRING];
  927. memset( buf, 0, len );
  928. STRNCAT( buf, insn->prefix_string, len );
  929. if ( format == att_syntax ) {
  930. format_att_mnemonic( insn, str, sizeof str );
  931. STRNCAT( buf, str, len );
  932. } else {
  933. STRNCAT( buf, insn->mnemonic, len );
  934. }
  935. return( strlen( buf ) );
  936. }
  937. struct op_string { char *buf; size_t len; };
  938. static void format_op_raw( x86_op_t *op, x86_insn_t *insn, void *arg ) {
  939. struct op_string * opstr = (struct op_string *) arg;
  940. format_operand_raw(op, insn, opstr->buf, opstr->len);
  941. }
  942. static int format_insn_note(x86_insn_t *insn, char *buf, int len){
  943. char note[32] = {0};
  944. int len_orig = len, note_len = 32;
  945. if ( insn->note & insn_note_ring0 ) {
  946. STRNCATF( note, "%s", "Ring0 ", note_len );
  947. }
  948. if ( insn->note & insn_note_smm ) {
  949. STRNCATF( note, "%s", "SMM ", note_len );
  950. }
  951. if ( insn->note & insn_note_serial ) {
  952. STRNCATF(note, "%s", "Serialize ", note_len );
  953. }
  954. STRNCATF( buf, "%s|", note, len );
  955. return( len_orig - len );
  956. }
  957. static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
  958. struct op_string opstr = { buf, len };
  959. int i;
  960. /* RAW style:
  961. * ADDRESS|OFFSET|SIZE|BYTES|
  962. * PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|
  963. * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|
  964. * STACK_MOD|STACK_MOD_VAL
  965. * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*
  966. *
  967. * Register values are encoded as:
  968. * NAME:TYPE:SIZE
  969. *
  970. * Effective addresses are encoded as:
  971. * disp(base_reg,index_reg,scale)
  972. */
  973. STRNCATF( buf, "0x%08" PRIX32 "|", insn->addr , len );
  974. STRNCATF( buf, "0x%08" PRIX32 "|", insn->offset, len );
  975. STRNCATF( buf, "%d|" , insn->size , len );
  976. /* print bytes */
  977. for ( i = 0; i < insn->size; i++ ) {
  978. STRNCATF( buf, "%02X ", insn->bytes[i], len );
  979. }
  980. STRNCAT( buf, "|", len );
  981. len -= format_insn_prefix_str( insn->prefix, buf, len );
  982. STRNCATF( buf, "|%s|", insn->prefix_string , len );
  983. STRNCATF( buf, "%s|", get_insn_group_str( insn->group ), len );
  984. STRNCATF( buf, "%s|", get_insn_type_str( insn->type ) , len );
  985. STRNCATF( buf, "%s|", insn->mnemonic , len );
  986. STRNCATF( buf, "%s|", get_insn_cpu_str( insn->cpu ) , len );
  987. STRNCATF( buf, "%s|", get_insn_isa_str( insn->isa ) , len );
  988. /* insn note */
  989. len -= format_insn_note( insn, buf, len );
  990. len -= format_insn_eflags_str( insn->flags_set, buf, len );
  991. STRNCAT( buf, "|", len );
  992. len -= format_insn_eflags_str( insn->flags_tested, buf, len );
  993. STRNCAT( buf, "|", len );
  994. STRNCATF( buf, "%d|", insn->stack_mod, len );
  995. STRNCATF( buf, "%" PRId32 "|", insn->stack_mod_val, len );
  996. opstr.len = len;
  997. insn->x86_operand_foreach( format_op_raw, &opstr, op_any );
  998. return( strlen (buf) );
  999. }
  1000. static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
  1001. char str[MAX_OP_XML_STRING];
  1002. int i;
  1003. STRNCAT( buf, "<x86_insn>\n", len );
  1004. STRNCATF( buf, "\t<address rva=\"0x%08" PRIX32 "\" ", insn->addr, len );
  1005. STRNCATF( buf, "offset=\"0x%08" PRIX32 "\" ", insn->offset, len );
  1006. STRNCATF( buf, "size=%d bytes=\"", insn->size, len );
  1007. for ( i = 0; i < insn->size; i++ ) {
  1008. STRNCATF( buf, "%02X ", insn->bytes[i], len );
  1009. }
  1010. STRNCAT( buf, "\"/>\n", len );
  1011. STRNCAT( buf, "\t<prefix type=\"", len );
  1012. len -= format_insn_prefix_str( insn->prefix, buf, len );
  1013. STRNCATF( buf, "\" string=\"%s\"/>\n", insn->prefix_string, len );
  1014. STRNCATF( buf, "\t<mnemonic group=\"%s\" ",
  1015. get_insn_group_str (insn->group), len );
  1016. STRNCATF( buf, "type=\"%s\" ", get_insn_type_str (insn->type), len );
  1017. STRNCATF( buf, "string=\"%s\"/>\n", insn->mnemonic, len );
  1018. STRNCAT( buf, "\t<flags type=set>\n", len );
  1019. STRNCAT( buf, "\t\t<flag name=\"", len );
  1020. len -= format_insn_eflags_str( insn->flags_set, buf, len );
  1021. STRNCAT( buf, "\"/>\n\t</flags>\n", len );
  1022. STRNCAT( buf, "\t<flags type=tested>\n", len );
  1023. STRNCAT( buf, "\t\t<flag name=\"", len );
  1024. len -= format_insn_eflags_str( insn->flags_tested, buf, len );
  1025. STRNCAT( buf, "\"/>\n\t</flags>\n", len );
  1026. if ( insn->x86_operand_1st() ) {
  1027. insn->x86_operand_1st()->x86_format_operand(str,
  1028. sizeof str, xml_syntax);
  1029. STRNCAT( buf, "\t<operand name=dest>\n", len );
  1030. STRNCAT( buf, str, len );
  1031. STRNCAT( buf, "\t</operand>\n", len );
  1032. }
  1033. if ( insn->x86_operand_2nd() ) {
  1034. insn->x86_operand_2nd()->x86_format_operand(str,sizeof str,
  1035. xml_syntax);
  1036. STRNCAT( buf, "\t<operand name=src>\n", len );
  1037. STRNCAT( buf, str, len );
  1038. STRNCAT( buf, "\t</operand>\n", len );
  1039. }
  1040. if ( insn->x86_operand_3rd() ) {
  1041. insn->x86_operand_3rd()->x86_format_operand(str,sizeof str,
  1042. xml_syntax);
  1043. STRNCAT( buf, "\t<operand name=imm>\n", len );
  1044. STRNCAT( buf, str, len );
  1045. STRNCAT( buf, "\t</operand>\n", len );
  1046. }
  1047. STRNCAT( buf, "</x86_insn>\n", len );
  1048. return strlen (buf);
  1049. }
  1050. int X86_Disasm::x86_format_header( char *buf, int len, enum x86_asm_format format ) {
  1051. switch (format) {
  1052. case att_syntax:
  1053. snprintf( buf, len, "MNEMONIC\tSRC, DEST, IMM" );
  1054. break;
  1055. case intel_syntax:
  1056. snprintf( buf, len, "MNEMONIC\tDEST, SRC, IMM" );
  1057. break;
  1058. case native_syntax:
  1059. snprintf( buf, len, "ADDRESS\tBYTES\tMNEMONIC\t"
  1060. "DEST\tSRC\tIMM" );
  1061. break;
  1062. case raw_syntax:
  1063. snprintf( buf, len, "ADDRESS|OFFSET|SIZE|BYTES|"
  1064. "PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|"
  1065. "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|"
  1066. "STACK_MOD|STACK_MOD_VAL"
  1067. "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*"
  1068. );
  1069. break;
  1070. case xml_syntax:
  1071. snprintf( buf, len,
  1072. "<x86_insn>"
  1073. "<address rva= offset= size= bytes=/>"
  1074. "<prefix type= string=/>"
  1075. "<mnemonic group= type= string= "
  1076. "cpu= isa= note= />"
  1077. "<flags type=set>"
  1078. "<flag name=>"
  1079. "</flags>"
  1080. "<stack_mod val= >"
  1081. "<flags type=tested>"
  1082. "<flag name=>"
  1083. "</flags>"
  1084. "<operand name=>"
  1085. "<register name= type= size=/>"
  1086. "<immediate type= value=/>"
  1087. "<relative_offset value=/>"
  1088. "<absolute_address value=>"
  1089. "<segment value=/>"
  1090. "</absolute_address>"
  1091. "<address_expression>"
  1092. "<segment value=/>"
  1093. "<base>"
  1094. "<register name= type= size=/>"
  1095. "</base>"
  1096. "<index>"
  1097. "<register name= type= size=/>"
  1098. "</index>"
  1099. "<scale>"
  1100. "<immediate value=/>"
  1101. "</scale>"
  1102. "<displacement>"
  1103. "<immediate value=/>"
  1104. "<address value=/>"
  1105. "</displacement>"
  1106. "</address_expression>"
  1107. "<segment_offset>"
  1108. "<address value=/>"
  1109. "</segment_offset>"
  1110. "</operand>"
  1111. "</x86_insn>"
  1112. );
  1113. break;
  1114. case unknown_syntax:
  1115. if ( len ) {
  1116. buf[0] = '\0';
  1117. }
  1118. break;
  1119. }
  1120. return( strlen(buf) );
  1121. }
  1122. int x86_insn_t::x86_format_insn( char *buf, int len,
  1123. enum x86_asm_format format ){
  1124. char str[MAX_OP_STRING];
  1125. x86_op_t *src, *dst;
  1126. int i;
  1127. memset(buf, 0, len);
  1128. if ( format == intel_syntax ) {
  1129. /* INTEL STYLE: mnemonic dest, src, imm */
  1130. STRNCAT( buf, prefix_string, len );
  1131. STRNCAT( buf, mnemonic, len );
  1132. STRNCAT( buf, "\t", len );
  1133. /* dest */
  1134. if ( (dst = x86_operand_1st()) && !(dst->flags.op_implied) ) {
  1135. dst->x86_format_operand(str, MAX_OP_STRING, format);
  1136. STRNCAT( buf, str, len );
  1137. }
  1138. /* src */
  1139. if ( (src = x86_operand_2nd()) ) {
  1140. if ( !(dst->flags.op_implied) ) {
  1141. STRNCAT( buf, ", ", len );
  1142. }
  1143. src->x86_format_operand( str, MAX_OP_STRING, format);
  1144. STRNCAT( buf, str, len );
  1145. }
  1146. /* imm */
  1147. if ( x86_operand_3rd()) {
  1148. STRNCAT( buf, ", ", len );
  1149. x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
  1150. STRNCAT( buf, str, len );
  1151. }
  1152. } else if ( format == att_syntax ) {
  1153. /* ATT STYLE: mnemonic src, dest, imm */
  1154. STRNCAT( buf, prefix_string, len );
  1155. format_att_mnemonic(this, str, MAX_OP_STRING);
  1156. STRNCATF( buf, "%s\t", str, len);
  1157. /* not sure which is correct? sometimes GNU as requires
  1158. * an imm as the first operand, sometimes as the third... */
  1159. /* imm */
  1160. if ( x86_operand_3rd() ) {
  1161. x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
  1162. STRNCAT( buf, str, len );
  1163. /* there is always 'dest' operand if there is 'src' */
  1164. STRNCAT( buf, ", ", len );
  1165. }
  1166. if ( (note & insn_note_nonswap ) == 0 ) {
  1167. /* regular AT&T style swap */
  1168. src = x86_operand_2nd();
  1169. dst = x86_operand_1st();
  1170. }
  1171. else {
  1172. /* special-case instructions */
  1173. src = x86_operand_1st();
  1174. dst = x86_operand_2nd();
  1175. }
  1176. /* src */
  1177. if ( src ) {
  1178. src->x86_format_operand(str, MAX_OP_STRING, format);
  1179. STRNCAT( buf, str, len );
  1180. /* there is always 'dest' operand if there is 'src' */
  1181. if ( dst && !(dst->flags.op_implied) ) {
  1182. STRNCAT( buf, ", ", len );
  1183. }
  1184. }
  1185. /* dest */
  1186. if ( dst && !(dst->flags.op_implied) ) {
  1187. dst->x86_format_operand(str, MAX_OP_STRING, format);
  1188. STRNCAT( buf, str, len );
  1189. }
  1190. } else if ( format == raw_syntax ) {
  1191. format_raw_insn( this, buf, len );
  1192. } else if ( format == xml_syntax ) {
  1193. format_xml_insn( this, buf, len );
  1194. } else { /* default to native */
  1195. /* NATIVE style: RVA\tBYTES\tMNEMONIC\tOPERANDS */
  1196. /* print address */
  1197. STRNCATF( buf, "%08" PRIX32 "\t", addr, len );
  1198. /* print bytes */
  1199. for ( i = 0; i < size; i++ ) {
  1200. STRNCATF( buf, "%02X ", bytes[i], len );
  1201. }
  1202. STRNCAT( buf, "\t", len );
  1203. /* print mnemonic */
  1204. STRNCAT( buf, prefix_string, len );
  1205. STRNCAT( buf, mnemonic, len );
  1206. STRNCAT( buf, "\t", len );
  1207. /* print operands */
  1208. /* dest */
  1209. if ( x86_operand_1st() ) {
  1210. x86_operand_1st()->x86_format_operand(str, MAX_OP_STRING,format);
  1211. STRNCATF( buf, "%s\t", str, len );
  1212. }
  1213. /* src */
  1214. if ( x86_operand_2nd() ) {
  1215. x86_operand_2nd()->x86_format_operand(str, MAX_OP_STRING,format);
  1216. STRNCATF( buf, "%s\t", str, len );
  1217. }
  1218. /* imm */
  1219. if ( x86_operand_3rd()) {
  1220. x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
  1221. STRNCAT( buf, str, len );
  1222. }
  1223. }
  1224. return( strlen( buf ) );
  1225. }