Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set(CMAKE_CXX_STANDARD 17)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)

include(GNUInstallDirs)

Expand Down
2 changes: 1 addition & 1 deletion cmake/FindZ3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Z3_CXX_INCLUDE_DIRS - the z3 C++ include directory
# Z3_LIBRARIES - Link these to use libbpf

find_path (Z3_CXX_INCLUDE_DIRS z3++.h)
find_path (Z3_CXX_INCLUDE_DIRS z3++.h PATH_SUFFIXES z3)

find_library (Z3_LIBRARIES z3)

Expand Down
35 changes: 3 additions & 32 deletions diffkemp/building/build_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from diffkemp.snapshot import Snapshot
from diffkemp.building.build_utils import (
generate_from_function_list,
add_funcs_for_globvar,
read_symbol_list,
EMSG_EMPTY_SYMBOL_LIST)
import errno
Expand Down Expand Up @@ -97,7 +98,8 @@ def generate_from_sysctl_list(snapshot, sysctl_list):
# Proc handler function for sysctl
_add_proc_handler(snapshot, sysctl, proc_fun)
# Adds functions which use the sysctl data variable
_add_funcs_for_data(snapshot, sysctl, sysctl_mod, proc_fun)
data = sysctl_mod.get_data(sysctl)
add_funcs_for_globvar(snapshot, sysctl, data, proc_fun)


def _add_proc_handler(snapshot, sysctl, proc_fun):
Expand All @@ -118,34 +120,3 @@ def _add_proc_handler(snapshot, sysctl, proc_fun):
snapshot.source_tree.source_dir)))
except SourceNotFoundException:
print(" could not build proc handler")


def _add_funcs_for_data(snapshot, sysctl, sysctl_mod, proc_fun):
data = sysctl_mod.get_data(sysctl)

if not data:
return

for module in \
snapshot.source_tree.get_modules_using_symbol(data.name):
# For now, we only support the x86 architecture in kernel
if "/arch/" in module.llvm and \
"/arch/x86/" not in module.llvm:
continue

curr_mod_path = os.path.relpath(module.llvm,
snapshot.source_tree.source_dir)
for func in module.get_functions_using_param(data):
if func == proc_fun:
continue

snapshot.add_fun(
name=func,
llvm_mod=module,
glob_var=data.name,
tag="using data variable \"{}\"".format(data.name),
group=sysctl)
print(" {}: {} (using data variable \"{}\")".format(
func,
curr_mod_path,
data.name))
39 changes: 38 additions & 1 deletion diffkemp/building/build_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from diffkemp.llvm_ir.source_tree import SourceNotFoundException
from diffkemp.llvm_ir.llvm_module import LlvmParam
import sys
import os

Expand Down Expand Up @@ -41,9 +42,45 @@ def generate_from_function_list(snapshot, fun_list):
snapshot.add_fun(symbol, llvm_mod)
print(os.path.relpath(llvm_mod.llvm,
snapshot.source_tree.source_dir))
elif llvm_mod.has_global(symbol):
print()
if add_funcs_for_globvar(snapshot, symbol, LlvmParam(symbol)):
snapshot.list_kind = "glob_var"
else:
snapshot.add_fun(symbol, None)
print("not a function")
print("not a function nor a global variable")
except SourceNotFoundException:
print("source not found")
snapshot.add_fun(symbol, None)


def add_funcs_for_globvar(snapshot, name, data, skip_fun=None):
functions_added = False
if not data:
return functions_added

for module in \
snapshot.source_tree.get_modules_using_symbol(data.name):
# For now, we only support the x86 architecture in kernel
if "/arch/" in module.llvm and \
"/arch/x86/" not in module.llvm:
continue

curr_mod_path = os.path.relpath(module.llvm,
snapshot.source_tree.source_dir)
for func in module.get_functions_using_param(data):
if skip_fun is not None and func == skip_fun:
continue

functions_added = True
snapshot.add_fun(
name=func,
llvm_mod=module,
glob_var=data.name,
tag="using global variable \"{}\"".format(data.name),
group=name)
print(" {}: {} (using global variable \"{}\")".format(
func,
curr_mod_path,
data.name))
return functions_added
18 changes: 13 additions & 5 deletions diffkemp/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def compare(args):

