1 /* Disassembler for x86. 2 Copyright (C) 2007, 2008 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 *_str = (str); \ 297 size_t _len = strlen (_str); \ 298 if (unlikely (bufcnt + _len > bufsize)) \ 299 goto enomem; \ 300 memcpy (buf + bufcnt, str, _len); \ 301 bufcnt += _len; \ 302 } while (0) 303 304 305 int 306 i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 307 const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb, 308 void *outcbarg, void *symcbarg) 309 { 310 const char *save_fmt = fmt; 311 312 #define BUFSIZE 512 313 char initbuf[BUFSIZE]; 314 int prefixes; 315 size_t bufcnt; 316 size_t bufsize = BUFSIZE; 317 char *buf = initbuf; 318 const uint8_t *param_start; 319 320 struct output_data output_data = 321 { 322 .prefixes = &prefixes, 323 .bufp = buf, 324 .bufsize = bufsize, 325 .bufcntp = &bufcnt, 326 .param_start = ¶m_start, 327 .end = end 328 }; 329 330 int retval = 0; 331 while (1) 332 { 333 prefixes = 0; 334 335 const uint8_t *data = *startp; 336 const uint8_t *begin = data; 337 338 /* Recognize all prefixes. */ 339 int last_prefix_bit = 0; 340 while (data < end) 341 { 342 unsigned int i; 343 for (i = idx_cs; i < nknown_prefixes; ++i) 344 if (known_prefixes[i] == *data) 345 break; 346 if (i == nknown_prefixes) 347 break; 348 349 prefixes |= last_prefix_bit = 1 << i; 350 351 ++data; 352 } 353 354 #ifdef X86_64 355 if (data < end && (*data & 0xf0) == 0x40) 356 prefixes |= ((*data++) & 0xf) | has_rex; 357 #endif 358 359 bufcnt = 0; 360 size_t cnt = 0; 361 362 const uint8_t *curr = match_data; 363 const uint8_t *const match_end = match_data + sizeof (match_data); 364 365 assert (data <= end); 366 if (data == end) 367 { 368 if (prefixes != 0) 369 goto print_prefix; 370 371 retval = -1; 372 goto do_ret; 373 } 374 375 next_match: 376 while (curr < match_end) 377 { 378 uint_fast8_t len = *curr++; 379 const uint8_t *start = curr; 380 381 assert (len > 0); 382 assert (curr + 2 * len <= match_end); 383 384 const uint8_t *codep = data; 385 int correct_prefix = 0; 386 int opoff = 0; 387 388 if (data > begin && codep[-1] == curr[1] && curr[0] == 0xff) 389 { 390 /* We match a prefix byte. This is exactly one byte and 391 is matched exactly, without a mask. */ 392 --len; 393 start += 2; 394 opoff = 8; 395 396 curr += 2; 397 398 assert (last_prefix_bit != 0); 399 correct_prefix = last_prefix_bit; 400 } 401 402 size_t avail = len; 403 while (avail > 0) 404 { 405 uint_fast8_t masked = *codep++ & *curr++; 406 if (masked != *curr++) 407 { 408 not: 409 curr = start + 2 * len; 410 ++cnt; 411 goto next_match; 412 } 413 414 --avail; 415 if (codep == end && avail > 0) 416 goto do_ret; 417 } 418 419 if (len > end - data) 420 /* There is not enough data for the entire instruction. The 421 caller can figure this out by looking at the pointer into 422 the input data. */ 423 goto do_ret; 424 425 assert (correct_prefix == 0 426 || (prefixes & correct_prefix) != 0); 427 prefixes ^= correct_prefix; 428 429 if (0) 430 { 431 /* Resize the buffer. */ 432 char *oldbuf; 433 enomem: 434 oldbuf = buf; 435 if (buf == initbuf) 436 buf = malloc (2 * bufsize); 437 else 438 buf = realloc (buf, 2 * bufsize); 439 if (buf == NULL) 440 { 441 buf = oldbuf; 442 retval = ENOMEM; 443 goto do_ret; 444 } 445 bufsize *= 2; 446 447 output_data.bufp = buf; 448 output_data.bufsize = bufsize; 449 bufcnt = 0; 450 451 if (data == end) 452 { 453 assert (prefixes != 0); 454 goto print_prefix; 455 } 456 457 /* gcc is not clever enough to see the following variables 458 are not used uninitialized. */ 459 asm ("" 460 : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep), 461 "=mr" (start), "=mr" (len)); 462 } 463 464 size_t prefix_size = 0; 465 466 // XXXonly print as prefix if valid? 467 if ((prefixes & has_lock) != 0) 468 { 469 ADD_STRING ("lock "); 470 prefix_size += 5; 471 } 472 473 if (instrtab[cnt].rep) 474 { 475 if ((prefixes & has_rep) != 0) 476 { 477 ADD_STRING ("rep "); 478 prefix_size += 4; 479 } 480 } 481 else if (instrtab[cnt].repe 482 && (prefixes & (has_rep | has_repne)) != 0) 483 { 484 if ((prefixes & has_repne) != 0) 485 { 486 ADD_STRING ("repne "); 487 prefix_size += 6; 488 } 489 else if ((prefixes & has_rep) != 0) 490 { 491 ADD_STRING ("repe "); 492 prefix_size += 5; 493 } 494 } 495 else if ((prefixes & (has_rep | has_repne)) != 0) 496 { 497 uint_fast8_t byte; 498 print_prefix: 499 bufcnt = 0; 500 byte = *begin; 501 /* This is a prefix byte. Print it. */ 502 switch (byte) 503 { 504 case prefix_rep: 505 ADD_STRING ("rep"); 506 break; 507 case prefix_repne: 508 ADD_STRING ("repne"); 509 break; 510 case prefix_cs: 511 ADD_STRING ("cs"); 512 break; 513 case prefix_ds: 514 ADD_STRING ("ds"); 515 break; 516 case prefix_es: 517 ADD_STRING ("es"); 518 break; 519 case prefix_fs: 520 ADD_STRING ("fs"); 521 break; 522 case prefix_gs: 523 ADD_STRING ("gs"); 524 break; 525 case prefix_ss: 526 ADD_STRING ("ss"); 527 break; 528 case prefix_data16: 529 ADD_STRING ("data16"); 530 break; 531 case prefix_addr16: 532 ADD_STRING ("addr16"); 533 break; 534 case prefix_lock: 535 ADD_STRING ("lock"); 536 break; 537 #ifdef X86_64 538 case 0x40 ... 0x4f: 539 ADD_STRING ("rex"); 540 if (byte != 0x40) 541 { 542 ADD_CHAR ('.'); 543 if (byte & 0x8) 544 ADD_CHAR ('w'); 545 if (byte & 0x4) 546 ADD_CHAR ('r'); 547 if (byte & 0x3) 548 ADD_CHAR ('x'); 549 if (byte & 0x1) 550 ADD_CHAR ('b'); 551 } 552 break; 553 #endif 554 default: 555 /* Cannot happen. */ 556 puts ("unknown prefix"); 557 abort (); 558 } 559 data = begin + 1; 560 ++addr; 561 562 goto out; 563 } 564 565 /* We have a match. First determine how many bytes are 566 needed for the adressing mode. */ 567 param_start = codep; 568 if (instrtab[cnt].modrm) 569 { 570 uint_fast8_t modrm = codep[-1]; 571 572 #ifndef X86_64 573 if (likely ((prefixes & has_addr16) != 0)) 574 { 575 /* Account for displacement. */ 576 if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 577 param_start += 2; 578 else if ((modrm & 0xc0) == 0x40) 579 param_start += 1; 580 } 581 else 582 #endif 583 { 584 /* Account for SIB. */ 585 if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4) 586 param_start += 1; 587 588 /* Account for displacement. */ 589 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 590 || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5)) 591 param_start += 4; 592 else if ((modrm & 0xc0) == 0x40) 593 param_start += 1; 594 } 595 596 if (unlikely (param_start > end)) 597 goto not; 598 } 599 600 output_data.addr = addr + (data - begin); 601 output_data.data = data; 602 603 unsigned long string_end_idx = 0; 604 fmt = save_fmt; 605 while (*fmt != '\0') 606 { 607 if (*fmt != '%') 608 { 609 char ch = *fmt++; 610 if (ch == '\\') 611 { 612 switch ((ch = *fmt++)) 613 { 614 case '0' ... '7': 615 { 616 int val = ch - '0'; 617 ch = *fmt; 618 if (ch >= '0' && ch <= '7') 619 { 620 val *= 8; 621 val += ch - '0'; 622 ch = *++fmt; 623 if (ch >= '0' && ch <= '7' && val < 32) 624 { 625 val *= 8; 626 val += ch - '0'; 627 ++fmt; 628 } 629 } 630 ch = val; 631 } 632 break; 633 634 case 'n': 635 ch = '\n'; 636 break; 637 638 case 't': 639 ch = '\t'; 640 break; 641 642 default: 643 retval = EINVAL; 644 goto do_ret; 645 } 646 } 647 ADD_CHAR (ch); 648 continue; 649 } 650 ++fmt; 651 652 int width = 0; 653 while (isdigit (*fmt)) 654 width = width * 10 + (*fmt++ - '0'); 655 656 int prec = 0; 657 if (*fmt == '.') 658 while (isdigit (*++fmt)) 659 prec = prec * 10 + (*fmt - '0'); 660 661 size_t start_idx = bufcnt; 662 switch (*fmt++) 663 { 664 char mnebuf[16]; 665 const char *str; 666 667 case 'm': 668 /* Mnemonic. */ 669 670 if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID)) 671 { 672 switch (*data) 673 { 674 #ifdef X86_64 675 case 0x90: 676 if (prefixes & has_rex_b) 677 goto not; 678 str = "nop"; 679 break; 680 #endif 681 682 case 0x98: 683 #ifdef X86_64 684 if (prefixes == (has_rex_w | has_rex)) 685 { 686 str = "cltq"; 687 break; 688 } 689 #endif 690 if (prefixes & ~has_data16) 691 goto print_prefix; 692 str = prefixes & has_data16 ? "cbtw" : "cwtl"; 693 break; 694 695 case 0x99: 696 #ifdef X86_64 697 if (prefixes == (has_rex_w | has_rex)) 698 { 699 str = "cqto"; 700 break; 701 } 702 #endif 703 if (prefixes & ~has_data16) 704 goto print_prefix; 705 str = prefixes & has_data16 ? "cwtd" : "cltd"; 706 break; 707 708 case 0xe3: 709 if (prefixes & ~has_addr16) 710 goto print_prefix; 711 #ifdef X86_64 712 str = prefixes & has_addr16 ? "jecxz" : "jrcxz"; 713 #else 714 str = prefixes & has_addr16 ? "jcxz" : "jecxz"; 715 #endif 716 break; 717 718 case 0x0f: 719 if (data[1] == 0x0f) 720 { 721 /* AMD 3DNOW. We need one more byte. */ 722 if (param_start >= end) 723 goto not; 724 if (*param_start < AMD3DNOW_LOW_IDX 725 || *param_start > AMD3DNOW_HIGH_IDX) 726 goto not; 727 unsigned int idx 728 = amd3dnow[AMD3DNOW_IDX (*param_start)]; 729 if (idx == 0) 730 goto not; 731 str = amd3dnowstr + idx - 1; 732 /* Eat the immediate byte indicating the 733 operation. */ 734 ++param_start; 735 break; 736 } 737 #ifdef X86_64 738 if (data[1] == 0xc7) 739 { 740 str = ((prefixes & has_rex_w) 741 ? "cmpxchg16b" : "cmpxchg8b"); 742 break; 743 } 744 #endif 745 if (data[1] == 0xc2) 746 { 747 if (param_start >= end) 748 goto not; 749 if (*param_start > 7) 750 goto not; 751 static const char cmpops[][9] = 752 { 753 [0] = "cmpeq", 754 [1] = "cmplt", 755 [2] = "cmple", 756 [3] = "cmpunord", 757 [4] = "cmpneq", 758 [5] = "cmpnlt", 759 [6] = "cmpnle", 760 [7] = "cmpord" 761 }; 762 char *cp = stpcpy (mnebuf, cmpops[*param_start]); 763 if (correct_prefix & (has_rep | has_repne)) 764 *cp++ = 's'; 765 else 766 *cp++ = 'p'; 767 if (correct_prefix & (has_data16 | has_repne)) 768 *cp++ = 'd'; 769 else 770 *cp++ = 's'; 771 *cp = '\0'; 772 str = mnebuf; 773 /* Eat the immediate byte indicating the 774 operation. */ 775 ++param_start; 776 break; 777 } 778 779 default: 780 assert (! "INVALID not handled"); 781 } 782 } 783 else 784 str = mnestr.str + mneidx[instrtab[cnt].mnemonic]; 785 786 ADD_STRING (str); 787 788 switch (instrtab[cnt].suffix) 789 { 790 case suffix_none: 791 break; 792 793 case suffix_w: 794 if ((codep[-1] & 0xc0) != 0xc0) 795 { 796 char ch; 797 798 if (data[0] & 1) 799 { 800 if (prefixes & has_data16) 801 ch = 'w'; 802 #ifdef X86_64 803 else if (prefixes & has_rex_w) 804 ch = 'q'; 805 #endif 806 else 807 ch = 'l'; 808 } 809 else 810 ch = 'b'; 811 812 ADD_CHAR (ch); 813 } 814 break; 815 816 case suffix_w0: 817 if ((codep[-1] & 0xc0) != 0xc0) 818 ADD_CHAR ('l'); 819 break; 820 821 case suffix_w1: 822 if ((data[0] & 0x4) == 0) 823 ADD_CHAR ('l'); 824 break; 825 826 case suffix_W: 827 if (prefixes & has_data16) 828 { 829 ADD_CHAR ('w'); 830 prefixes &= ~has_data16; 831 } 832 #ifdef X86_64 833 else 834 ADD_CHAR ('q'); 835 #endif 836 break; 837 838 case suffix_W1: 839 if (prefixes & has_data16) 840 { 841 ADD_CHAR ('w'); 842 prefixes &= ~has_data16; 843 } 844 #ifdef X86_64 845 else if (prefixes & has_rex_w) 846 ADD_CHAR ('q'); 847 #endif 848 break; 849 850 case suffix_tttn:; 851 static const char tttn[16][3] = 852 { 853 "o", "no", "b", "ae", "e", "ne", "be", "a", 854 "s", "ns", "p", "np", "l", "ge", "le", "g" 855 }; 856 ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]); 857 break; 858 859 case suffix_D: 860 if ((codep[-1] & 0xc0) != 0xc0) 861 ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l'); 862 break; 863 864 default: 865 printf("unknown suffix %d\n", instrtab[cnt].suffix); 866 abort (); 867 } 868 869 string_end_idx = bufcnt; 870 break; 871 872 case 'o': 873 if (prec == 1 && instrtab[cnt].fct1 != 0) 874 { 875 /* First parameter. */ 876 if (instrtab[cnt].str1 != 0) 877 ADD_STRING (op1_str 878 + op1_str_idx[instrtab[cnt].str1 - 1]); 879 880 output_data.opoff1 = (instrtab[cnt].off1_1 881 + OFF1_1_BIAS - opoff); 882 output_data.opoff2 = (instrtab[cnt].off1_2 883 + OFF1_2_BIAS - opoff); 884 output_data.opoff3 = (instrtab[cnt].off1_3 885 + OFF1_3_BIAS - opoff); 886 int r = op1_fct[instrtab[cnt].fct1] (&output_data); 887 if (r < 0) 888 goto not; 889 if (r > 0) 890 goto enomem; 891 892 string_end_idx = bufcnt; 893 } 894 else if (prec == 2 && instrtab[cnt].fct2 != 0) 895 { 896 /* Second parameter. */ 897 if (instrtab[cnt].str2 != 0) 898 ADD_STRING (op2_str 899 + op2_str_idx[instrtab[cnt].str2 - 1]); 900 901 output_data.opoff1 = (instrtab[cnt].off2_1 902 + OFF2_1_BIAS - opoff); 903 output_data.opoff2 = (instrtab[cnt].off2_2 904 + OFF2_2_BIAS - opoff); 905 output_data.opoff3 = (instrtab[cnt].off2_3 906 + OFF2_3_BIAS - opoff); 907 int r = op2_fct[instrtab[cnt].fct2] (&output_data); 908 if (r < 0) 909 goto not; 910 if (r > 0) 911 goto enomem; 912 913 string_end_idx = bufcnt; 914 } 915 else if (prec == 3 && instrtab[cnt].fct3 != 0) 916 { 917 /* Third parameter. */ 918 if (instrtab[cnt].str3 != 0) 919 ADD_STRING (op3_str 920 + op3_str_idx[instrtab[cnt].str3 - 1]); 921 922 output_data.opoff1 = (instrtab[cnt].off3_1 923 + OFF3_1_BIAS - opoff); 924 output_data.opoff2 = (instrtab[cnt].off3_2 925 + OFF3_2_BIAS - opoff); 926 #ifdef OFF3_3_BITS 927 output_data.opoff3 = (instrtab[cnt].off3_3 928 + OFF3_3_BIAS - opoff); 929 #else 930 output_data.opoff3 = 0; 931 #endif 932 int r = op3_fct[instrtab[cnt].fct3] (&output_data); 933 if (r < 0) 934 goto not; 935 if (r > 0) 936 goto enomem; 937 938 string_end_idx = bufcnt; 939 } 940 else 941 bufcnt = string_end_idx; 942 break; 943 944 case 'e': 945 string_end_idx = bufcnt; 946 break; 947 948 case 'a': 949 /* Pad to requested column. */ 950 while (bufcnt < (size_t) width) 951 ADD_CHAR (' '); 952 width = 0; 953 break; 954 955 case 'l': 956 if (output_data.labelbuf != NULL 957 && output_data.labelbuf[0] != '\0') 958 { 959 ADD_STRING (output_data.labelbuf); 960 output_data.labelbuf[0] = '\0'; 961 string_end_idx = bufcnt; 962 } 963 else if (output_data.symaddr_use != addr_none) 964 { 965 GElf_Addr symaddr = output_data.symaddr; 966 if (output_data.symaddr_use >= addr_rel_symbolic) 967 symaddr += addr + param_start - begin; 968 969 // XXX Lookup symbol based on symaddr 970 const char *symstr = NULL; 971 if (symcb != NULL 972 && symcb (0 /* XXX */, 0 /* XXX */, symaddr, 973 &output_data.labelbuf, 974 &output_data.labelbufsize, symcbarg) == 0) 975 symstr = output_data.labelbuf; 976 977 size_t bufavail = bufsize - bufcnt; 978 int r = 0; 979 if (symstr != NULL) 980 r = snprintf (&buf[bufcnt], bufavail, "# <%s>", 981 symstr); 982 else if (output_data.symaddr_use == addr_abs_always 983 || output_data.symaddr_use == addr_rel_always) 984 r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64, 985 (uint64_t) symaddr); 986 987 if (r < 0) 988 goto not; 989 if ((size_t) r >= bufavail) 990 goto enomem; 991 bufcnt += r; 992 string_end_idx = bufcnt; 993 994 output_data.symaddr_use = addr_none; 995 } 996 break; 997 } 998 999 /* Pad according to the specified width. */ 1000 while (bufcnt + prefix_size < start_idx + width) 1001 ADD_CHAR (' '); 1002 prefix_size = 0; 1003 } 1004 1005 if ((prefixes & SEGMENT_PREFIXES) != 0) 1006 goto print_prefix; 1007 1008 assert (string_end_idx != ~0ul); 1009 bufcnt = string_end_idx; 1010 1011 addr += param_start - begin; 1012 data = param_start; 1013 1014 goto out; 1015 } 1016 1017 /* Invalid (or at least unhandled) opcode. */ 1018 if (prefixes != 0) 1019 goto print_prefix; 1020 assert (*startp == data); 1021 ++data; 1022 ADD_STRING ("(bad)"); 1023 addr += data - begin; 1024 1025 out: 1026 if (bufcnt == bufsize) 1027 goto enomem; 1028 buf[bufcnt] = '\0'; 1029 1030 *startp = data; 1031 retval = outcb (buf, bufcnt, outcbarg); 1032 if (retval != 0) 1033 goto do_ret; 1034 } 1035 1036 do_ret: 1037 free (output_data.labelbuf); 1038 if (buf != initbuf) 1039 free (buf); 1040 1041 return retval; 1042 } 1043