예제 #1
0
def check_datafile(filename):
    """
    Verify that the reassembling the output of the disassembler produces
    the same binary, and that disassembling the output of the assembler
    produces the same text.
    """
    data = testdata.read(filename)

    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")

    assembled = ebpf.assembler.assemble(data['asm'])
    disassembled = ebpf.disassembler.disassemble(assembled)
    reassembled = ebpf.assembler.assemble(disassembled)
    disassembled2 = ebpf.disassembler.disassemble(reassembled)

    if disassembled != disassembled2:
        diff = difflib.unified_diff(disassembled.splitlines(),
                                    disassembled2.splitlines(),
                                    lineterm="")
        formatted = ''.join('  %s\n' % x for x in diff)
        raise AssertionError("Assembly differs:\n%s" % formatted)

    if assembled != reassembled:
        raise AssertionError("binary differs")
예제 #2
0
def check_datafile(filename):
    """
    Given assembly source code and an expected result, run the eBPF program and
    verify that the result matches.
    """
    data = testdata.read(filename)
    if 'asm' not in data and 'raw' not in data:
        raise SkipTest("no asm or raw section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")

    if 'raw' in data:
        code = ''.join(struct.pack("=Q", x) for x in data['raw'])
    else:
        code = ubpf.assembler.assemble(data['asm'])

    memfile = None

    cmd = [VM]
    if 'mem' in data:
        memfile = tempfile.NamedTemporaryFile()
        memfile.write(data['mem'])
        memfile.flush()
        cmd.extend(['-m', memfile.name])

    cmd.append('-')

    vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout, stderr = vm.communicate(code)
    stderr = stderr.strip()

    if memfile:
        memfile.close()

    if 'error' in data:
        if data['error'] != stderr:
            raise AssertionError("Expected error %r, got %r" % (data['error'], stderr))
    elif 'error pattern' in data:
        if not re.search(data['error pattern'], stderr):
            raise AssertionError("Expected error matching %r, got %r" % (data['error pattern'], stderr))
    else:
        if stderr:
            raise AssertionError("Unexpected error %r" % stderr)

    if 'result' in data:
        if vm.returncode != 0:
            raise AssertionError("VM exited with status %d, stderr=%r" % (vm.returncode, stderr))
        expected = int(data['result'], 0)
        result = int(stdout, 0)
        if expected != result:
            raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" % (expected, result, stderr))
    else:
        if vm.returncode == 0:
            raise AssertionError("Expected VM to exit with an error code")
예제 #3
0
def main():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('name')
    parser.add_argument('path')
    args = parser.parse_args()

    data = testdata.read(args.name + '.data')
    assert data

    if not os.path.isdir(args.path):
        os.makedirs(args.path)

    def writefile(name, contents):
        file("%s/%s" % (args.path, name), "w").write(contents)

    if 'mem' in data:
        writefile('mem', data['mem'])

        # Probably a packet, so write out a pcap file
        writefile(
            'pcap',
            struct.pack(
                '=IHHIIIIIIII',
                0xa1b2c3d4,  # magic
                2,
                4,  # version
                0,  # time zone offset
                0,  # time stamp accuracy
                65535,  # snapshot length
                1,  # link layer type
                0,
                0,  # timestamp
                len(data['mem']),  # length
                len(data['mem']))  # length
            + data['mem'])

    if 'raw' in data:
        code = ''.join(struct.pack("=Q", x) for x in data['raw'])
    elif 'asm' in data:
        code = ebpf.assembler.assemble(data['asm'])
    else:
        code = None

    if code:
        writefile('code', code)

    if 'asm' in data:
        writefile('asm', data['asm'])
    elif code:
        writefile('asm', ebpf.disassembler.disassemble(code))
예제 #4
0
def main():
    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('name')
    parser.add_argument('path')
    args = parser.parse_args()

    data = testdata.read(args.name + '.data')
    assert data

    if not os.path.isdir(args.path):
        os.makedirs(args.path)

    def writefile(name, contents):
        file("%s/%s" % (args.path, name), "w").write(contents)

    if 'mem' in data:
        writefile('mem', data['mem'])

        # Probably a packet, so write out a pcap file
        writefile('pcap',
            struct.pack('=IHHIIIIIIII',
                0xa1b2c3d4, # magic
                2, 4, # version
                0, # time zone offset
                0, # time stamp accuracy
                65535, # snapshot length
                1, # link layer type
                0, 0, # timestamp
                len(data['mem']), # length
                len(data['mem'])) # length
            + data['mem'])

    if 'raw' in data:
        code = ''.join(struct.pack("=Q", x) for x in data['raw'])
    elif 'asm' in data:
        code = ubpf.assembler.assemble(data['asm'])
    else:
        code = None

    if code:
        writefile('code', code)

    if 'asm' in data:
        writefile('asm', data['asm'])
    elif code:
        writefile('asm', ubpf.disassembler.disassemble(code))

    if 'pyelf' in data:
        from test_elf import generate_elf
        elf = generate_elf(data['pyelf'])
        writefile('elf', elf)
