25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: bintrans_i386.c,v 1.75 2005/03/22 09:12:04 debug Exp $ |
* $Id: bintrans_i386.c,v 1.76 2005/06/22 10:12:25 debug Exp $ |
29 |
* |
* |
30 |
* i386 specific code for dynamic binary translation. |
* i386 specific code for dynamic binary translation. |
31 |
* See bintrans.c for more information. Included from bintrans.c. |
* See bintrans.c for more information. Included from bintrans.c. |
68 |
|
|
69 |
static void (*bintrans_runchunk)(struct cpu *, unsigned char *); |
static void (*bintrans_runchunk)(struct cpu *, unsigned char *); |
70 |
static void (*bintrans_jump_to_32bit_pc)(struct cpu *); |
static void (*bintrans_jump_to_32bit_pc)(struct cpu *); |
71 |
static void (*bintrans_loadstore_32bit)(struct cpu *); |
static void (*bintrans_load_32bit)(struct cpu *); |
72 |
|
static void (*bintrans_store_32bit)(struct cpu *); |
73 |
|
|
74 |
|
|
75 |
/* |
/* |
1891 |
|
|
1892 |
if (mem->bintrans_32bit_only) { |
if (mem->bintrans_32bit_only) { |
1893 |
/* Call the quick lookup routine: */ |
/* Call the quick lookup routine: */ |
1894 |
ofs = (size_t)bintrans_loadstore_32bit; |
if (load) |
1895 |
|
ofs = (size_t)bintrans_load_32bit; |
1896 |
|
else |
1897 |
|
ofs = (size_t)bintrans_store_32bit; |
1898 |
ofs = ofs - ((size_t)a + 5); |
ofs = ofs - ((size_t)a + 5); |
1899 |
*a++ = 0xe8; *a++ = ofs; *a++ = ofs >> 8; |
*a++ = 0xe8; *a++ = ofs; *a++ = ofs >> 8; |
1900 |
*a++ = ofs >> 16; *a++ = ofs >> 24; |
*a++ = ofs >> 16; *a++ = ofs >> 24; |
1911 |
*retfail = (size_t)a - (size_t)retfail - 1; |
*retfail = (size_t)a - (size_t)retfail - 1; |
1912 |
|
|
1913 |
/* |
/* |
|
* If the lowest bit is zero, and we're storing, then fail. |
|
|
*/ |
|
|
if (!load) { |
|
|
/* |
|
|
* f7 c1 01 00 00 00 test $0x1,%ecx |
|
|
* 75 01 jne <ok> |
|
|
*/ |
|
|
*a++ = 0xf7; *a++ = 0xc1; *a++ = 1; *a++ = 0; *a++ = 0; *a++ = 0; |
|
|
*a++ = 0x75; retfail = a; *a++ = 0x00; |
|
|
bintrans_write_chunkreturn_fail(&a); /* ret (and fail) */ |
|
|
*retfail = (size_t)a - (size_t)retfail - 1; |
|
|
} |
|
|
|
|
|
/* |
|
1914 |
* eax = offset within page = vaddr & 0xfff |
* eax = offset within page = vaddr & 0xfff |
1915 |
* |
* |
1916 |
* 25 ff 0f 00 00 and $0xfff,%eax |
* 25 ff 0f 00 00 and $0xfff,%eax |
1945 |
*a++ = 0x75; generic64bit = a; *a++ = 0x01; |
*a++ = 0x75; generic64bit = a; *a++ = 0x01; |
1946 |
|
|
1947 |
/* Call the quick lookup routine: */ |
/* Call the quick lookup routine: */ |
1948 |
ofs = (size_t)bintrans_loadstore_32bit; |
if (load) |
1949 |
|
ofs = (size_t)bintrans_load_32bit; |
1950 |
|
else |
1951 |
|
ofs = (size_t)bintrans_store_32bit; |
1952 |
ofs = ofs - ((size_t)a + 5); |
ofs = ofs - ((size_t)a + 5); |
1953 |
*a++ = 0xe8; *a++ = ofs; *a++ = ofs >> 8; |
*a++ = 0xe8; *a++ = ofs; *a++ = ofs >> 8; |
1954 |
*a++ = ofs >> 16; *a++ = ofs >> 24; |
*a++ = ofs >> 16; *a++ = ofs >> 24; |
1965 |
*retfail = (size_t)a - (size_t)retfail - 1; |
*retfail = (size_t)a - (size_t)retfail - 1; |
1966 |
|
|
1967 |
/* |
/* |
|
* If the lowest bit is zero, and we're storing, then fail. |
|
|
*/ |
|
|
if (!load) { |
|
|
/* |
|
|
* f7 c1 01 00 00 00 test $0x1,%ecx |
|
|
* 75 01 jne <ok> |
|
|
*/ |
|
|
*a++ = 0xf7; *a++ = 0xc1; *a++ = 1; *a++ = 0; *a++ = 0; *a++ = 0; |
|
|
*a++ = 0x75; retfail = a; *a++ = 0x00; |
|
|
bintrans_write_chunkreturn_fail(&a); /* ret (and fail) */ |
|
|
*retfail = (size_t)a - (size_t)retfail - 1; |
|
|
} |
|
|
|
|
|
/* |
|
1968 |
* eax = offset within page = vaddr & 0xfff |
* eax = offset within page = vaddr & 0xfff |
1969 |
* |
* |
1970 |
* 25 ff 0f 00 00 and $0xfff,%eax |
* 25 ff 0f 00 00 and $0xfff,%eax |
2825 |
|
|
2826 |
|
|
2827 |
|
|
2828 |
/* "loadstore_32bit": */ |
/* "load_32bit": */ |
2829 |
size = 48; /* NOTE: This MUST be enough, or we fail */ |
size = 48; /* NOTE: This MUST be enough, or we fail */ |
2830 |
p = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE | |
p = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE | |
2831 |
PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); |
PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); |
2840 |
} |
} |
2841 |
} |
} |
2842 |
|
|
2843 |
bintrans_loadstore_32bit = (void *)p; |
bintrans_load_32bit = (void *)p; |
2844 |
|
|
2845 |
/* |
/* |
2846 |
* ebx = ((vaddr >> 22) & 1023) * sizeof(void *) |
* ebx = ((vaddr >> 22) & 1023) * sizeof(void *) |
2881 |
*p++ = 0x81; *p++ = 0xe3; *p++ = 0xfc; *p++ = 0x0f; *p++ = 0; *p++ = 0; |
*p++ = 0x81; *p++ = 0xe3; *p++ = 0xfc; *p++ = 0x0f; *p++ = 0; *p++ = 0; |
2882 |
|
|
2883 |
/* |
/* |
2884 |
* ecx = vaddr_to_hostaddr_table0[a][b] |
* ecx = vaddr_to_hostaddr_table0[a][b*2] |
2885 |
* |
* |
2886 |
* 8b 0c 19 mov (%ecx,%ebx,1),%ecx |
* 8b 0c 59 mov 0(%ecx,%ebx,2),%ecx |
2887 |
|
*/ |
2888 |
|
*p++ = 0x8b; *p++ = 0x0c; *p++ = 0x59; |
2889 |
|
|
2890 |
|
/* ret */ |
2891 |
|
*p++ = 0xc3; |
2892 |
|
|
2893 |
|
|
2894 |
|
|
2895 |
|
/* "store_32bit": */ |
2896 |
|
size = 48; /* NOTE: This MUST be enough, or we fail */ |
2897 |
|
p = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE | |
2898 |
|
PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); |
2899 |
|
|
2900 |
|
/* If mmap() failed, try malloc(): */ |
2901 |
|
if (p == NULL) { |
2902 |
|
p = malloc(size); |
2903 |
|
if (p == NULL) { |
2904 |
|
fprintf(stderr, "bintrans_backend_init():" |
2905 |
|
" out of memory\n"); |
2906 |
|
exit(1); |
2907 |
|
} |
2908 |
|
} |
2909 |
|
|
2910 |
|
bintrans_store_32bit = (void *)p; |
2911 |
|
|
2912 |
|
/* |
2913 |
|
* ebx = ((vaddr >> 22) & 1023) * sizeof(void *) |
2914 |
|
* |
2915 |
|
* 89 c3 mov %eax,%ebx |
2916 |
|
* c1 eb 14 shr $20,%ebx |
2917 |
|
* 81 e3 fc 0f 00 00 and $0xffc,%ebx |
2918 |
|
*/ |
2919 |
|
*p++ = 0x89; *p++ = 0xc3; |
2920 |
|
*p++ = 0xc1; *p++ = 0xeb; *p++ = 0x14; |
2921 |
|
*p++ = 0x81; *p++ = 0xe3; *p++ = 0xfc; *p++ = 0x0f; *p++ = 0; *p++ = 0; |
2922 |
|
|
2923 |
|
/* |
2924 |
|
* ecx = vaddr_to_hostaddr_table0 |
2925 |
|
* |
2926 |
|
* 8b 8e 34 12 00 00 mov 0x1234(%esi),%ecx |
2927 |
|
*/ |
2928 |
|
*p++ = 0x8b; *p++ = 0x8e; *p++ = ofs_tabl0 & 255; |
2929 |
|
*p++ = (ofs_tabl0 >> 8) & 255; |
2930 |
|
*p++ = (ofs_tabl0 >> 16) & 255; *p++ = (ofs_tabl0 >> 24) & 255; |
2931 |
|
|
2932 |
|
/* |
2933 |
|
* ecx = vaddr_to_hostaddr_table0[a] |
2934 |
|
* |
2935 |
|
* 8b 0c 19 mov (%ecx,%ebx),%ecx |
2936 |
*/ |
*/ |
2937 |
*p++ = 0x8b; *p++ = 0x0c; *p++ = 0x19; |
*p++ = 0x8b; *p++ = 0x0c; *p++ = 0x19; |
2938 |
|
|
2939 |
|
/* |
2940 |
|
* ebx = ((vaddr >> 12) & 1023) * sizeof(void *) |
2941 |
|
* |
2942 |
|
* 89 c3 mov %eax,%ebx |
2943 |
|
* c1 eb 0a shr $10,%ebx |
2944 |
|
* 81 e3 fc 0f 00 00 and $0xffc,%ebx |
2945 |
|
*/ |
2946 |
|
*p++ = 0x89; *p++ = 0xc3; |
2947 |
|
*p++ = 0xc1; *p++ = 0xeb; *p++ = 0x0a; |
2948 |
|
*p++ = 0x81; *p++ = 0xe3; *p++ = 0xfc; *p++ = 0x0f; *p++ = 0; *p++ = 0; |
2949 |
|
|
2950 |
|
/* |
2951 |
|
* ecx = vaddr_to_hostaddr_table0[a][b*2] |
2952 |
|
* |
2953 |
|
* 8b 4c 59 04 mov 4(%ecx,%ebx,2),%ecx |
2954 |
|
*/ |
2955 |
|
*p++ = 0x8b; *p++ = 0x4c; *p++ = 0x59; *p++ = 0x04; |
2956 |
|
|
2957 |
/* ret */ |
/* ret */ |
2958 |
*p++ = 0xc3; |
*p++ = 0xc3; |
2959 |
} |
} |