blob: 2c3986d265f23af1541ba6234b8d349fce4260ca [file] [log] [blame]
philippeffcfa7a2015-04-11 14:32:25 +00001#include <stdio.h>
2#include <stdlib.h>
sewardj8eb8bab2015-07-21 14:44:28 +00003# if defined(VGO_linux)
philippe203a35d2015-04-19 15:43:53 +00004#include <endian.h>
sewardj8eb8bab2015-07-21 14:44:28 +00005# elif defined(VGO_darwin)
rhyskidd76e04ec2015-04-30 23:39:10 +00006#include <machine/endian.h>
7# endif
philippeffcfa7a2015-04-11 14:32:25 +00008#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
philippe203a35d2015-04-19 15:43:53 +000041// 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
philippeffcfa7a2015-04-11 14:32:25 +000084static 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;
philippe203a35d2015-04-19 15:43:53 +000092 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();
philippeffcfa7a2015-04-11 14:32:25 +000096 case VexArchS390X: return VexEndnessBE;
philippe203a35d2015-04-19 15:43:53 +000097 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 }
philippeffcfa7a2015-04-11 14:32:25 +0000115 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;
Elliott Hughesa0664b92017-04-18 17:46:52 -0700132 case VexArchMIPS32: return VEX_PRID_COMP_MIPS;
133 case VexArchMIPS64: return VEX_PRID_COMP_MIPS;
philippeffcfa7a2015-04-11 14:32:25 +0000134 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
philippeffcfa7a2015-04-11 14:32:25 +0000156static 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
mjw0bfd39c2015-09-09 13:40:23 +0000224 // 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
philippeffcfa7a2015-04-11 14:32:25 +0000228 // 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 }
philippeffcfa7a2015-04-11 14:32:25 +0000287 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}