示例#1
0
def test_create_snapshot_from_source():
    """Create a new kernel directory snapshot."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, None, False)

    assert snap.kernel_source is not None
    assert kernel_dir in snap.kernel_source.kernel_dir
    assert snap.snapshot_source is not None
    assert output_dir in snap.snapshot_source.kernel_dir
    assert snap.fun_kind is None
    assert len(snap.fun_groups) == 1
    assert len(snap.fun_groups[None].functions) == 0

    snap = Snapshot.create_from_source(kernel_dir, output_dir, "sysctl", False)

    assert snap.fun_kind == "sysctl"
    assert len(snap.fun_groups) == 0
示例#2
0
def test_to_yaml_sysctls():
    """
    Dump a snapshot with multiple sysctl groups into YAML.
    YAML string should contain the version of Diffkemp, source kernel
    directory, a simple list of function groups, each one containing a
    function list with the "name", "llvm", "glob_var" and "tag" fields set,
    and the kind of this list, which should be a group list.
    The LLVM paths in the YAML should be relative to the snapshot directory.
    """
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots-sysctl/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir,
                                       KernelLlvmSourceBuilder, None, "sysctl",
                                       False)

    snap.add_fun_group("kernel.sched_latency_ns")
    snap.add_fun_group("kernel.timer_migration")
    snap.add_fun(
        "sched_proc_update_handler",
        LlvmModule("snapshots-sysctl/linux-3.10.0-957.el7/"
                   "kernel/sched/fair.ll"), None, "proc handler",
        "kernel.sched_latency_ns")
    snap.add_fun(
        "proc_dointvec_minmax",
        LlvmModule("snapshots-sysctl/linux-3.10.0-957.el7/kernel/sysctl.ll"),
        None, "proc handler", "kernel.timer_migration")

    yaml_str = snap.to_yaml()
    yaml_snap = yaml.safe_load(yaml_str)
    assert len(yaml_snap) == 1
    yaml_dict = yaml_snap[0]
    assert len(yaml_dict) == 7
    assert yaml_dict["llvm_source_finder"]["kind"] == "kernel_with_builder"
    assert isinstance(yaml_dict["created_time"], datetime.datetime)
    assert len(yaml_dict["list"]) == 2
    assert set([g["sysctl"] for g in yaml_dict["list"]
                ]) == {"kernel.sched_latency_ns", "kernel.timer_migration"}

    for g in yaml_dict["list"]:
        assert len(g["functions"]) == 1
        if g["sysctl"] == "kernel.sched_latency_ns":
            assert g["functions"][0] == {
                "name": "sched_proc_update_handler",
                "llvm": "kernel/sched/fair.ll",
                "glob_var": None,
                "tag": "proc handler"
            }
        elif g["sysctl"] == "kernel.timer_migration":
            assert g["functions"][0] == {
                "name": "proc_dointvec_minmax",
                "llvm": "kernel/sysctl.ll",
                "glob_var": None,
                "tag": "proc handler"
            }
示例#3
0
def test_add_sysctl_fun_group():
    """Create a snapshot and check the creation of a sysctl function group."""

    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, "sysctl", False)

    snap.add_fun_group("kernel.sched_latency_ns")

    assert len(snap.fun_groups) == 1
    assert "kernel.sched_latency_ns" in snap.fun_groups
示例#4
0
def test_filter():
    """Filter snapshot functions."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, None, False)

    snap.add_fun("___pskb_trim", LlvmKernelModule("net/core/skbuff.ll"))
    snap.add_fun("__alloc_pages_nodemask",
                 LlvmKernelModule("mm/page_alloc.ll"))

    snap.filter(["__alloc_pages_nodemask"])
    assert len(snap.fun_groups[None].functions) == 1
    assert "___pskb_trim" not in snap.fun_groups[None].functions
    assert "__alloc_pages_nodemask" in snap.fun_groups[None].functions
示例#5
0
def test_add_fun_none_group():
    """Create a snapshot and try to add functions into a None group."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, None, False)

    mod = LlvmKernelModule("net/core/skbuff.ll")
    snap.add_fun("___pskb_trim", mod)

    assert "___pskb_trim" in snap.fun_groups[None].functions
    fun_desc = snap.fun_groups[None].functions["___pskb_trim"]
    assert fun_desc.mod is mod
    assert fun_desc.glob_var is None
    assert fun_desc.tag is None
示例#6
0
def test_get_by_name_functions():
    """Get the module of inserted function by its name."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, None, False)

    mod_buff = LlvmKernelModule("net/core/skbuff.ll")
    mod_alloc = LlvmKernelModule("mm/page_alloc.ll")
    snap.add_fun("___pskb_trim", mod_buff)
    snap.add_fun("__alloc_pages_nodemask", mod_alloc)

    fun = snap.get_by_name("___pskb_trim")
    assert fun.mod is mod_buff
    fun = snap.get_by_name("__alloc_pages_nodemask")
    assert fun.mod is mod_alloc
