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