summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Maennich <maennich@google.com>2019-03-29 08:40:18 +0000
committerMatthias Maennich <maennich@google.com>2019-04-02 08:45:41 +0100
commitcec41ee52fc9966bcab1a31ea591bec5b140a306 (patch)
tree9b04fa40f91725afa3ed72b3575b33db53630157
parentf7d7e4dca29372c591e89e49451a7b0251f85351 (diff)
Initial version of the abi monitoring utilities
Add a generic abitool implementation that is capable of translating common abi operations like dumping and diffing to concrete tool implementation. Also add the cmd line utilities `diff_abi` and `dump_abi`. Bug: 111449103 Co-authored-by: Jayant Chowdhary <jchowdhary@google.com> Change-Id: I1c4dedb96f4806ea58cf11786d0e7464e26f3059 Signed-off-by: Matthias Maennich <maennich@google.com>
-rw-r--r--abi/.gitignore2
-rw-r--r--abi/README.md20
-rw-r--r--abi/abitool.py71
-rwxr-xr-xabi/diff_abi50
-rwxr-xr-xabi/dump_abi47
5 files changed, 190 insertions, 0 deletions
diff --git a/abi/.gitignore b/abi/.gitignore
index 3438f57..6ddc8a7 100644
--- a/abi/.gitignore
+++ b/abi/.gitignore
@@ -1 +1,3 @@
abigail-*
+*.pyc
+__pycache__
diff --git a/abi/README.md b/abi/README.md
index 4b8544a..23541b7 100644
--- a/abi/README.md
+++ b/abi/README.md
@@ -18,3 +18,23 @@ the local `${PATH}` to be used by the remaining utilities.
You can skip this step if your host system provides a suitable version of the
libabigail tooling including the binaries `abidw` and `abidiff`.
+
+
+Creating ABI dumps from kernel trees
+------------------------------------
+Provided a linux kernel tree with built vmlinux and kernel modules, the tool
+`dump_abi` creates an ABI representation using the selected abi tool. As of now
+there is only one option: 'libabigail' (default). A sample invocation looks as
+follows:
+ $ dump_abi --linux-tree path/to/out --out-file /path/to/abidump.out
+
+
+Comparing ABI dumps
+-------------------
+ABI dumps created by `dump_abi` can be compared with `diff_abi`. Ensure to use
+the same abi-tool for `dump_abi` and `diff_abi`. A sample invocation looks as
+follows:
+ $ diff_abi --baseline dump1.out --new dump2.out --report report.out
+
+The report created is tool specific, but generally lists ABI changes detected
+that affect the Kernel's module interface.
diff --git a/abi/abitool.py b/abi/abitool.py
new file mode 100644
index 0000000..9491c3f
--- /dev/null
+++ b/abi/abitool.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import subprocess
+import logging
+
+log = logging.getLogger(__name__)
+
+class AbiTool(object):
+ """ Base class for different kinds of abi analysis tools"""
+ def dump_kernel_abi(self, linux_tree, dump_path):
+ raise NotImplementedError()
+
+ def diff_abi(self, old_dump, new_dump, diff_report):
+ raise NotImplementedError()
+
+ def name(self):
+ raise NotImplementedError()
+
+class Libabigail(AbiTool):
+ """" Concrete AbiTool implementation for libabigail """
+ def dump_kernel_abi(self, linux_tree, dump_path):
+ dump_abi_cmd = ['abidw',
+ '--linux-tree',
+ linux_tree,
+ '--out-file',
+ dump_path]
+ subprocess.check_call(dump_abi_cmd)
+
+ def diff_abi(self, old_dump, new_dump, diff_report):
+ log.info('libabigail diffing: {} and {} at {}'.format(old_dump,
+ new_dump,
+ diff_report))
+ diff_abi_cmd = ['abidiff',
+ '--impacted-interfaces',
+ '--leaf-changes-only',
+ '--dump-diff-tree',
+ old_dump,
+ new_dump]
+
+ with open(diff_report, 'w') as out:
+ try:
+ subprocess.check_call(diff_abi_cmd, stdout=out, stderr=out)
+ except subprocess.CalledProcessError as e:
+ if e.returncode in (1, 2): # abigail error, user error
+ raise
+ return True # actual abi change
+
+ return False # no abi change
+
+def get_abi_tool(abi_tool):
+ if abi_tool == 'libabigail':
+ log.info('using libabigail for abi analysis')
+ return Libabigail()
+
+ raise ValueError("not a valid abi_tool: %s" % abi_tool)
+
diff --git a/abi/diff_abi b/abi/diff_abi
new file mode 100755
index 0000000..7ea4448
--- /dev/null
+++ b/abi/diff_abi
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+import os
+import sys
+
+from abitool import get_abi_tool
+
+def diff_abi(abitool, baseline, new, out_file):
+ tool = get_abi_tool(abitool)
+ return tool.diff_abi(baseline, new, out_file)
+
+def main():
+ """ Build the linux kernel, freshly cloning if needed"""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--baseline', help='baseline dump to compare to',
+ required=True)
+ parser.add_argument('--new', help='new dump to compare to baseline',
+ required=True)
+ parser.add_argument('--abi-tool', default='libabigail',
+ help='abi tool to be used to monitor abi')
+ parser.add_argument('--report', help='where to write the report to',
+ required=True)
+
+ args = parser.parse_args()
+
+ abi_changed = diff_abi(args.abi_tool,
+ args.baseline,
+ args.new,
+ args.report)
+ if abi_changed:
+ return 8
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/abi/dump_abi b/abi/dump_abi
new file mode 100755
index 0000000..3791504
--- /dev/null
+++ b/abi/dump_abi
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+import os
+import sys
+
+from abitool import get_abi_tool
+
+def dump_abi(abitool, linux_tree, out_file):
+ tool = get_abi_tool(abitool)
+ tool.dump_kernel_abi(linux_tree, out_file)
+
+def main():
+ """ Build the linux kernel, freshly cloning if needed"""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--linux-tree',
+ help='Path to kernel tree containing '
+ 'vmlinux and modules',
+ required=True)
+ parser.add_argument('--abi-tool', default='libabigail',
+ help='abi tool to be used to monitor abi')
+ parser.add_argument('--out-file', default=None,
+ help='where to write the abi dump to')
+
+ args = parser.parse_args()
+
+ dump_abi(args.abi_tool,
+ args.linux_tree,
+ args.out_file or os.path.join(args.linux_tree, "abi.out"))
+
+if __name__ == "__main__":
+ sys.exit(main())