示例#7
0
def test_add_fun_sysctl_group():
    """Create a snapshot and try to add functions into sysctl groups."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, "sysctl", False)

    snap.add_fun_group("kernel.sched_latency_ns")
    mod = LlvmKernelModule("kernel/sched/debug.ll")
    snap.add_fun("sched_debug_header", mod, "sysctl_sched_latency",
                 "using_data_variable \"sysctl_sched_latency\"",
                 "kernel.sched_latency_ns")

    assert "sched_debug_header" in snap.fun_groups[
        "kernel.sched_latency_ns"].functions
    fun_desc = snap.fun_groups["kernel.sched_latency_ns"].functions[
        "sched_debug_header"]
    assert fun_desc.mod is mod
    assert fun_desc.glob_var == "sysctl_sched_latency"
    assert fun_desc.tag == "using_data_variable \"sysctl_sched_latency\""
示例#8
0
def test_to_yaml_functions():
    """
    Dump a snapshot with a single "None" group into YAML.
    YAML string should contain the version of Diffkemp, source kernel
    directory, a simple list of functions, each one having the "name",
    "llvm", "glob_var" and "tag" fields set, and the kind of this list,
    which should be a function list.
    The LLVM paths in the YAML should be relative to the snapshot directory.
    """
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir,
                                       KernelLlvmSourceBuilder, None, None,
                                       False)

    snap.add_fun(
        "___pskb_trim",
        LlvmModule("snapshots/linux-3.10.0-957.el7/net/core/skbuff.ll"))
    snap.add_fun("__alloc_pages_nodemask",
                 LlvmModule("snapshots/linux-3.10.0-957.el7/mm/page_alloc.ll"))

    yaml_str = snap.to_yaml()
    yaml_snap = yaml.safe_load(yaml_str)

    assert len(yaml_snap) == 1
    yaml_dict = yaml_snap[0]
    assert len(yaml_dict) == 7
    assert isinstance(yaml_dict["created_time"], datetime.datetime)
    assert yaml_dict["llvm_source_finder"]["kind"] == "kernel_with_builder"
    assert len(yaml_dict["list"]) == 2
    assert set([f["name"] for f in yaml_dict["list"]]) ==\
        {"___pskb_trim",
         "__alloc_pages_nodemask"}

    for f in yaml_dict["list"]:
        if f["name"] == "___pskb_trim":
            assert f["llvm"] == "net/core/skbuff.ll"
        elif f["name"] == "__alloc_pages_nodemask":
            assert f["llvm"] == "mm/page_alloc.ll"
示例#9
0
def test_get_by_name_sysctls():
    """Get the module of inserted function by its name and sysctl group."""
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, "sysctl", False)

    snap.add_fun_group("kernel.sched_latency_ns")
    snap.add_fun_group("kernel.timer_migration")
    mod_fair = LlvmKernelModule(
        "snapshots-sysctl/linux-3.10.0-957.el7/kernel/sched/fair.ll")
    mod_sysctl = LlvmKernelModule(
        "snapshots-sysctl/linux-3.10.0-957.el7/kernel/sysctl.ll")
    snap.add_fun("sched_proc_update_handler", mod_fair, None, "proc handler",
                 "kernel.sched_latency_ns")
    snap.add_fun("proc_dointvec_minmax", mod_sysctl, None, "proc handler",
                 "kernel.timer_migration")

    # Test that the function
    fun = snap.get_by_name("proc_dointvec_minmax", "kernel.sched_latency_ns")
    assert fun is None
    fun = snap.get_by_name("proc_dointvec_minmax", "kernel.timer_migration")
    assert fun.mod is mod_sysctl
示例#10
0
def test_get_modules():
    """
    Test getting all modules in the snapshot function lists.
    Check if the snapshot returns a list of all modules of all groups in case
    that multiple groups are present.
    """
    kernel_dir = "kernel/linux-3.10.0-957.el7"
    output_dir = "snapshots/linux-3.10.0-957.el7"
    snap = Snapshot.create_from_source(kernel_dir, output_dir, "sysctl", False)

    snap.add_fun_group("kernel.sched_latency_ns")
    snap.add_fun_group("kernel.timer_migration")
    snap.add_fun("sched_proc_update_handler",
                 LlvmKernelModule("kernel/sched/fair.ll"), None,
                 "proc_handler", "kernel.sched_latency_ns")
    snap.add_fun("proc_dointvec_minmax", LlvmKernelModule("kernel/sysctl.ll"),
                 None, "proc_handler", "kernel.timer_migration")

    modules = snap.modules()
    assert len(modules) == 2
    assert set([m.llvm for m in modules
                ]) == {"kernel/sched/fair.ll", "kernel/sysctl.ll"}
示例#11
0
def generate(args):
    """
    Generate snapshot of sources of kernel functions.
    This involves:
      - find source code with functions definitions
      - compile the source codes into LLVM IR
      - copy LLVM and C source files into snapshot directory
      - create YAML with list mapping functions to their LLVM sources
    """
    # Create a new snapshot from the source directory.
    snapshot = Snapshot.create_from_source(args.kernel_dir, args.output_dir,
                                           "sysctl" if args.sysctl else None)
    source = snapshot.kernel_source

    # Build sources for symbols from the list into LLVM IR
    with open(args.functions_list, "r") as fun_list_file:
        for line in fun_list_file.readlines():
            symbol = line.strip()
            if not symbol or not (symbol[0].isalpha() or symbol[0] == "_"):
                continue
            if args.sysctl:
                # For a sysctl parameter, we have to:
                #  - get LLVM of a file which defines the sysctl option
                #  - find and compile proc handler function and add it to the
                #    snapshot
                #  - find sysctl data variable
                #  - find, complile, and add to snapshot all functions that
                #    use the data variable

                # Get module with sysctl definitions
                try:
                    sysctl_mod = source.get_sysctl_module(symbol)
                except SourceNotFoundException:
                    print("{}: sysctl not supported".format(symbol))

                # Iterate all sysctls represented by the symbol (it can be
                # a pattern).
                sysctl_list = sysctl_mod.parse_sysctls(symbol)
                if not sysctl_list:
                    print("{}: no sysctl found".format(symbol))
                for sysctl in sysctl_list:
                    print("{}:".format(sysctl))
                    # New group in function list for the sysctl
                    snapshot.add_fun_group(sysctl)

                    # Proc handler function for sysctl
                    proc_fun = sysctl_mod.get_proc_fun(sysctl)
                    if proc_fun:
                        try:
                            proc_fun_mod = source.get_module_for_symbol(
                                proc_fun)
                            snapshot.add_fun(name=proc_fun,
                                             llvm_mod=proc_fun_mod,
                                             glob_var=None,
                                             tag="proc handler function",
                                             group=sysctl)
                            print("  {}: {} (proc handler)".format(
                                proc_fun,
                                os.path.relpath(proc_fun_mod.llvm,
                                                args.kernel_dir)))
                        except SourceNotFoundException:
                            print("  could not build proc handler")

                    # Functions using the sysctl data variable
                    data = sysctl_mod.get_data(sysctl)
                    if not data:
                        continue
                    for data_src in source.find_srcs_using_symbol(data.name):
                        data_mod = source.get_module_from_source(data_src)
                        if not data_mod:
                            continue
                        for data_fun in \
                                data_mod.get_functions_using_param(data):
                            if data_fun == proc_fun:
                                continue
                            snapshot.add_fun(name=data_fun,
                                             llvm_mod=data_mod,
                                             glob_var=data.name,
                                             tag="function using sysctl data "
                                             "variable \"{}\"".format(
                                                 data.name),
                                             group=sysctl)
                            print(
                                "  {}: {} (using data variable \"{}\")".format(
                                    data_fun,
                                    os.path.relpath(data_mod.llvm,
                                                    args.kernel_dir),
                                    data.name))
            else:
                try:
                    # For a normal function, we compile its source and include
                    # it into the snapshot
                    sys.stdout.write("{}: ".format(symbol))
                    llvm_mod = source.get_module_for_symbol(symbol)
                    if not llvm_mod.has_function(symbol):
                        print("unsupported")
                        continue
                    print(os.path.relpath(llvm_mod.llvm, args.kernel_dir))
                    snapshot.add_fun(symbol, llvm_mod)
                except SourceNotFoundException:
                    print("source not found")
                    snapshot.add_fun(symbol, None)

    snapshot.generate_snapshot_dir()
    snapshot.finalize()