vgdb: Handle EAGAIN in read_buf
[valgrind.git] / none / tests / libvex_test.c
blob5b57a4c2e220ec1c4e545dcf31239457065a8a5a
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"
10 Bool return_false(void*cb, Addr ad)
12 return False;
14 UInt return_0(void *cb, VexRegisterUpdates* pxControl,
15 const VexGuestExtents *vge)
17 return 0;
20 __attribute__ ((noreturn))
21 static void failure_exit()
23 fflush(stdout);
24 fprintf(stderr, "//// failure exit called by libVEX\n");
25 exit(1);
28 __attribute__ ((noreturn))
29 static void failure_dispcalled()
31 fflush(stdout);
32 fprintf(stderr, "//// unexpected call to a disp function by libVEX\n");
33 exit(1);
36 static void log_bytes (const HChar* chars, SizeT nbytes )
38 printf("%*s", (int)nbytes, chars);
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.
44 static VexEndness running_endness (void)
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 endianness\n");
52 exit(1);
53 #endif
56 // noinline, as this function is also the one we decode.
57 __attribute__((noinline)) static void get_guest_arch(VexArch *ga)
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_nanomips)
78 *ga = VexArchNANOMIPS;
79 #else
80 missing arch;
81 #endif
84 static 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 case VexArchNANOMIPS:
100 /* mips32/64 supports BE or LE, but at compile time.
101 If mips64 is compiled on a non mips system, the VEX lib
102 is missing bit and pieces of code related to endianness.
103 The mandatory code for this test is then compiled as BE.
104 So, if this test runs on a mips system, returns the
105 running endianness. Otherwise, returns BE as this one
106 has the more chances to work. */
108 VexArch ga;
109 get_guest_arch( &ga);
111 if (ga == VexArchMIPS64 || ga == VexArchMIPS32 || ga == VexArchNANOMIPS)
112 return running_endness();
113 else
114 return VexEndnessBE;
116 default: failure_exit();
120 /* returns whatever kind of hwcaps needed to make
121 the host and/or guest VexArch happy. */
122 static 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 #if (__mips_isa_rev>=6)
133 case VexArchMIPS32: return VEX_PRID_COMP_MIPS | VEX_MIPS_CPU_ISA_M32R6 |
134 VEX_MIPS_HOST_FR;
135 case VexArchMIPS64: return VEX_PRID_COMP_MIPS | VEX_MIPS_CPU_ISA_M64R6 |
136 VEX_MIPS_HOST_FR;
137 #else
138 case VexArchMIPS32: return VEX_PRID_COMP_MIPS;
139 case VexArchMIPS64: return VEX_PRID_COMP_MIPS | VEX_MIPS_HOST_FR;
140 #endif
141 case VexArchNANOMIPS: return 0;
142 default: failure_exit();
146 static Bool mode64 (VexArch va) {
147 switch (va) {
148 case VexArch_INVALID: failure_exit();
149 case VexArchX86: return False;
150 case VexArchAMD64: return True;
151 case VexArchARM: return False;
152 case VexArchARM64: return True;
153 case VexArchPPC32: return False;
154 case VexArchPPC64: return True;
155 case VexArchS390X: return True;
156 case VexArchMIPS32: return False;
157 case VexArchMIPS64: return True;
158 case VexArchNANOMIPS: return False;
159 default: failure_exit();
163 static void show_vta(char *msg, VexTranslateArgs *vta)
165 printf("//// %s translating guest %s(%d) %s %dbits to host %s(%d)"
166 " %s %dbits\n",
167 msg,
168 LibVEX_ppVexArch(vta->arch_guest),
169 vta->arch_guest,
170 LibVEX_ppVexEndness(arch_endness(vta->arch_guest)),
171 mode64(vta->arch_guest) ? 64 : 32,
172 LibVEX_ppVexArch(vta->arch_host),
173 vta->arch_host,
174 LibVEX_ppVexEndness(arch_endness(vta->arch_host)),
175 mode64(vta->arch_host) ? 64 : 32);
179 int main(int argc, char **argv)
181 const int multiarch = argc > 1 ? atoi(argv[1]) : 0;
182 // 0 means: do not do multiarch
183 // > 0 means: do multiarch
184 // > VexArch_INVALID means: do multiarch, only and specifically
185 // with the host arch equal to multiarch
186 // (ugly interface, but hey, that is for testing only special cases only).
187 const int endness_may_differ = argc > 2 ? atoi(argv[2]) : 0;
188 const int wordsize_may_differ = argc > 3 ? atoi(argv[3]) : 0;
189 // Note: if multiarch > VexArch_INVALID, then endness_may_differ
190 // and wordsize_may_differ are ignored.
192 // So, here are examples of usage:
193 // * run only host == guest:
194 // ./libvexmultiarch_test
195 // ./libvex_test
196 // * run all combinations (this will abort very soon :):
197 // ./libvexmultiarch_test 1 1 1
198 // * run all combinations that are supposed to work by default :
199 // ./libvexmultiarch_test 1 0 0
200 // * run a specific host arch (e.g. 1028 i.e. VexArchARM64)
201 // ./libvexmultiarch_test 1028
202 // * show how a single arch VEX lib reports its failure when host != guest
203 // ./libvex_test 1 0 0
206 VexArch guest_arch;
207 VexEndness guest_endness;
209 VexControl vcon;
211 VexGuestExtents vge;
212 VexTranslateArgs vta;
213 VexTranslateResult vtr;
215 UChar host_bytes[10000];
216 Int host_bytes_used;
218 LibVEX_default_VexControl(&vcon);
219 LibVEX_Init (failure_exit, log_bytes, 3, &vcon);
221 get_guest_arch (&guest_arch);
222 guest_endness = arch_endness (guest_arch);
224 LibVEX_default_VexArchInfo(&vta.archinfo_guest);
225 LibVEX_default_VexArchInfo(&vta.archinfo_host);
226 LibVEX_default_VexAbiInfo (&vta.abiinfo_both);
228 // Use some values that makes AMD64 happy.
229 vta.abiinfo_both.guest_stack_redzone_size = 128;
231 // Use some values that makes ARM64 happy.
232 vta.archinfo_guest.arm64_dMinLine_lg2_szB = 6;
233 vta.archinfo_guest.arm64_iMinLine_lg2_szB = 6;
235 // Prepare first for a translation where guest == host
236 // We will translate the get_guest_arch function
237 vta.arch_guest = guest_arch;
238 vta.archinfo_guest.endness = guest_endness;
239 vta.archinfo_guest.hwcaps = arch_hwcaps (vta.arch_guest);
240 vta.arch_host = guest_arch;
241 vta.archinfo_host.endness = guest_endness;
242 vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host);
243 vta.callback_opaque = NULL;
244 vta.guest_bytes = (UChar*) get_guest_arch;
245 vta.guest_bytes_addr = (Addr) get_guest_arch;
246 vta.chase_into_ok = return_false;
247 vta.guest_extents = &vge;
248 vta.host_bytes = host_bytes;
249 vta.host_bytes_size = sizeof host_bytes;
250 vta.host_bytes_used = &host_bytes_used;
251 vta.instrument1 = NULL;
252 vta.instrument2 = NULL;
253 vta.finaltidy = NULL;
254 vta.needs_self_check = return_0;
255 vta.preamble_function = NULL;
256 vta.traceflags = 0xFFFFFFFF;
257 vta.sigill_diag = False;
258 vta.addProfInc = False;
259 vta.disp_cp_chain_me_to_slowEP = failure_dispcalled;
260 vta.disp_cp_chain_me_to_fastEP = failure_dispcalled;
261 vta.disp_cp_xindir = failure_dispcalled;
262 vta.disp_cp_xassisted = failure_dispcalled;
265 show_vta("host == guest", &vta);
266 vtr = LibVEX_Translate ( &vta );
267 if (vtr.status != VexTransOK)
268 return 1;
270 // Now, try various combinations, if told to do so:
271 // host != guest,
272 // endness(host) != endness(guest) (not well supported)
273 // wordsize (host) != wordsize (guest) (not well supported)
274 // The not well supported combinations are not run, unless requested
275 // explicitly via command line arguments.
276 if (multiarch) {
277 VexArch va;
278 for (va = VexArchX86; va <= VexArchNANOMIPS; va++) {
279 vta.arch_host = va;
280 vta.archinfo_host.endness = arch_endness (vta.arch_host);
281 vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host);
282 if (arch_endness(va) != arch_endness(guest_arch)
283 && !endness_may_differ
284 && multiarch != va) {
285 show_vta("skipped (endness differs)", &vta);
286 continue;
288 if (mode64(va) != mode64(guest_arch)
289 && !wordsize_may_differ
290 && multiarch != va) {
291 show_vta("skipped (word size differs)", &vta);
292 continue;
294 if (multiarch > VexArch_INVALID
295 && multiarch != va) {
296 show_vta("skipped (!= specific requested arch)", &vta);
297 continue;
299 show_vta ("doing", &vta);
300 vtr = LibVEX_Translate ( &vta );
301 if (vtr.status != VexTransOK)
302 return 1;
306 printf ("//// libvex testing normal exit\n");
307 return 0;