On 200528 1533, Philippe Mathieu-Daudé wrote: > On 5/26/20 5:52 PM, Philippe Mathieu-Daudé wrote: > > On 5/26/20 5:41 PM, Alexander Bulekov wrote: > >> On 200526 1725, Philippe Mathieu-Daudé wrote: > >>> On 5/26/20 4:56 PM, Alexander Bulekov wrote: > >>>> On 200526 1105, Philippe Mathieu-Daudé wrote: > >>>>> On 5/26/20 10:56 AM, Stefan Hajnoczi wrote: > >>>>>> On Tue, May 26, 2020 at 07:58:18AM +0200, Philippe Mathieu-Daudé wrote: > >>>>>>> Hi Alexander, > >>>>>>> > >>>>>>> I forgot to share these 2 patches wrote before > >>>>>>> the direct MemoryRegion fuzzer sent yesterday. > >>>>>>> > >>>>>>> Regards, > >>>>>>> > >>>>>>> Phil. > >>>>>>> > >>>>>>> Philippe Mathieu-Daudé (2): > >>>>>>> tests/qtest/fuzz: Avoid QTest ioport serialization > >>>>>>> tests/qtest/fuzz: Avoid QTest mmio serialization > >>>>>>> > >>>>>>> tests/qtest/fuzz/i440fx_fuzz.c | 19 +++++++++++++------ > >>>>>>> tests/qtest/fuzz/virtio_net_fuzz.c | 6 ++++-- > >>>>>>> tests/qtest/fuzz/virtio_scsi_fuzz.c | 6 +++++- > >>>>>>> 3 files changed, 22 insertions(+), 9 deletions(-) > >>>>>> > >>>>>> Will it still be possible to print qtest reproducer commands when a > >>>>>> crash is found? > >>>>> > >>>>> Yes, there is no change in the corpus format. > >>>> > >>>> Yes, though with these patches, the qtest-based code will be gone. > >>>> Should there be some option to switch between the two modes? > >>> > >>> How so? > >>> > >>> How do you generate your reproducers? > >> > >> Right now basically with this: > >> > >> --- a/qtest.c > >> +++ b/qtest.c > >> @@ -808,6 +808,8 @@ bool qtest_driver(void) > >> > >> void qtest_server_inproc_recv(void *dummy, const char *buf) > >> { > >> + // It would be nice to add support for qtest's built in qtest_log_fp. > >> + printf(">>> %s\n", buf); > > > > Uh =) I suppose you restart a single job with the offending corpus file? > > > >> static GString *gstr; > >> if (!gstr) { > >> gstr = g_string_new(NULL); > >> -- > >> > >> It would be nice to add support for qtest's built in qtest_log_fp. > >> Unless I'm missing something, these address_space_writes completely > >> bypass qtest, so there has to be some additional step to build > >> reproducers(eg running against the QTest-based version, or adding some > >> way to spit out corresponding qtest commands for the > >> address_space_writes). > > > > I am using this hacky script, not committed yet because not ready but > > still you can get the idea: > > > > -- >8 -- > > import sys > > import struct > > > > # Tune to MemoryRegion properties > > IOBASE = 0xa0002000 > > IOSIZE = 0x1000 > > > > action = { # ASM ADDR VAL > > 0x00: {'opcode': 'writeb', 'size': 8, 'fmt': 'B'}, > > 0x01: {'opcode': 'writew', 'size': 8, 'fmt': 'H'}, > > 0x02: {'opcode': 'writel', 'size': 8, 'fmt': 'I'}, > > 0x03: {'opcode': 'writeq', 'size': 8, 'fmt': 'L'}, > > > > 0x04: {'opcode': 'writeb', 'size': 16, 'fmt': 'B'}, > > 0x05: {'opcode': 'writew', 'size': 16, 'fmt': 'H'}, > > 0x06: {'opcode': 'writel', 'size': 16, 'fmt': 'I'}, > > 0x07: {'opcode': 'writeq', 'size': 16, 'fmt': 'L'}, > > > > 0x08: {'opcode': 'writeb', 'size': 32, 'fmt': 'B'}, > > 0x09: {'opcode': 'writew', 'size': 32, 'fmt': 'H'}, > > 0x0a: {'opcode': 'writel', 'size': 32, 'fmt': 'I'}, > > 0x0b: {'opcode': 'writeq', 'size': 32, 'fmt': 'L'}, > > > > 0x10: {'opcode': 'readb', 'size': 8, 'fmt': 'B'}, > > 0x11: {'opcode': 'readw', 'size': 8, 'fmt': 'H'}, > > 0x12: {'opcode': 'readl', 'size': 8, 'fmt': 'I'}, > > 0x13: {'opcode': 'readq', 'size': 8, 'fmt': 'L'}, > > > > 0x14: {'opcode': 'readb', 'size': 16, 'fmt': 'B'}, > > 0x15: {'opcode': 'readw', 'size': 16, 'fmt': 'H'}, > > 0x16: {'opcode': 'readl', 'size': 16, 'fmt': 'I'}, > > 0x17: {'opcode': 'readq', 'size': 16, 'fmt': 'L'}, > > > > 0x18: {'opcode': 'readb', 'size': 32, 'fmt': 'B'}, > > 0x19: {'opcode': 'readw', 'size': 32, 'fmt': 'H'}, > > 0x1a: {'opcode': 'readl', 'size': 32, 'fmt': 'I'}, > > 0x1b: {'opcode': 'readq', 'size': 32, 'fmt': 'L'}, > > } > > AMASK = 0x1f > > ADDR = {8: 'B', 16: 'H', 32: 'I', 64: 'L'} > > > > def fuzz_parse_corpus_data(fn): > > fd = open(fn, 'rb') > > while True: > > buf = fd.read(1) > > if len(buf) < 1: > > break > > op, = struct.unpack("B", buf) > > op &= AMASK > > if op not in action: > > break > > a = action[op] > > fmt = "<" + ADDR[a['size']] + a['fmt'] > > fmtsz = struct.calcsize(fmt) > > buf = fd.read(fmtsz) > > if len(buf) < fmtsz: > > break > > if a['fmt'] == 'x': > > addr, = struct.unpack(fmt, buf) > > val = 0 > > else: > > addr, val = struct.unpack(fmt, buf) > > addr &= IOSIZE - 1 > > print("%s 0x%02x 0x%x" % (a['opcode'], IOBASE + addr, val)) > > > > fuzz_parse_corpus_data(sys.argv[1]) > > --- > > > > $ python tests/qtest/fuzz/corpus2qtest.py \ > > ./crash-12e481ba7c2a7a625152dc701821d5e184cddee8 > > writel 0xa0002000 0x20010000 > > writeb 0xa0002020 0x20 > > readl 0xa0002100 0x204204ff > > writeb 0xa0002042 0x36 > > readl 0xa0002436 0xf4760024 > > writel 0xa0002020 0x4363636 > > writeb 0xa0002600 0xf4 > > writew 0xa0002001 0x2020 > > writeb 0xa0002020 0x4 > > writel 0xa0002020 0x4363636 > > writeb 0xa0002600 0xf4 > > writel 0xa0002020 0x36363a01 > > readl 0xa0002404 0x1f47600 > > writew 0xa0002020 0x2020 > > writeb 0xa0002004 0x42 > > writeb 0xa0002036 0x36 > > readl 0xa0002404 0x42f47600 > > writeb 0xa0002036 0x36 > > readl 0xa0002404 0x1f47600 > > writew 0xa0002020 0x420 > > FYI talking with Stefan he kinda suggested it is cleaner to use a > '-replay corpus_data.bin' mode that enables the printf output from > qtest_*read/write (without reaching the device) rather than maintaining > a Python script.
I think handling the QTEST_LOG=1 environment variable in qtest_inproc_init would be a decent solution. Alternatively we could have a -replay flag which just adds "-qtest-log /dev/fd/2" to the qemu_main args. Writing scripts gets complicated for e.g. the virtio-net-* fuzzers, where the input is converted into some high-level libqos calls. -Alex > > > >> > >>>> > >>>>>> > >>>>>> Other than this concern, higher fuzzing rates would be great. > >>>>> > >>>>> Thanks, > >>>>> > >>>>> Phil. > >>>> > >> > >