| vbit-test |
| |
| The program tests the effect of an undefined input bit to an IROp on the |
| definedness of the result of that operation. It also checks that only those |
| bits in the result are undefined that we expect to be undefined. That way |
| we can detect false positives (there are bits in the result that are |
| undefined but shouldn't) and false negatives (there are defined bits in |
| the result that should be undefined). |
| |
| By design, the tester will always be in-synch with the list of IROps |
| in libvex_ir.h. Addition / removel of IROps will cause a compile or |
| runtime error of the tester and thusly will not go unnoticed. |
| |
| |
| How it works |
| ------------ |
| The underlying idea is to |
| (1) use VALGRIND_SET_VBITS to set the V-bits of the operands of an IROp |
| (2) execute that IROp |
| (3) use VALGRIND_GET_VBITS to obtain the V-bits of the result |
| (4) compare the result against our expectation |
| Do that for all IROps and for all input bits of their operands. |
| For all this to work, the tester must run under the auspices of memcheck. |
| |
| The key step here is #2. To "execute an IROp" we need to inject some |
| IR into the the superblock. This is accomplished by adding a new "special |
| instruction" that is supported by all frontends. During the decoding step |
| that instruction will be recognised and a suitable piece of IR will be |
| inserted (function vex_inject_ir does just that). What is "suitable" depends |
| on the IROp at hand and its operands. We need to know the addresses of |
| those operands, their types and, trivially, which IROp we want to execute. |
| This information is collected in the IR Injection Control Block (IRICB). |
| To get the IRICB to VEX we use the new client request |
| VG_USERREQ__VEX_INIT_FOR_IRI. |
| |
| |
| Invocation |
| ---------- |
| Use vbit-test --help to obtain list of supported command line flags. |
| |
| |
| Source code overview |
| -------------------- |
| main.c |
| Contains the main loop that iterates over all IROps in libvex_ir.h. |
| Depending on the number of operands one of the functions test_unary, |
| test_binary, etc. will be invoked to run all tests for that opreator. |
| |
| irops.c |
| List of IROps. For each operator it defines how undefined input bits |
| influence the output (result) and whether the operator is supported on a |
| given architecture. |
| |
| util.c |
| Miscellaneous convenience functions. It also includes sizeof_irtype and |
| typeof_primop which were imported from VEX/priv/ir_defs.c. |
| |
| unary.c |
| The function test_unary_op is the work horse. It iterates over all input |
| bits of the single operand. For each such bit, the corresponding V-bit will |
| be set to undefined, the IROps is executed and the resulting V-bits will |
| be compared against the expected result. |
| The function check_result_for_unary will check the V-bits for correctness. |
| |
| binary.c, ternary.c, qernary.c |
| Like unary.c... |
| |
| valgrind.c |
| The main function there is valgrind_execute_test. It will |
| (1) set the V-bits of the operands using the VALGRIND_SET_VBITS mechanism, |
| (2) inject IR into the current IRSB to exacute a single IROp, and |
| (3) obtain the V-bits of the result using the VALGRIND_GET_VBITS mechanism. |
| The addresses of the operands and the result, as well as they V-bit vectors |
| are stored in the test_data_t structure. |
| |
| <valgrind>/VEX/priv/ir_inject.c |
| The file provides the function vex_inject_ir which will inject a piece of |
| IR into the current IRSB based on the information provided in the IRICB. |
| That code snippet will perform a single IR operation |
| |
| <valgrind>/include/valgrind.h |
| Defines the macro VALGRIND_VEX_INJECT_IR for all architectures. |
| Also defines a new client request VG_USERREQ__VEX_INIT_FOR_IRI. |
| |
| |
| Adding a new IROp |
| ----------------- |
| The following steps are needed |
| (1) Add the operator to irops.c |
| (2) If the operator propagates undefinedness from input to output in a new |
| way: |
| (a) Add a new enumerator to undef_t and document it there. |
| (b) Add a new case in function check_result_for_XYZ depending on the |
| arity of the operator. The code snippet there is supposed to check |
| that the result matches what we expect. |
| |
| |
| Status |
| ------ |
| vbit-test has been tested on x86-64, ppc64, s390x, and mips32. |
| There is support for other architectures in valgrind.h and guest_ARCH_toIR.c |
| but it has not been tested. |