1#include <stdio.h> 2#include <stdlib.h> 3# if defined(VGO_linux) 4#include <endian.h> 5# elif defined(VGO_darwin) 6#include <machine/endian.h> 7# endif 8#include "../../VEX/pub/libvex.h" 9 10Bool return_false(void*cb, Addr ad) 11{ 12 return False; 13} 14UInt return_0(void *cb, VexRegisterUpdates* pxControl, 15 const VexGuestExtents *vge) 16{ 17 return 0; 18} 19 20__attribute__ ((noreturn)) 21static void failure_exit() 22{ 23 fflush(stdout); 24 fprintf(stderr, "//// failure exit called by libVEX\n"); 25 exit(1); 26} 27 28__attribute__ ((noreturn)) 29static void failure_dispcalled() 30{ 31 fflush(stdout); 32 fprintf(stderr, "//// unexpected call to a disp function by libVEX\n"); 33 exit(1); 34} 35 36static void log_bytes (const HChar* chars, SizeT nbytes ) 37{ 38 printf("%*s", (int)nbytes, chars); 39} 40 41// Returns the endness of the system we are running on. 42// We use that as the endness of arch that supports both 43// little and big endian. 44static VexEndness running_endness (void) 45{ 46#if __BYTE_ORDER == __LITTLE_ENDIAN 47 return VexEndnessLE; 48#elif __BYTE_ORDER == __BIG_ENDIAN 49 return VexEndnessBE; 50#else 51 fprintf(stderr, "cannot determine endianess\n"); 52 exit(1); 53#endif 54} 55 56// noinline, as this function is also the one we decode. 57__attribute__((noinline)) static void get_guest_arch(VexArch *ga) 58{ 59#if defined(VGA_x86) 60 *ga = VexArchX86; 61#elif defined(VGA_amd64) 62 *ga = VexArchAMD64; 63#elif defined(VGA_arm) 64 *ga = VexArchARM; 65#elif defined(VGA_arm64) 66 *ga = VexArchARM64; 67#elif defined(VGA_ppc32) 68 *ga = VexArchPPC32; 69#elif defined(VGA_ppc64be) || defined(VGA_ppc64le) 70 *ga = VexArchPPC64; 71#elif defined(VGA_s390x) 72 *ga = VexArchS390X; 73#elif defined(VGA_mips32) 74 *ga = VexArchMIPS32; 75#elif defined(VGA_mips64) 76 *ga = VexArchMIPS64; 77#elif defined(VGA_tilegx) 78 *ga = VexArchTILEGX; 79#else 80 missing arch; 81#endif 82} 83 84static VexEndness arch_endness (VexArch va) { 85 switch (va) { 86 case VexArch_INVALID: failure_exit(); 87 case VexArchX86: return VexEndnessLE; 88 case VexArchAMD64: return VexEndnessLE; 89 case VexArchARM: return VexEndnessLE; 90 case VexArchARM64: return VexEndnessLE; 91 case VexArchPPC32: return VexEndnessBE; 92 case VexArchPPC64: 93 /* ppc64 supports BE or LE at run time. So, on a LE system, 94 returns LE, on a BE system, return BE. */ 95 return running_endness(); 96 case VexArchS390X: return VexEndnessBE; 97 case VexArchMIPS32: 98 case VexArchMIPS64: 99 /* mips32/64 supports BE or LE, but at compile time. 100 If mips64 is compiled on a non mips system, the VEX lib 101 is missing bit and pieces of code related to endianess. 102 The mandatory code for this test is then compiled as BE. 103 So, if this test runs on a mips system, returns the 104 running endianess. Otherwise, returns BE as this one 105 has the more chances to work. */ 106 { 107 VexArch ga; 108 get_guest_arch( &ga); 109 110 if (ga == VexArchMIPS64 || ga == VexArchMIPS32) 111 return running_endness(); 112 else 113 return VexEndnessBE; 114 } 115 case VexArchTILEGX: return VexEndnessLE; 116 default: failure_exit(); 117 } 118} 119 120/* returns whatever kind of hwcaps needed to make 121 the host and/or guest VexArch happy. */ 122static UInt arch_hwcaps (VexArch va) { 123 switch (va) { 124 case VexArch_INVALID: failure_exit(); 125 case VexArchX86: return 0; 126 case VexArchAMD64: return 0; 127 case VexArchARM: return 7; 128 case VexArchARM64: return 0; 129 case VexArchPPC32: return 0; 130 case VexArchPPC64: return 0; 131 case VexArchS390X: return VEX_HWCAPS_S390X_LDISP; 132 case VexArchMIPS32: return 0; 133 case VexArchMIPS64: return 0; 134 case VexArchTILEGX: return 0; 135 default: failure_exit(); 136 } 137} 138 139static Bool mode64 (VexArch va) { 140 switch (va) { 141 case VexArch_INVALID: failure_exit(); 142 case VexArchX86: return False; 143 case VexArchAMD64: return True; 144 case VexArchARM: return False; 145 case VexArchARM64: return True; 146 case VexArchPPC32: return False; 147 case VexArchPPC64: return True; 148 case VexArchS390X: return True; 149 case VexArchMIPS32: return False; 150 case VexArchMIPS64: return True; 151 case VexArchTILEGX: return True; 152 default: failure_exit(); 153 } 154} 155 156static void show_vta(char *msg, VexTranslateArgs *vta) 157{ 158 printf("//// %s translating guest %s(%d) %s %dbits to host %s(%d)" 159 " %s %dbits\n", 160 msg, 161 LibVEX_ppVexArch(vta->arch_guest), 162 vta->arch_guest, 163 LibVEX_ppVexEndness(arch_endness(vta->arch_guest)), 164 mode64(vta->arch_guest) ? 64 : 32, 165 LibVEX_ppVexArch(vta->arch_host), 166 vta->arch_host, 167 LibVEX_ppVexEndness(arch_endness(vta->arch_host)), 168 mode64(vta->arch_host) ? 64 : 32); 169} 170 171 172int main(int argc, char **argv) 173{ 174 const int multiarch = argc > 1 ? atoi(argv[1]) : 0; 175 // 0 means: do not do multiarch 176 // > 0 means: do multiarch 177 // > VexArch_INVALID means: do multiarch, only and specifically 178 // with the host arch equal to multiarch 179 // (ugly interface, but hey, that is for testing only special cases only). 180 const int endness_may_differ = argc > 2 ? atoi(argv[2]) : 0; 181 const int wordsize_may_differ = argc > 3 ? atoi(argv[3]) : 0; 182 // Note: if multiarch > VexArch_INVALID, then endness_may_differ 183 // and wordsize_may_differ are ignored. 184 185 // So, here are examples of usage: 186 // * run only host == guest: 187 // ./libvexmultiarch_test 188 // ./libvex_test 189 // * run all combinations (this will abort very soon :): 190 // ./libvexmultiarch_test 1 1 1 191 // * run all combinations that are supposed to work by default : 192 // ./libvexmultiarch_test 1 0 0 193 // * run a specific host arch (e.g. 1028 i.e. VexArchARM64) 194 // ./libvexmultiarch_test 1028 195 // * show how a single arch VEX lib reports its failure when host != guest 196 // ./libvex_test 1 0 0 197 198 199 VexArch guest_arch; 200 VexEndness guest_endness; 201 202 VexControl vcon; 203 204 VexGuestExtents vge; 205 VexTranslateArgs vta; 206 VexTranslateResult vtr; 207 208 UChar host_bytes[10000]; 209 Int host_bytes_used; 210 211 LibVEX_default_VexControl(&vcon); 212 LibVEX_Init (failure_exit, log_bytes, 3, &vcon); 213 214 get_guest_arch (&guest_arch); 215 guest_endness = arch_endness (guest_arch); 216 217 LibVEX_default_VexArchInfo(&vta.archinfo_guest); 218 LibVEX_default_VexArchInfo(&vta.archinfo_host); 219 LibVEX_default_VexAbiInfo (&vta.abiinfo_both); 220 221 // Use some values that makes AMD64 happy. 222 vta.abiinfo_both.guest_stack_redzone_size = 128; 223 224 // Use some values that makes ARM64 happy. 225 vta.archinfo_guest.arm64_dMinLine_lg2_szB = 6; 226 vta.archinfo_guest.arm64_iMinLine_lg2_szB = 6; 227 228 // Prepare first for a translation where guest == host 229 // We will translate the get_guest_arch function 230 vta.arch_guest = guest_arch; 231 vta.archinfo_guest.endness = guest_endness; 232 vta.archinfo_guest.hwcaps = arch_hwcaps (vta.arch_guest); 233 vta.arch_host = guest_arch; 234 vta.archinfo_host.endness = guest_endness; 235 vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host); 236 vta.callback_opaque = NULL; 237 vta.guest_bytes = (UChar*) get_guest_arch; 238 vta.guest_bytes_addr = (Addr) get_guest_arch; 239 vta.chase_into_ok = return_false; 240 vta.guest_extents = &vge; 241 vta.host_bytes = host_bytes; 242 vta.host_bytes_size = sizeof host_bytes; 243 vta.host_bytes_used = &host_bytes_used; 244 vta.instrument1 = NULL; 245 vta.instrument2 = NULL; 246 vta.finaltidy = NULL; 247 vta.needs_self_check = return_0; 248 vta.preamble_function = NULL; 249 vta.traceflags = 0xFFFFFFFF; 250 vta.sigill_diag = False; 251 vta.addProfInc = False; 252 vta.disp_cp_chain_me_to_slowEP = failure_dispcalled; 253 vta.disp_cp_chain_me_to_fastEP = failure_dispcalled; 254 vta.disp_cp_xindir = failure_dispcalled; 255 vta.disp_cp_xassisted = failure_dispcalled; 256 257 258 show_vta("host == guest", &vta); 259 vtr = LibVEX_Translate ( &vta ); 260 if (vtr.status != VexTransOK) 261 return 1; 262 263 // Now, try various combinations, if told to do so: 264 // host != guest, 265 // endness(host) != endness(guest) (not well supported) 266 // wordsize (host) != wordsize (guest) (not well supported) 267 // The not well supported combinations are not run, unless requested 268 // explicitely via command line arguments. 269 if (multiarch) { 270 VexArch va; 271 for (va = VexArchX86; va <= VexArchTILEGX; va++) { 272 vta.arch_host = va; 273 vta.archinfo_host.endness = arch_endness (vta.arch_host); 274 vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host); 275 if (arch_endness(va) != arch_endness(guest_arch) 276 && !endness_may_differ 277 && multiarch != va) { 278 show_vta("skipped (endness differs)", &vta); 279 continue; 280 } 281 if (mode64(va) != mode64(guest_arch) 282 && !wordsize_may_differ 283 && multiarch != va) { 284 show_vta("skipped (word size differs)", &vta); 285 continue; 286 } 287 if (multiarch > VexArch_INVALID 288 && multiarch != va) { 289 show_vta("skipped (!= specific requested arch)", &vta); 290 continue; 291 } 292 show_vta ("doing", &vta); 293 vtr = LibVEX_Translate ( &vta ); 294 if (vtr.status != VexTransOK) 295 return 1; 296 } 297 } 298 299 printf ("//// libvex testing normal exit\n"); 300 return 0; 301} 302