예제 #5
0
def check_datafile(filename):
    """
    """
    data = testdata.read(filename)
    if 'pyelf' not in data:
        raise SkipTest("no pyelf section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")

    elf = generate_elf(data['pyelf'])

    cmd = [VM]

    cmd.append('-')

    vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout, stderr = vm.communicate(elf)
    stdout = stdout.decode("utf-8")
    stderr = stderr.decode("utf-8")
    stderr = stderr.strip()

    if 'error' in data:
        if data['error'] != stderr:
            raise AssertionError("Expected error %r, got %r" %
                                 (data['error'], stderr))
    elif 'error pattern' in data:
        if not re.search(data['error pattern'], stderr):
            raise AssertionError("Expected error matching %r, got %r" %
                                 (data['error pattern'], stderr))
    else:
        if stderr:
            raise AssertionError("Unexpected error %r" % stderr)

    if 'result' in data:
        if vm.returncode != 0:
            raise AssertionError("VM exited with status %d, stderr=%r" %
                                 (vm.returncode, stderr))
        expected = int(data['result'], 0)
        result = int(stdout, 0)
        if expected != result:
            raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" %
                                 (expected, result, stderr))
    else:
        if vm.returncode == 0:
            raise AssertionError("Expected VM to exit with an error code")
예제 #6
0
def check_datafile(filename):
    """
    Verify that the result of disassembling the 'raw' section matches the
    'asm' section.
    """
    data = testdata.read(filename)
    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")
    if 'raw' not in data:
        raise SkipTest("no raw section in datafile")

    binary = ''.join(struct.pack("=Q", x) for x in data['raw'])
    result = ubpf.disassembler.disassemble(binary)

    # TODO strip whitespace and comments from asm
    if result.strip() != data['asm'].strip():
        diff = difflib.unified_diff(data['asm'].splitlines(), result.splitlines(), lineterm="")
        formatted = ''.join('  %s\n' % x for x in diff)
        raise AssertionError("Assembly differs:\n%s" % formatted)
예제 #7
0
def check_datafile(filename):
    """
    """
    data = testdata.read(filename)
    if 'pyelf' not in data:
        raise SkipTest("no pyelf section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")

    elf = generate_elf(data['pyelf'])

    cmd = [VM]

    cmd.append('-')

    vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout, stderr = vm.communicate(elf)
    stderr = stderr.strip()

    if 'error' in data:
        if data['error'] != stderr:
            raise AssertionError("Expected error %r, got %r" % (data['error'], stderr))
    elif 'error pattern' in data:
        if not re.search(data['error pattern'], stderr):
            raise AssertionError("Expected error matching %r, got %r" % (data['error pattern'], stderr))
    else:
        if stderr:
            raise AssertionError("Unexpected error %r" % stderr)

    if 'result' in data:
        if vm.returncode != 0:
            raise AssertionError("VM exited with status %d, stderr=%r" % (vm.returncode, stderr))
        expected = int(data['result'], 0)
        result = int(stdout, 0)
        if expected != result:
            raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" % (expected, result, stderr))
    else:
        if vm.returncode == 0:
            raise AssertionError("Expected VM to exit with an error code")
예제 #8
0
def check_datafile(filename):
    """
    Verify that the result of disassembling the 'raw' section matches the
    'asm' section.
    """
    data = testdata.read(filename)
    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")
    if 'raw' not in data:
        raise SkipTest("no raw section in datafile")

    binary = ''.join(struct.pack("=Q", x) for x in data['raw'])
    result = ubpf.disassembler.disassemble(binary)

    # TODO strip whitespace and comments from asm
    if result.strip() != data['asm'].strip():
        diff = difflib.unified_diff(data['asm'].splitlines(),
                                    result.splitlines(),
                                    lineterm="")
        formatted = ''.join('  %s\n' % x for x in diff)
        raise AssertionError("Assembly differs:\n%s" % formatted)
