diff options
author | Matthias Maennich <maennich@google.com> | 2019-03-29 08:40:18 +0000 |
---|---|---|
committer | Matthias Maennich <maennich@google.com> | 2019-04-02 08:45:41 +0100 |
commit | cec41ee52fc9966bcab1a31ea591bec5b140a306 (patch) | |
tree | 9b04fa40f91725afa3ed72b3575b33db53630157 | |
parent | f7d7e4dca29372c591e89e49451a7b0251f85351 (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/.gitignore | 2 | ||||
-rw-r--r-- | abi/README.md | 20 | ||||
-rw-r--r-- | abi/abitool.py | 71 | ||||
-rwxr-xr-x | abi/diff_abi | 50 | ||||
-rwxr-xr-x | abi/dump_abi | 47 |
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()) |