class GroupInfo:
def __init__(self, group, group_name, enable_module_cache, config,
output_dir):
output_dir, group_kind):
self.group = group
self.group_name = group_name
self.group_dir = self._get_group_dir(output_dir)
Expand All @@ -44,6 +44,7 @@ def __init__(self, group, group_name, enable_module_cache, config,
self.cache = SimpLLCache(mkdtemp())
self.module_cache = {}
self.group_result = None
self.group_kind = group_kind

def _get_group_dir(self, output_dir):
if output_dir is not None and self.group_name is not None:
Expand Down Expand Up @@ -92,7 +93,8 @@ def __init__(self, cmd_args):
self.result = Result(Result.Kind.NONE, cmd_args.snapshot_dir_old,
cmd_args.snapshot_dir_new,
start_time=default_timer(),
hierarchy_level=Result.HierarchyLevel.OVERALL)
hierarchy=Result.Hierarchy(
Result.Hierarchy.Level.OVERALL))
self.regex_pattern = re.compile(cmd_args.regex_filter) \
if cmd_args.regex_filter else None
self.output_dir = None
Expand Down Expand Up @@ -130,11 +132,15 @@ def _default_output_dir(self):
return base_dirname

def _compare_snapshots(self):
# group_name could be None or str, which are uncomparable
for group_name, group in sorted(self.config.snapshot_first
.fun_groups.items()):
.fun_groups.items(),
key=lambda item: (item[0] is not None,
item[0])):
group_info = GroupInfo(group, group_name,
self.args.enable_module_cache,
self.config, self.output_dir)
self.config, self.output_dir,
self.config.snapshot_first.list_kind)
self._compare_groups(group_info)

self._finalize_output()
Expand All @@ -149,7 +155,9 @@ def _compare_groups(self, group_info):
Result.Kind.NONE,
group_name,
group_name,
hierarchy_level=Result.HierarchyLevel.GROUP)
hierarchy=Result.Hierarchy(
Result.Hierarchy.Level.GROUP,
group_info.group_kind))
else:
group_info.group_result = self.result

Expand Down
6 changes: 3 additions & 3 deletions diffkemp/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def _create_output(self):

def _create_results(self, current_result, name=None):
""":param current_result: node in the result class tree"""
if current_result.hierarchy_level == Result.HierarchyLevel.FUNCTION:
if current_result.hierarchy.level == Result.Hierarchy.Level.FUNCTION:
return self._create_function_result(current_result, name)

inner_results = []
Expand All @@ -44,11 +44,11 @@ def _create_results(self, current_result, name=None):
if result is not None:
inner_results.append(result)

if current_result.hierarchy_level == Result.HierarchyLevel.OVERALL:
if current_result.hierarchy.level == Result.Hierarchy.Level.OVERALL:
return inner_results
# hierarchy_level == GROUP
return {
"sysctl": name, # sysctl is the only usecase of groups
current_result.hierarchy.group_kind: name,
"results": inner_results
}