예제 #9
0
def check_datafile(filename):
    """
    Verify that the result of assembling the 'asm' section matches the
    'raw' section.
    """
    data = testdata.read(filename)
    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")
    if 'raw' not in data:
        raise SkipTest("no raw section in datafile")

    bin_result = ubpf.assembler.assemble(data['asm'])
    assert len(bin_result) % 8 == 0
    assert len(bin_result) / 8 == len(data['raw'])

    for i in xrange(0, len(bin_result), 8):
        j = int(i/8)
        inst, = struct.unpack_from("=Q", bin_result[i:i+8])
        exp = data['raw'][j]
        if exp != inst:
            raise AssertionError("Expected instruction %d to be %#x (%s), but was %#x (%s)" %
                (j, exp, try_disassemble(exp), inst, try_disassemble(inst)))
예제 #10
0
def check_datafile(filename):
    """
    Verify that the result of assembling the 'asm' section matches the
    'raw' section.
    """
    data = testdata.read(filename)
    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")
    if 'raw' not in data:
        raise SkipTest("no raw section in datafile")

    bin_result = ubpf.assembler.assemble(data['asm'])
    assert len(bin_result) % 8 == 0
    assert len(bin_result) / 8 == len(data['raw'])

    for i in xrange(0, len(bin_result), 8):
        j = i/8
        inst, = struct.unpack_from("=Q", bin_result[i:i+8])
        exp = data['raw'][j]
        if exp != inst:
            raise AssertionError("Expected instruction %d to be %#x (%s), but was %#x (%s)" %
                (j, exp, try_disassemble(exp), inst, try_disassemble(inst)))
예제 #11
0
def check_datafile(filename):
    """
    Verify that the reassembling the output of the disassembler produces
    the same binary, and that disassembling the output of the assembler
    produces the same text.
    """
    data = testdata.read(filename)

    if 'asm' not in data:
        raise SkipTest("no asm section in datafile")

    assembled = ubpf.assembler.assemble(data['asm'])
    disassembled = ubpf.disassembler.disassemble(assembled)
    reassembled = ubpf.assembler.assemble(disassembled)
    disassembled2 = ubpf.disassembler.disassemble(reassembled)

    if disassembled != disassembled2:
        diff = difflib.unified_diff(disassembled.splitlines(), disassembled2.splitlines(), lineterm="")
        formatted = ''.join('  %s\n' % x for x in diff)
        raise AssertionError("Assembly differs:\n%s" % formatted)

    if assembled != reassembled:
        raise AssertionError("binary differs")
예제 #12
0
def check_datafile(filename):
    """
    Given assembly source code and an expected result, run the eBPF program and
    verify that the result matches. Uses the JIT compiler.
    """
    data = testdata.read(filename)
    if 'asm' not in data and 'raw' not in data:
        raise SkipTest("no asm or raw section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")
    if 'no jit' in data:
        raise SkipTest("JIT disabled for this testcase (%s)" % data['no jit'])

    if 'raw' in data:
        code = b''.join(struct.pack("=Q", x) for x in data['raw'])
    else:
        code = ubpf.assembler.assemble(data['asm'])

    memfile = None

    if 'mem' in data:
        memfile = tempfile.NamedTemporaryFile()
        memfile.write(data['mem'])
        memfile.flush()

    num_register_offsets = 20
    if 'no register offset' in data:
        # The JIT relies on a fixed register mapping for the call instruction
        num_register_offsets = 1

    try:
        for register_offset in xrange(0, num_register_offsets):
            cmd = [VM]
            if memfile:
                cmd.extend(['-m', memfile.name])
            if 'reload' in data:
                cmd.extend(['-R'])
            if 'unload' in data:
                cmd.extend(['-U'])
            cmd.extend(['-j', '-r', str(register_offset), '-'])

            vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

            stdout, stderr = vm.communicate(code)
            stdout = stdout.decode("utf-8")
            stderr = stderr.decode("utf-8")
            stderr = stderr.strip()

            if 'error' in data:
                if data['error'] != stderr:
                    raise AssertionError("Expected error %r, got %r" % (data['error'], stderr))
            elif 'error pattern' in data:
                if not re.search(data['error pattern'], stderr):
                    raise AssertionError("Expected error matching %r, got %r" % (data['error pattern'], stderr))
            else:
                if stderr:
                    raise AssertionError("Unexpected error %r" % stderr)

            if 'result' in data:
                if vm.returncode != 0:
                    raise AssertionError("VM exited with status %d, stderr=%r" % (vm.returncode, stderr))
                expected = int(data['result'], 0)
                result = int(stdout, 0)
                if expected != result:
                    raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" % (expected, result, stderr))
            else:
                if vm.returncode == 0:
                    raise AssertionError("Expected VM to exit with an error code")
    finally:
        if memfile:
            memfile.close()
