Lines 32-37
Link Here
|
32 |
|
32 |
|
33 |
#include "config-host.h" |
33 |
#include "config-host.h" |
34 |
|
34 |
|
|
|
35 |
//#define DEBUG_OP |
36 |
|
35 |
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross |
37 |
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross |
36 |
compilation */ |
38 |
compilation */ |
37 |
#if defined(CONFIG_WIN32) |
39 |
#if defined(CONFIG_WIN32) |
Lines 1343-1348
Link Here
|
1343 |
#endif |
1345 |
#endif |
1344 |
|
1346 |
|
1345 |
|
1347 |
|
|
|
1348 |
#if defined(HOST_I386) || defined(HOST_X86_64) |
1349 |
|
1350 |
/* This byte is the first byte of an instruction. */ |
1351 |
#define FLAG_INSN (1 << 0) |
1352 |
/* This byte has been processed as part of an instruction. */ |
1353 |
#define FLAG_SCANNED (1 << 1) |
1354 |
/* This instruction is a return instruction. Gcc cometimes generates prefix |
1355 |
bytes, so may be more than one byte long. */ |
1356 |
#define FLAG_RET (1 << 2) |
1357 |
/* This is either the target of a jump, or the preceeding instruction uses |
1358 |
a pc-relative offset. */ |
1359 |
#define FLAG_TARGET (1 << 3) |
1360 |
/* This is a magic instruction that needs fixing up. */ |
1361 |
#define FLAG_EXIT (1 << 4) |
1362 |
/* This instruction clobbers the stack pointer. */ |
1363 |
/* XXX only supports push, pop, add/sub $imm,%esp */ |
1364 |
#define FLAG_STACK (1 << 5) |
1365 |
#define MAX_EXITS 5 |
1366 |
|
1367 |
static void |
1368 |
bad_opcode(const char *name, uint32_t op) |
1369 |
{ |
1370 |
error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name); |
1371 |
} |
1372 |
|
1373 |
/* Mark len bytes as scanned, Returns insn_size + len. Reports an error |
1374 |
if these bytes have already been scanned. */ |
1375 |
static int |
1376 |
eat_bytes(const char *name, char *flags, int insn, int insn_size, int len) |
1377 |
{ |
1378 |
while (len > 0) { |
1379 |
/* This should never occur in sane code. */ |
1380 |
if (flags[insn + insn_size] & FLAG_SCANNED) |
1381 |
error ("Overlapping instructions in %s", name); |
1382 |
flags[insn + insn_size] |= FLAG_SCANNED; |
1383 |
insn_size++; |
1384 |
len--; |
1385 |
} |
1386 |
return insn_size; |
1387 |
} |
1388 |
|
1389 |
static void |
1390 |
trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn, |
1391 |
int len) |
1392 |
{ |
1393 |
uint8_t *ptr; |
1394 |
uint8_t op; |
1395 |
int modrm; |
1396 |
int is_prefix; |
1397 |
int op_size; |
1398 |
int addr_size; |
1399 |
int insn_size; |
1400 |
int is_ret; |
1401 |
int is_condjmp; |
1402 |
int is_jmp; |
1403 |
int is_exit; |
1404 |
int is_pcrel; |
1405 |
int is_stack; |
1406 |
int immed; |
1407 |
int seen_rexw; |
1408 |
int32_t disp; |
1409 |
|
1410 |
ptr = start_p + insn; |
1411 |
/* nonzero if this insn has a ModR/M byte. */ |
1412 |
modrm = 1; |
1413 |
/* The size of the immediate value in this instruction. */ |
1414 |
immed = 0; |
1415 |
/* The operand size. */ |
1416 |
op_size = 4; |
1417 |
/* The address size */ |
1418 |
addr_size = 4; |
1419 |
/* The total length of this instruction. */ |
1420 |
insn_size = 0; |
1421 |
is_prefix = 1; |
1422 |
is_ret = 0; |
1423 |
is_condjmp = 0; |
1424 |
is_jmp = 0; |
1425 |
is_exit = 0; |
1426 |
seen_rexw = 0; |
1427 |
is_pcrel = 0; |
1428 |
is_stack = 0; |
1429 |
|
1430 |
while (is_prefix) { |
1431 |
op = ptr[insn_size]; |
1432 |
insn_size = eat_bytes(name, flags, insn, insn_size, 1); |
1433 |
is_prefix = 0; |
1434 |
switch (op >> 4) { |
1435 |
case 0: |
1436 |
case 1: |
1437 |
case 2: |
1438 |
case 3: |
1439 |
if (op == 0x0f) { |
1440 |
/* two-byte opcode. */ |
1441 |
op = ptr[insn_size]; |
1442 |
insn_size = eat_bytes(name, flags, insn, insn_size, 1); |
1443 |
switch (op >> 4) { |
1444 |
case 0: |
1445 |
if ((op & 0xf) > 3) |
1446 |
modrm = 0; |
1447 |
break; |
1448 |
case 1: /* vector move or prefetch */ |
1449 |
case 2: /* various moves and vector compares. */ |
1450 |
case 4: /* cmov */ |
1451 |
case 5: /* vector instructions */ |
1452 |
case 6: |
1453 |
case 13: |
1454 |
case 14: |
1455 |
case 15: |
1456 |
break; |
1457 |
case 7: /* mmx */ |
1458 |
if (op & 0x77) /* emms */ |
1459 |
modrm = 0; |
1460 |
break; |
1461 |
case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */ |
1462 |
modrm = 0; |
1463 |
break; |
1464 |
case 8: /* long conditional jump */ |
1465 |
is_condjmp = 1; |
1466 |
immed = op_size; |
1467 |
modrm = 0; |
1468 |
break; |
1469 |
case 9: /* setcc */ |
1470 |
break; |
1471 |
case 10: |
1472 |
switch (op & 0x7) { |
1473 |
case 0: /* push fs/gs */ |
1474 |
case 1: /* pop fs/gs */ |
1475 |
is_stack = 1; |
1476 |
case 2: /* cpuid/rsm */ |
1477 |
modrm = 0; |
1478 |
break; |
1479 |
case 4: /* shld/shrd immediate */ |
1480 |
immed = 1; |
1481 |
break; |
1482 |
default: /* Normal instructions with a ModR/M byte. */ |
1483 |
break; |
1484 |
} |
1485 |
break; |
1486 |
case 11: |
1487 |
switch (op & 0xf) { |
1488 |
case 10: /* bt, bts, btr, btc */ |
1489 |
immed = 1; |
1490 |
break; |
1491 |
default: |
1492 |
/* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr |
1493 |
undefined, and movsx */ |
1494 |
break; |
1495 |
} |
1496 |
break; |
1497 |
case 12: |
1498 |
if (op & 8) { |
1499 |
/* bswap */ |
1500 |
modrm = 0; |
1501 |
} else { |
1502 |
switch (op & 0x7) { |
1503 |
case 2: |
1504 |
case 4: |
1505 |
case 5: |
1506 |
case 6: |
1507 |
immed = 1; |
1508 |
break; |
1509 |
default: |
1510 |
break; |
1511 |
} |
1512 |
} |
1513 |
break; |
1514 |
} |
1515 |
} else if ((op & 0x07) <= 0x3) { |
1516 |
/* General arithmentic ax. */ |
1517 |
} else if ((op & 0x07) <= 0x5) { |
1518 |
/* General arithmetic ax, immediate. */ |
1519 |
if (op & 0x01) |
1520 |
immed = op_size; |
1521 |
else |
1522 |
immed = 1; |
1523 |
modrm = 0; |
1524 |
} else if ((op & 0x23) == 0x22) { |
1525 |
/* Segment prefix. */ |
1526 |
is_prefix = 1; |
1527 |
} else { |
1528 |
/* Segment register push/pop or DAA/AAA/DAS/AAS. */ |
1529 |
modrm = 0; |
1530 |
} |
1531 |
break; |
1532 |
|
1533 |
#if defined(HOST_X86_64) |
1534 |
case 4: /* rex prefix. */ |
1535 |
is_prefix = 1; |
1536 |
/* The address/operand size is actually 64-bit, but the immediate |
1537 |
values in the instruction are still 32-bit. */ |
1538 |
op_size = 4; |
1539 |
addr_size = 4; |
1540 |
if (op & 8) |
1541 |
seen_rexw = 1; |
1542 |
break; |
1543 |
#else |
1544 |
case 4: /* inc/dec register. */ |
1545 |
#endif |
1546 |
case 5: /* push/pop general register. */ |
1547 |
modrm = 0; |
1548 |
is_stack = 1; |
1549 |
break; |
1550 |
|
1551 |
case 6: |
1552 |
switch (op & 0x0f) { |
1553 |
case 0: /* pusha */ |
1554 |
case 1: /* popa */ |
1555 |
modrm = 0; |
1556 |
is_stack = 1; |
1557 |
break; |
1558 |
case 2: /* bound */ |
1559 |
case 3: /* arpl */ |
1560 |
break; |
1561 |
case 4: /* FS */ |
1562 |
case 5: /* GS */ |
1563 |
is_prefix = 1; |
1564 |
break; |
1565 |
case 6: /* opcode size prefix. */ |
1566 |
op_size = 2; |
1567 |
is_prefix = 1; |
1568 |
break; |
1569 |
case 7: /* Address size prefix. */ |
1570 |
addr_size = 2; |
1571 |
is_prefix = 1; |
1572 |
break; |
1573 |
case 8: /* push immediate */ |
1574 |
immed = op_size; |
1575 |
modrm = 0; |
1576 |
is_stack = 1; |
1577 |
break; |
1578 |
case 10: /* push 8-bit immediate */ |
1579 |
immed = 1; |
1580 |
modrm = 0; |
1581 |
is_stack = 1; |
1582 |
break; |
1583 |
case 9: /* imul immediate */ |
1584 |
immed = op_size; |
1585 |
break; |
1586 |
case 11: /* imul 8-bit immediate */ |
1587 |
immed = 1; |
1588 |
break; |
1589 |
case 12: /* insb */ |
1590 |
case 13: /* insw */ |
1591 |
case 14: /* outsb */ |
1592 |
case 15: /* outsw */ |
1593 |
modrm = 0; |
1594 |
break; |
1595 |
} |
1596 |
break; |
1597 |
|
1598 |
case 7: /* Short conditional jump. */ |
1599 |
is_condjmp = 1; |
1600 |
immed = 1; |
1601 |
modrm = 0; |
1602 |
break; |
1603 |
|
1604 |
case 8: |
1605 |
if ((op & 0xf) <= 3) { |
1606 |
/* arithmetic immediate. */ |
1607 |
if ((op & 3) == 1) |
1608 |
immed = op_size; |
1609 |
else |
1610 |
immed = 1; |
1611 |
if (op == 0x81 || op == 0x83) { |
1612 |
/* add, sub */ |
1613 |
op = ptr[insn_size]; |
1614 |
switch ((op >> 3) & 7) { |
1615 |
case 0: |
1616 |
case 5: |
1617 |
is_stack = (op & 7) == 4; |
1618 |
break; |
1619 |
} |
1620 |
} |
1621 |
} |
1622 |
else if ((op & 0xf) == 0xf) { |
1623 |
/* pop general. */ |
1624 |
is_stack = 1; |
1625 |
} |
1626 |
/* else test, xchg, mov, lea. */ |
1627 |
break; |
1628 |
|
1629 |
case 9: |
1630 |
/* Various single-byte opcodes with no modrm byte. */ |
1631 |
modrm = 0; |
1632 |
if (op == 10) { |
1633 |
/* Call */ |
1634 |
immed = 4; |
1635 |
} |
1636 |
break; |
1637 |
|
1638 |
case 10: |
1639 |
switch ((op & 0xe) >> 1) { |
1640 |
case 0: /* mov absoliute immediate. */ |
1641 |
case 1: |
1642 |
if (seen_rexw) |
1643 |
immed = 8; |
1644 |
else |
1645 |
immed = addr_size; |
1646 |
break; |
1647 |
case 4: /* test immediate. */ |
1648 |
if (op & 1) |
1649 |
immed = op_size; |
1650 |
else |
1651 |
immed = 1; |
1652 |
break; |
1653 |
default: /* Various string ops. */ |
1654 |
break; |
1655 |
} |
1656 |
modrm = 0; |
1657 |
break; |
1658 |
|
1659 |
case 11: /* move immediate to register */ |
1660 |
if (op & 8) { |
1661 |
if (seen_rexw) |
1662 |
immed = 8; |
1663 |
else |
1664 |
immed = op_size; |
1665 |
} else { |
1666 |
immed = 1; |
1667 |
} |
1668 |
modrm = 0; |
1669 |
break; |
1670 |
|
1671 |
case 12: |
1672 |
switch (op & 0xf) { |
1673 |
case 0: /* shift immediate */ |
1674 |
case 1: |
1675 |
immed = 1; |
1676 |
break; |
1677 |
case 2: /* ret immediate */ |
1678 |
immed = 2; |
1679 |
modrm = 0; |
1680 |
bad_opcode(name, op); |
1681 |
break; |
1682 |
case 3: /* ret */ |
1683 |
modrm = 0; |
1684 |
is_ret = 1; |
1685 |
case 4: /* les */ |
1686 |
case 5: /* lds */ |
1687 |
break; |
1688 |
case 6: /* mov immediate byte */ |
1689 |
immed = 1; |
1690 |
break; |
1691 |
case 7: /* mov immediate */ |
1692 |
immed = op_size; |
1693 |
break; |
1694 |
case 8: /* enter */ |
1695 |
/* TODO: Is this right? */ |
1696 |
immed = 3; |
1697 |
modrm = 0; |
1698 |
break; |
1699 |
case 10: /* retf immediate */ |
1700 |
immed = 2; |
1701 |
modrm = 0; |
1702 |
bad_opcode(name, op); |
1703 |
break; |
1704 |
case 13: /* int */ |
1705 |
immed = 1; |
1706 |
modrm = 0; |
1707 |
break; |
1708 |
case 11: /* retf */ |
1709 |
case 15: /* iret */ |
1710 |
modrm = 0; |
1711 |
bad_opcode(name, op); |
1712 |
break; |
1713 |
default: /* leave, int3 or into */ |
1714 |
modrm = 0; |
1715 |
break; |
1716 |
} |
1717 |
break; |
1718 |
|
1719 |
case 13: |
1720 |
if ((op & 0xf) >= 8) { |
1721 |
/* Coprocessor escape. For our purposes this is just a normal |
1722 |
instruction with a ModR/M byte. */ |
1723 |
} else if ((op & 0xf) >= 4) { |
1724 |
/* AAM, AAD or XLAT */ |
1725 |
modrm = 0; |
1726 |
} |
1727 |
/* else shift instruction */ |
1728 |
break; |
1729 |
|
1730 |
case 14: |
1731 |
switch ((op & 0xc) >> 2) { |
1732 |
case 0: /* loop or jcxz */ |
1733 |
is_condjmp = 1; |
1734 |
immed = 1; |
1735 |
break; |
1736 |
case 1: /* in/out immed */ |
1737 |
immed = 1; |
1738 |
break; |
1739 |
case 2: /* call or jmp */ |
1740 |
switch (op & 3) { |
1741 |
case 0: /* call */ |
1742 |
immed = op_size; |
1743 |
break; |
1744 |
case 1: /* long jump */ |
1745 |
immed = 4; |
1746 |
is_jmp = 1; |
1747 |
break; |
1748 |
case 2: /* far jmp */ |
1749 |
bad_opcode(name, op); |
1750 |
break; |
1751 |
case 3: /* short jmp */ |
1752 |
immed = 1; |
1753 |
is_jmp = 1; |
1754 |
break; |
1755 |
} |
1756 |
break; |
1757 |
case 3: /* in/out register */ |
1758 |
break; |
1759 |
} |
1760 |
modrm = 0; |
1761 |
break; |
1762 |
|
1763 |
case 15: |
1764 |
switch ((op & 0xe) >> 1) { |
1765 |
case 0: |
1766 |
case 1: |
1767 |
is_prefix = 1; |
1768 |
break; |
1769 |
case 2: |
1770 |
case 4: |
1771 |
case 5: |
1772 |
case 6: |
1773 |
modrm = 0; |
1774 |
/* Some privileged insns are used as markers. */ |
1775 |
switch (op) { |
1776 |
case 0xf4: /* hlt: Exit translation block. */ |
1777 |
is_exit = 1; |
1778 |
break; |
1779 |
case 0xfa: /* cli: Jump to label. */ |
1780 |
is_exit = 1; |
1781 |
immed = 4; |
1782 |
break; |
1783 |
case 0xfb: /* sti: TB patch jump. */ |
1784 |
/* Mark the insn for patching, but continue sscanning. */ |
1785 |
flags[insn] |= FLAG_EXIT; |
1786 |
immed = 4; |
1787 |
break; |
1788 |
} |
1789 |
break; |
1790 |
case 3: /* unary grp3 */ |
1791 |
if ((ptr[insn_size] & 0x38) == 0) { |
1792 |
if (op == 0xf7) |
1793 |
immed = op_size; |
1794 |
else |
1795 |
immed = 1; /* test immediate */ |
1796 |
} |
1797 |
break; |
1798 |
case 7: /* inc/dec grp4/5 */ |
1799 |
/* TODO: This includes indirect jumps. We should fail if we |
1800 |
encounter one of these. */ |
1801 |
break; |
1802 |
} |
1803 |
break; |
1804 |
} |
1805 |
} |
1806 |
|
1807 |
if (modrm) { |
1808 |
if (addr_size != 4) |
1809 |
error("16-bit addressing mode used in %s", name); |
1810 |
|
1811 |
disp = 0; |
1812 |
modrm = ptr[insn_size]; |
1813 |
insn_size = eat_bytes(name, flags, insn, insn_size, 1); |
1814 |
modrm &= 0xc7; |
1815 |
switch ((modrm & 0xc0) >> 6) { |
1816 |
case 0: |
1817 |
if (modrm == 5) |
1818 |
disp = 4; |
1819 |
break; |
1820 |
case 1: |
1821 |
disp = 1; |
1822 |
break; |
1823 |
case 2: |
1824 |
disp = 4; |
1825 |
break; |
1826 |
} |
1827 |
if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) { |
1828 |
/* SIB byte */ |
1829 |
if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) { |
1830 |
disp = 4; |
1831 |
is_pcrel = 1; |
1832 |
} |
1833 |
insn_size = eat_bytes(name, flags, insn, insn_size, 1); |
1834 |
} |
1835 |
insn_size = eat_bytes(name, flags, insn, insn_size, disp); |
1836 |
} |
1837 |
insn_size = eat_bytes(name, flags, insn, insn_size, immed); |
1838 |
if (is_condjmp || is_jmp) { |
1839 |
if (immed == 1) { |
1840 |
disp = (int8_t)*(ptr + insn_size - 1); |
1841 |
} else { |
1842 |
disp = (((int32_t)*(ptr + insn_size - 1)) << 24) |
1843 |
| (((int32_t)*(ptr + insn_size - 2)) << 16) |
1844 |
| (((int32_t)*(ptr + insn_size - 3)) << 8) |
1845 |
| *(ptr + insn_size - 4); |
1846 |
} |
1847 |
disp += insn_size; |
1848 |
/* Jumps to external symbols point to the address of the offset |
1849 |
before relocation. */ |
1850 |
/* ??? These are probably a tailcall. We could fix them up by |
1851 |
replacing them with jmp to EOB + call, but it's easier to just |
1852 |
prevent the compiler generating them. */ |
1853 |
if (disp == 1) |
1854 |
error("Unconditional jump (sibcall?) in %s", name); |
1855 |
disp += insn; |
1856 |
if (disp < 0 || disp > len) |
1857 |
error("Jump outside instruction in %s", name); |
1858 |
|
1859 |
if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED) |
1860 |
error("Overlapping instructions in %s", name); |
1861 |
|
1862 |
flags[disp] |= (FLAG_INSN | FLAG_TARGET); |
1863 |
is_pcrel = 1; |
1864 |
} |
1865 |
if (is_pcrel) { |
1866 |
/* Mark the following insn as a jump target. This will stop |
1867 |
this instruction being moved. */ |
1868 |
flags[insn + insn_size] |= FLAG_TARGET; |
1869 |
} |
1870 |
if (is_ret) |
1871 |
flags[insn] |= FLAG_RET; |
1872 |
|
1873 |
if (is_exit) |
1874 |
flags[insn] |= FLAG_EXIT; |
1875 |
|
1876 |
if (is_stack) |
1877 |
flags[insn] |= FLAG_STACK; |
1878 |
|
1879 |
if (!(is_jmp || is_ret || is_exit)) |
1880 |
flags[insn + insn_size] |= FLAG_INSN; |
1881 |
} |
1882 |
|
1883 |
/* Scan a function body. Returns the position of the return sequence. |
1884 |
Sets *patch_bytes to the number of bytes that need to be copied from that |
1885 |
location. If no patching is required (ie. the return is the last insn) |
1886 |
*patch_bytes will be set to -1. *plen is the number of code bytes to copy. |
1887 |
*/ |
1888 |
static int trace_i386_op(const char * name, uint8_t *start_p, int *plen, |
1889 |
int *patch_bytes, int *exit_addrs) |
1890 |
{ |
1891 |
char *flags; |
1892 |
int more; |
1893 |
int insn; |
1894 |
int retpos; |
1895 |
int bytes; |
1896 |
int num_exits; |
1897 |
int len; |
1898 |
int last_insn; |
1899 |
int stack_clobbered; |
1900 |
|
1901 |
len = *plen; |
1902 |
flags = malloc(len + 1); |
1903 |
memset(flags, 0, len + 1); |
1904 |
flags[0] |= FLAG_INSN; |
1905 |
more = 1; |
1906 |
while (more) { |
1907 |
more = 0; |
1908 |
for (insn = 0; insn < len; insn++) { |
1909 |
if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) { |
1910 |
trace_i386_insn(name, start_p, flags, insn, len); |
1911 |
more = 1; |
1912 |
} |
1913 |
} |
1914 |
} |
1915 |
|
1916 |
/* Strip any unused code at the end of the function. */ |
1917 |
while (len > 0 && flags[len - 1] == 0) |
1918 |
len--; |
1919 |
|
1920 |
retpos = -1; |
1921 |
num_exits = 0; |
1922 |
last_insn = 0; |
1923 |
stack_clobbered = 0; |
1924 |
for (insn = 0; insn < len; insn++) { |
1925 |
if (flags[insn] & FLAG_RET) { |
1926 |
/* ??? In theory it should be possible to handle multiple return |
1927 |
points. In practice it's not worth the effort. */ |
1928 |
if (retpos != -1) |
1929 |
error("Multiple return instructions in %s", name); |
1930 |
retpos = insn; |
1931 |
} |
1932 |
if (flags[insn] & FLAG_EXIT) { |
1933 |
if (stack_clobbered) |
1934 |
error("Stack clobbered in %s", name); |
1935 |
if (num_exits == MAX_EXITS) |
1936 |
error("Too many block exits in %s", name); |
1937 |
exit_addrs[num_exits] = insn; |
1938 |
num_exits++; |
1939 |
} |
1940 |
if (flags[insn] & FLAG_INSN) |
1941 |
last_insn = insn; |
1942 |
if (flags[insn] & FLAG_STACK) |
1943 |
stack_clobbered = 1; |
1944 |
} |
1945 |
|
1946 |
exit_addrs[num_exits] = -1; |
1947 |
if (retpos == -1) { |
1948 |
if (num_exits == 0) { |
1949 |
error ("No return instruction found in %s", name); |
1950 |
} else { |
1951 |
retpos = len; |
1952 |
last_insn = len; |
1953 |
} |
1954 |
} |
1955 |
|
1956 |
/* If the return instruction is the last instruction we can just |
1957 |
remove it. */ |
1958 |
if (retpos == last_insn) |
1959 |
*patch_bytes = -1; |
1960 |
else |
1961 |
*patch_bytes = 0; |
1962 |
|
1963 |
/* Back up over any nop instructions. */ |
1964 |
while (retpos > 0 |
1965 |
&& (flags[retpos] & FLAG_TARGET) == 0 |
1966 |
&& (flags[retpos - 1] & FLAG_INSN) != 0 |
1967 |
&& start_p[retpos - 1] == 0x90) { |
1968 |
retpos--; |
1969 |
} |
1970 |
|
1971 |
if (*patch_bytes == -1) { |
1972 |
*plen = retpos; |
1973 |
free (flags); |
1974 |
return retpos; |
1975 |
} |
1976 |
*plen = len; |
1977 |
|
1978 |
/* The ret is in the middle of the function. Find four more bytes that |
1979 |
so the ret can be replaced by a jmp. */ |
1980 |
/* ??? Use a short jump where possible. */ |
1981 |
bytes = 4; |
1982 |
insn = retpos + 1; |
1983 |
/* We can clobber everything up to the next jump target. */ |
1984 |
while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) { |
1985 |
insn++; |
1986 |
bytes--; |
1987 |
} |
1988 |
if (bytes > 0) { |
1989 |
/* ???: Strip out nop blocks. */ |
1990 |
/* We can't do the replacement without clobbering anything important. |
1991 |
Copy preceeding instructions(s) to give us some space. */ |
1992 |
while (retpos > 0) { |
1993 |
/* If this byte is the target of a jmp we can't move it. */ |
1994 |
if (flags[retpos] & FLAG_TARGET) |
1995 |
break; |
1996 |
|
1997 |
(*patch_bytes)++; |
1998 |
bytes--; |
1999 |
retpos--; |
2000 |
|
2001 |
/* Break out of the loop if we have enough space and this is either |
2002 |
the first byte of an instruction or a pad byte. */ |
2003 |
if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED |
2004 |
&& bytes <= 0) { |
2005 |
break; |
2006 |
} |
2007 |
} |
2008 |
} |
2009 |
|
2010 |
if (bytes > 0) |
2011 |
error("Unable to replace ret with jmp in %s\n", name); |
2012 |
|
2013 |
free(flags); |
2014 |
return retpos; |
2015 |
} |
2016 |
|
2017 |
#endif |
2018 |
|
1346 |
#define MAX_ARGS 3 |
2019 |
#define MAX_ARGS 3 |
1347 |
|
2020 |
|
1348 |
/* generate op code */ |
2021 |
/* generate op code */ |
Lines 1356-1361
Link Here
|
1356 |
uint8_t args_present[MAX_ARGS]; |
2029 |
uint8_t args_present[MAX_ARGS]; |
1357 |
const char *sym_name, *p; |
2030 |
const char *sym_name, *p; |
1358 |
EXE_RELOC *rel; |
2031 |
EXE_RELOC *rel; |
|
|
2032 |
#if defined(HOST_I386) || defined(HOST_X86_64) |
2033 |
int patch_bytes; |
2034 |
int retpos; |
2035 |
int exit_addrs[MAX_EXITS]; |
2036 |
#endif |
1359 |
|
2037 |
|
1360 |
/* Compute exact size excluding prologue and epilogue instructions. |
2038 |
/* Compute exact size excluding prologue and epilogue instructions. |
1361 |
* Increment start_offset to skip epilogue instructions, then compute |
2039 |
* Increment start_offset to skip epilogue instructions, then compute |
Lines 1366-1398
Link Here
|
1366 |
p_end = p_start + size; |
2044 |
p_end = p_start + size; |
1367 |
start_offset = offset; |
2045 |
start_offset = offset; |
1368 |
#if defined(HOST_I386) || defined(HOST_X86_64) |
2046 |
#if defined(HOST_I386) || defined(HOST_X86_64) |
1369 |
#ifdef CONFIG_FORMAT_COFF |
|
|
1370 |
{ |
1371 |
uint8_t *p; |
1372 |
p = p_end - 1; |
1373 |
if (p == p_start) |
1374 |
error("empty code for %s", name); |
1375 |
while (*p != 0xc3) { |
1376 |
p--; |
1377 |
if (p <= p_start) |
1378 |
error("ret or jmp expected at the end of %s", name); |
1379 |
} |
1380 |
copy_size = p - p_start; |
1381 |
} |
1382 |
#else |
1383 |
{ |
2047 |
{ |
1384 |
int len; |
2048 |
int len; |
1385 |
len = p_end - p_start; |
2049 |
len = p_end - p_start; |
1386 |
if (len == 0) |
2050 |
retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs); |
1387 |
error("empty code for %s", name); |
|
|
1388 |
if (p_end[-1] == 0xc3) { |
1389 |
len--; |
1390 |
} else { |
1391 |
error("ret or jmp expected at the end of %s", name); |
1392 |
} |
1393 |
copy_size = len; |
2051 |
copy_size = len; |
1394 |
} |
2052 |
} |
1395 |
#endif |
|
|
1396 |
#elif defined(HOST_PPC) |
2053 |
#elif defined(HOST_PPC) |
1397 |
{ |
2054 |
{ |
1398 |
uint8_t *p; |
2055 |
uint8_t *p; |
Lines 1596-1601
Link Here
|
1596 |
} |
2253 |
} |
1597 |
|
2254 |
|
1598 |
if (gen_switch == 2) { |
2255 |
if (gen_switch == 2) { |
|
|
2256 |
#if defined(HOST_I386) || defined(HOST_X86_64) |
2257 |
if (patch_bytes != -1) |
2258 |
copy_size += patch_bytes; |
2259 |
#ifdef DEBUG_OP |
2260 |
copy_size += 2; |
2261 |
#endif |
2262 |
#endif |
1599 |
fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size); |
2263 |
fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size); |
1600 |
} else if (gen_switch == 1) { |
2264 |
} else if (gen_switch == 1) { |
1601 |
|
2265 |
|
Lines 1800-1806
Link Here
|
1800 |
#error unsupport object format |
2464 |
#error unsupport object format |
1801 |
#endif |
2465 |
#endif |
1802 |
} |
2466 |
} |
|
|
2467 |
} |
2468 |
/* Replace the marker instructions with the actual opcodes. */ |
2469 |
for (i = 0; exit_addrs[i] != -1; i++) { |
2470 |
int op; |
2471 |
switch (p_start[exit_addrs[i]]) |
2472 |
{ |
2473 |
case 0xf4: op = 0xc3; break; /* hlt -> ret */ |
2474 |
case 0xfa: op = 0xe9; break; /* cli -> jmp */ |
2475 |
case 0xfb: op = 0xe9; break; /* sti -> jmp */ |
2476 |
default: error("Internal error"); |
2477 |
} |
2478 |
fprintf(outfile, |
2479 |
" *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n", |
2480 |
exit_addrs[i], op); |
1803 |
} |
2481 |
} |
|
|
2482 |
/* Fix up the return instruction. */ |
2483 |
if (patch_bytes != -1) { |
2484 |
if (patch_bytes) { |
2485 |
fprintf(outfile, " memcpy(gen_code_ptr + %d," |
2486 |
"gen_code_ptr + %d, %d);\n", |
2487 |
copy_size, retpos, patch_bytes); |
2488 |
} |
2489 |
fprintf(outfile, |
2490 |
" *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n", |
2491 |
retpos); |
2492 |
fprintf(outfile, |
2493 |
" *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n", |
2494 |
retpos + 1, copy_size - (retpos + 5)); |
2495 |
|
2496 |
copy_size += patch_bytes; |
2497 |
} |
2498 |
#ifdef DEBUG_OP |
2499 |
fprintf(outfile, |
2500 |
" *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n", |
2501 |
copy_size); |
2502 |
copy_size += 2; |
2503 |
#endif |
1804 |
} |
2504 |
} |
1805 |
#elif defined(HOST_X86_64) |
2505 |
#elif defined(HOST_X86_64) |
1806 |
{ |
2506 |
{ |
Lines 1834-1839
Link Here
|
1834 |
} |
2534 |
} |
1835 |
} |
2535 |
} |
1836 |
} |
2536 |
} |
|
|
2537 |
/* Replace the marker instructions with the actual opcodes. */ |
2538 |
for (i = 0; exit_addrs[i] != -1; i++) { |
2539 |
int op; |
2540 |
switch (p_start[exit_addrs[i]]) |
2541 |
{ |
2542 |
case 0xf4: op = 0xc3; break; /* hlt -> ret */ |
2543 |
case 0xfa: op = 0xe9; break; /* cli -> jmp */ |
2544 |
case 0xfb: op = 0xe9; break; /* sti -> jmp */ |
2545 |
default: error("Internal error"); |
2546 |
} |
2547 |
fprintf(outfile, |
2548 |
" *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n", |
2549 |
exit_addrs[i], op); |
2550 |
} |
2551 |
/* Fix up the return instruction. */ |
2552 |
if (patch_bytes != -1) { |
2553 |
if (patch_bytes) { |
2554 |
fprintf(outfile, " memcpy(gen_code_ptr + %d," |
2555 |
"gen_code_ptr + %d, %d);\n", |
2556 |
copy_size, retpos, patch_bytes); |
2557 |
} |
2558 |
fprintf(outfile, |
2559 |
" *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n", |
2560 |
retpos); |
2561 |
fprintf(outfile, |
2562 |
" *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n", |
2563 |
retpos + 1, copy_size - (retpos + 5)); |
2564 |
|
2565 |
copy_size += patch_bytes; |
2566 |
} |
2567 |
#ifdef DEBUG_OP |
2568 |
fprintf(outfile, |
2569 |
" *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n", |
2570 |
copy_size); |
2571 |
copy_size += 2; |
2572 |
#endif |
1837 |
} |
2573 |
} |
1838 |
#elif defined(HOST_PPC) |
2574 |
#elif defined(HOST_PPC) |
1839 |
{ |
2575 |
{ |