Expand Down
24 changes: 15 additions & 9 deletions diffkemp/semdiff/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,16 @@ def __init__(self, name, filename=None, line=None, callstack=None,
self.diff_kind = diff_kind
self.covered = covered

class HierarchyLevel(IntEnum):
class Hierarchy:
"""Describes position of result instance in result comparison tree"""
OVERALL = 0
GROUP = 1
FUNCTION = 2
class Level(IntEnum):
OVERALL = 0
GROUP = 1
FUNCTION = 2

def __init__(self, level, group_kind=None):
self.level = level
self.group_kind = group_kind

class SymbolStat:
def __init__(self):
Expand All @@ -199,7 +204,8 @@ def __init__(self):
self.empty_diff = 0

def __init__(self, kind, first_name, second_name, start_time=None,
stop_time=None, hierarchy_level=HierarchyLevel.FUNCTION):
stop_time=None,
hierarchy=Hierarchy(Hierarchy.Level.FUNCTION)):
self.kind = kind
self.first = Result.Entity(first_name)
self.second = Result.Entity(second_name)
Expand All @@ -209,7 +215,7 @@ def __init__(self, kind, first_name, second_name, start_time=None,
self.inner = dict()
self.start_time = start_time
self.stop_time = stop_time
self.hierarchy_level = hierarchy_level
self.hierarchy = hierarchy

def __str__(self):
return str(self.kind)
Expand Down Expand Up @@ -264,7 +270,7 @@ def report_symbol_stat(self, show_errors=False):

def print_function_names(self, kind):
for name, result in self.inner.items():
if result.hierarchy_level == Result.HierarchyLevel.FUNCTION:
if result.hierarchy.level == Result.Hierarchy.Level.FUNCTION:
if result.kind == kind:
print(name)
else:
Expand All @@ -273,7 +279,7 @@ def print_function_names(self, kind):
def _populate_symbol_stat(self, stats):
"""Aggregate statistics about analysed symbols."""
for result in self.inner.values():
if result.hierarchy_level == Result.HierarchyLevel.FUNCTION:
if result.hierarchy.level == Result.Hierarchy.Level.FUNCTION:
stats.total += 1
stats.eq += result.kind == Result.Kind.EQUAL
stats.neq += result.kind == Result.Kind.NOT_EQUAL
Expand Down Expand Up @@ -306,7 +312,7 @@ def __hash__(self):
return hash(self.res.first.name)

def _populate_unique_diffs(result, unique_diffs):
if result.hierarchy_level == Result.HierarchyLevel.FUNCTION:
if result.hierarchy.level == Result.Hierarchy.Level.FUNCTION:
for _, inner_res in result.inner.items():
if (inner_res.diff == "" and
inner_res.first.covered):
Expand Down
8 changes: 4 additions & 4 deletions diffkemp/simpll/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ execute_process(COMMAND llvm-config --system-libs
OUTPUT_VARIABLE system_libs
OUTPUT_STRIP_TRAILING_WHITESPACE)

# Try to find system-wide Z3 (e.g. local build)
find_package(Z3 CONFIG)
# Use our FindZ3.cmake (e.g. nix build)
find_package(Z3 MODULE)
if (NOT ${Z3_FOUND})
# Use our FindZ3.cmake (e.g. nix build)
find_package(Z3 REQUIRED MODULE)
# Try to find system-wide Z3 (e.g. local build)
find_package(Z3 REQUIRED CONFIG)
endif()

add_library(simpll-lib ${srcs} ${passes} ${library})
Expand Down
3 changes: 3 additions & 0 deletions diffkemp/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ def _from_yaml(self, yaml_file):
if "sysctl" in g:
group = g["sysctl"]
functions = g["functions"]
elif "glob_var" in g:
group = g["glob_var"]
functions = g["functions"]
else:
group = None
functions = g
Expand Down
15 changes: 9 additions & 6 deletions tests/unit_tests/result_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def single_function_result(graph):
@pytest.fixture
def multi_functions_result(graph, single_function_result):
result = Result(Result.Kind.NONE, "old-snapshot-path", "new-snapshot-path",
hierarchy_level=Result.HierarchyLevel.OVERALL)
hierarchy=Result.Hierarchy(Result.Hierarchy.Level.OVERALL))
result.add_inner(single_function_result)
result.graph = graph
yield result
Expand All @@ -132,9 +132,10 @@ def multi_functions_result(graph, single_function_result):
@pytest.fixture
def sysctl_group_result(graph, single_function_result):
result = Result(Result.Kind.NONE, "old-snapshot-path", "new-snapshot-path",
hierarchy_level=Result.HierarchyLevel.OVERALL)
hierarchy=Result.Hierarchy(Result.Hierarchy.Level.OVERALL))
group_result = Result(Result.Kind.NONE, "group_name", "group_name",
hierarchy_level=Result.HierarchyLevel.GROUP)
hierarchy=Result.Hierarchy(
Result.Hierarchy.Level.GROUP, "sysctl"))
group_result.add_inner(single_function_result)
result.add_inner(group_result)
result.graph = graph
Expand All @@ -144,11 +145,13 @@ def sysctl_group_result(graph, single_function_result):
@pytest.fixture
def multi_groups_result(graph, single_function_result):
result = Result(Result.Kind.NONE, "old-snapshot-path", "new-snapshot-path",
hierarchy_level=Result.HierarchyLevel.OVERALL)
hierarchy=Result.Hierarchy(Result.Hierarchy.Level.OVERALL))
outer_group_result = Result(Result.Kind.NONE, "outer_name", "outer_name",
hierarchy_level=Result.HierarchyLevel.GROUP)
hierarchy=Result.Hierarchy(
Result.Hierarchy.Level.GROUP, "sysctl"))
inner_group_result = Result(Result.Kind.NONE, "inner_name", "inner_name",
hierarchy_level=Result.HierarchyLevel.GROUP)
hierarchy=Result.Hierarchy(
Result.Hierarchy.Level.GROUP, "sysctl"))
inner_group_result.add_inner(single_function_result)
outer_group_result.add_inner(inner_group_result)
result.add_inner(outer_group_result)
Expand Down
8 changes: 4 additions & 4 deletions tests/unit_tests/simpll/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ execute_process(COMMAND llvm-config --system-libs
OUTPUT_VARIABLE system_libs
OUTPUT_STRIP_TRAILING_WHITESPACE)

# Try to find system-wide Z3 (e.g. local build)
find_package(Z3 CONFIG)
# Use our FindZ3.cmake (e.g. nix build)
find_package(Z3 MODULE)
if (NOT ${Z3_FOUND})
# Use our FindZ3.cmake (e.g. nix build)
find_package(Z3 REQUIRED MODULE)
# Try to find system-wide Z3 (e.g. local build)
find_package(Z3 REQUIRED CONFIG)
endif()

target_include_directories(simpllTests PRIVATE ${Z3_CXX_INCLUDE_DIRS})
Expand Down
Loading