예제 #13
0
def check_datafile(filename):
    """
    Given assembly source code and an expected result, run the eBPF program and
    verify that the result matches.
    """
    data = testdata.read(filename)
    if 'asm' not in data and 'raw' not in data:
        raise SkipTest("no asm or raw section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")

    if 'raw' in data:
        code = ''.join(struct.pack("=Q", x) for x in data['raw'])
    else:
        code = ubpf.assembler.assemble(data['asm'])

    memfile = None

    cmd = [VM]
    if 'mem' in data:
        memfile = tempfile.NamedTemporaryFile()
        memfile.write(data['mem'])
        memfile.flush()
        cmd.extend(['-m', memfile.name])

    cmd.append('-')

    vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout, stderr = vm.communicate(code)
    stderr = stderr.strip()

    if memfile:
        memfile.close()

    if 'error' in data:
        if data['error'] != stderr:
            raise AssertionError("Expected error %r, got %r" %
                                 (data['error'], stderr))
    elif 'error pattern' in data:
        if not re.search(data['error pattern'], stderr):
            raise AssertionError("Expected error matching %r, got %r" %
                                 (data['error pattern'], stderr))
    else:
        if stderr:
            raise AssertionError("Unexpected error %r" % stderr)

    if 'result' in data:
        if vm.returncode != 0:
            raise AssertionError("VM exited with status %d, stderr=%r" %
                                 (vm.returncode, stderr))
        expected = int(data['result'], 0)
        result = int(stdout, 0)
        if expected != result:
            raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" %
                                 (expected, result, stderr))
    else:
        if vm.returncode == 0:
            raise AssertionError("Expected VM to exit with an error code")
예제 #14
0
def check_datafile(filename):
    """
    Given assembly source code and an expected result, run the eBPF program and
    verify that the result matches. Uses the JIT compiler.
    """
    data = testdata.read(filename)
    if 'asm' not in data and 'raw' not in data:
        raise SkipTest("no asm or raw section in datafile")
    if 'result' not in data and 'error' not in data and 'error pattern' not in data:
        raise SkipTest("no result or error section in datafile")
    if not os.path.exists(VM):
        raise SkipTest("VM not found")
    if 'no jit' in data:
        raise SkipTest("JIT disabled for this testcase (%s)" % data['no jit'])

    if 'raw' in data:
        code = ''.join(struct.pack("=Q", x) for x in data['raw'])
    else:
        code = ubpf.assembler.assemble(data['asm'])

    memfile = None

    if 'mem' in data:
        memfile = tempfile.NamedTemporaryFile()
        memfile.write(data['mem'])
        memfile.flush()

    num_register_offsets = 20
    if 'no register offset' in data:
        # The JIT relies on a fixed register mapping for the call instruction
        num_register_offsets = 1

    try:
        for register_offset in xrange(0, num_register_offsets):
            cmd = [VM]
            if memfile:
                cmd.extend(['-m', memfile.name])
            cmd.extend(['-j', '-r', str(register_offset), '-'])

            vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

            stdout, stderr = vm.communicate(code)
            stderr = stderr.strip()

            if 'error' in data:
                if data['error'] != stderr:
                    raise AssertionError("Expected error %r, got %r" % (data['error'], stderr))
            elif 'error pattern' in data:
                if not re.search(data['error pattern'], stderr):
                    raise AssertionError("Expected error matching %r, got %r" % (data['error pattern'], stderr))
            else:
                if stderr:
                    raise AssertionError("Unexpected error %r" % stderr)

            if 'result' in data:
                if vm.returncode != 0:
                    raise AssertionError("VM exited with status %d, stderr=%r" % (vm.returncode, stderr))
                expected = int(data['result'], 0)
                result = int(stdout, 0)
                if expected != result:
                    raise AssertionError("Expected result 0x%x, got 0x%x, stderr=%r" % (expected, result, stderr))
            else:
                if vm.returncode == 0:
                    raise AssertionError("Expected VM to exit with an error code")
    finally:
        if memfile:
            memfile.close()