From 83ceee4a5f12f83c7159142f5ace63aad838532d Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Tue, 21 Jul 2020 14:31:13 +0800 Subject: [PATCH 1/7] add check_abi --- advisors/check_abi.py | 253 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100755 advisors/check_abi.py diff --git a/advisors/check_abi.py b/advisors/check_abi.py new file mode 100755 index 00000000..9f751320 --- /dev/null +++ b/advisors/check_abi.py @@ -0,0 +1,253 @@ +#!/usr/bin/python3 +#****************************************************************************** +# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. +# licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. +# Author: wangchuangGG +# Create: 2020-07-20 +# ******************************************************************************/ + +""" +(1) This script is used to check the interface changes between the old + and new versions of the C/C++ language pack. + The final difference information result is saved in the xxx.abidiff.out file in the working directory + +(2) To use this script, you must first install the Libabigail service, + you can download and install libabigail-xxx.rpm in the community. + +(3) Command parameters + Required parameters: + -rpm1 Specify the old version rpm path or url + (e.g. /home/test-1.0.rpm or https://example.com/test-1.0.rpm) + + -rpm2 Specify the new version rpm path or url + (e.g. /home/test-2.0.rpm or https://example.com/test-2.0.rpm) + + -debug1 Specify the old version debuginfo_rpm path or url + (e.g. /home/test-debuginfo-1.0.rpm or https://example.com/test-debuginfo-1.0.rpm) + + -debug2 Specify the new version debuginfo_rpm path or url + (e.g. /home/test-debuginfo-2.0.rpm or https://example.com/test-debuginfo-2.0.rpm) + + Optional parameters: + -d Specify the work path of the rpm2cpio + default: /var/tmp/ + + -all Show all infos includ changes in member name + default: False +""" +import argparse +import subprocess +import sys +import os +import logging +import pycurl +import io +logging.basicConfig(format='%(message)s', level=logging.INFO) + +def parse_command_line(): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument("-rpm1", "--old_rpm", default="", + nargs="?", required=1, + help = "the old version rpm path or url") + parser.add_argument("-rpm2", "--new_rpm", default="", + nargs="?", required=1, + help = "the new version rpm path or url") + parser.add_argument("-debug1", "--old_debuginfo_rpm", + default="", nargs="?", required=1, + help = "the old version debuginfo_rpm path or url") + parser.add_argument("-debug2", "--new_debuginfo_rpm", + default="", nargs="?", required=1, + help = "the new version debuginfo_rpm path or url") + parser.add_argument("-d", "--work_path", default="", nargs="?", + help="The work path to put rpm2cpio files and results" + " (e.g. /home/tmp_abidiff default: /var/tmp/)") + parser.add_argument("-all", "--show_all_info", action="store_true", default=False, + help="show all infos includ changes in member name") + return parser.parse_args() + + +def do_curl(url, dest=None): + """ + Perform a curl operation for url. + If perform failure or write to dest failure, + the program exiting with an error. + """ + c = pycurl.Curl() + c.setopt(c.URL, url) + c.setopt(c.FOLLOWLOCATION, True) + c.setopt(c.FAILONERROR, True) + c.setopt(c.CONNECTTIMEOUT, 10) + c.setopt(c.TIMEOUT, 600) + c.setopt(c.LOW_SPEED_LIMIT, 1) + c.setopt(c.LOW_SPEED_TIME, 10) + buf = io.BytesIO() + c.setopt(c.WRITEDATA, buf) + try: + c.perform() + except pycurl.error as e: + print("Unable to fetch {}: {} or rpm path is wrong".format(url, e)) + sys.exit(1) + finally: + c.close() + + if dest: + try: + with open(dest, 'wb') as fp: + fp.write(buf.getvalue()) + except IOError as e: + if os.path.exists(dest): + os.unlink(dest) + print("Unable to write to {}: {}".format(dest, e)) + sys.exit(1) + + +def find_so_file(path, word): + """ + Try to find the so file. + return the full path of so file. + """ + base_word = word.split('-')[0][0:-1] + logging.debug("the rpm base name:%s", base_word) + for dirpath, dirnames, files in os.walk(path): + for filename in files: + fp = os.path.join(dirpath, filename) + if base_word in filename and ".so" in filename: + return fp + return path + + +def get_rpm2cpio_path(work_path, abipath): + """ + Get the path to put so file from rpm + return the path. + """ + fp = os.path.join(work_path, abipath) + if os.path.isdir(fp): + subprocess.run("rm -rf {}".format(fp), shell=True) + subprocess.run("mkdir {}".format(fp), shell=True) + return fp + + +def get_rpm_path(rpm_url, dest): + """Get the path of rpm package""" + if os.path.isfile(rpm_url): + abs_rpmpath = os.path.abspath(rpm_url) + logging.debug("rpm exists:%s", abs_rpmpath) + return abs_rpmpath + else: + rpm_name = os.path.basename(rpm_url) + rpm_path = os.path.join(dest, rpm_name) + logging.debug("downloading %s......", rpm_name) + do_curl(rpm_url, rpm_path) + return rpm_path + + +def get_work_path(config): + work_path = "/var/tmp" + if config.work_path: + work_path = os.path.abspath(config.work_path) + logging.debug("work_path assigned:%s", work_path) + return work_path + + +def main(): + """Entry point for check_abi""" + config = parse_command_line() + work_path = get_work_path(config) + + old_rpm2cpio_path = get_rpm2cpio_path(work_path, "old_abi") + new_rpm2cpio_path = get_rpm2cpio_path(work_path, "new_abi") + logging.debug("old_rpm2cpio_path:%s\nnew_rpm2cpio_path:%s", + old_rpm2cpio_path, new_rpm2cpio_path) + + old_rpm = get_rpm_path(config.old_rpm, old_rpm2cpio_path) + old_debuginfo_rpm = get_rpm_path(config.old_debuginfo_rpm, old_rpm2cpio_path) + + new_rpm = get_rpm_path(config.new_rpm, new_rpm2cpio_path) + new_debuginfo_rpm = get_rpm_path(config.new_debuginfo_rpm, new_rpm2cpio_path) + logging.debug("old_rpm:%s\nold_debuginfo_rpm:%s\n" + "new_rpm:%s\nnew_debuginfo_rpm:%s", + old_rpm, + old_debuginfo_rpm, + new_rpm, + new_debuginfo_rpm) + + os.chdir(old_rpm2cpio_path) + logging.debug("\n----old version working in path:%s----", os.getcwd()) + logging.debug("rpm2cpio %s", old_rpm) + subprocess.run("rpm2cpio {} | cpio -id".format(old_rpm), + shell=True) + + logging.debug("rpm2cpio %s", old_debuginfo_rpm) + subprocess.run("rpm2cpio {} | cpio -id".format(old_debuginfo_rpm), + shell=True) + + os.chdir(new_rpm2cpio_path) + logging.debug("\n----new version working in path:%s----", os.getcwd()) + logging.debug("rpm2cpio %s", new_rpm) + subprocess.run("rpm2cpio {} | cpio -id".format(new_rpm), + shell=True) + + logging.debug("rpm2cpio %s", new_debuginfo_rpm) + subprocess.run("rpm2cpio {} | cpio -id".format(new_debuginfo_rpm), + shell=True) + + os.chdir(work_path) + logging.debug("\n----begin abidiff working in path:%s----", os.getcwd()) + + old_so_file = find_so_file(os.path.join(old_rpm2cpio_path, "usr/lib64"), + os.path.basename(old_rpm)) + new_so_file = find_so_file(os.path.join(new_rpm2cpio_path, "usr/lib64"), + os.path.basename(new_rpm)) + + old_debuginfo_path = os.path.join(old_rpm2cpio_path, "usr/lib/debug") + new_debuginfo_path = os.path.join(new_rpm2cpio_path, "usr/lib/debug") + logging.debug("old_so_file:%s\nnew_so_file:%s\n" + "old_debuginfo_path:%s\nnew_debuginfo_path:%s", + old_so_file, + new_so_file, + old_debuginfo_path, + new_debuginfo_path) + + if not os.path.isfile(old_so_file) or not os.path.isfile(new_so_file): + logging.info("There has no so file") + sys.exit(0) + + abidiff_file = os.path.join(work_path, "{}_abidiff.out".format(os.path.basename(new_rpm))) + if config.show_all_info: + completed_process = subprocess.run("abidiff {} {} --d1 {} --d2 {} --harmless > {}".format( + old_so_file, + new_so_file, + old_debuginfo_path, + new_debuginfo_path, + abidiff_file), + shell=True) + else: + completed_process = subprocess.run("abidiff {} {} --d1 {} --d2 {} > {}".format( + old_so_file, + new_so_file, + old_debuginfo_path, + new_debuginfo_path, + abidiff_file), + shell=True) + ABIDIFF_ERROR_BIT = 1 + if completed_process.returncode == 0: + logging.info("No abidiff found") + elif completed_process.returncode & ABIDIFF_ERROR_BIT: + logging.info("An unexpected error happened") + else: + logging.info("Found abidiffs, results at: {}".format(abidiff_file)) + + sys.exit(0) + + +if __name__ == "__main__": + main() -- Gitee From 37684a1c281bf3bbb3a4d882bc238cdefdee1e16 Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Fri, 24 Jul 2020 11:32:51 +0800 Subject: [PATCH 2/7] update check_abi --- advisors/check_abi.py | 405 +++++++++++++++++++++++++++++------------- 1 file changed, 279 insertions(+), 126 deletions(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index 9f751320..6421bcba 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -28,14 +28,28 @@ -rpm2 Specify the new version rpm path or url (e.g. /home/test-2.0.rpm or https://example.com/test-2.0.rpm) + + Or: + -so1 Specify the old version .so file + (e.g /home/test-1.0.so) + + -so2 Specify the old version .so file + (e.g /home/test-2.0.so) + + Optional parameters: - -debug1 Specify the old version debuginfo_rpm path or url + -d_rpm1 Specify the old version debuginfo_rpm path or url (e.g. /home/test-debuginfo-1.0.rpm or https://example.com/test-debuginfo-1.0.rpm) - -debug2 Specify the new version debuginfo_rpm path or url + -d_rpm2 Specify the new version debuginfo_rpm path or url (e.g. /home/test-debuginfo-2.0.rpm or https://example.com/test-debuginfo-2.0.rpm) - Optional parameters: + -d_path1 Specify the old version debuginfo file path + (e.g. /home/test-1.0/lib/debug/) + + -d_path2 Specify the new version debuginfo file path + (e.g. /home/test-2.0/lib/debug/) + -d Specify the work path of the rpm2cpio default: /var/tmp/ @@ -47,25 +61,39 @@ import subprocess import sys import os import logging -import pycurl +#import pycurl import io -logging.basicConfig(format='%(message)s', level=logging.INFO) - +logging.basicConfig(format='%(message)s', level=logging.DEBUG) + +all_so_pair = {} + def parse_command_line(): """Parse the command line arguments.""" parser = argparse.ArgumentParser() parser.add_argument("-rpm1", "--old_rpm", default="", - nargs="?", required=1, + nargs="?", help = "the old version rpm path or url") parser.add_argument("-rpm2", "--new_rpm", default="", - nargs="?", required=1, + nargs="?", help = "the new version rpm path or url") - parser.add_argument("-debug1", "--old_debuginfo_rpm", - default="", nargs="?", required=1, + parser.add_argument("-d_rpm1", "--old_debuginfo_rpm", + default="", nargs="?", help = "the old version debuginfo_rpm path or url") - parser.add_argument("-debug2", "--new_debuginfo_rpm", - default="", nargs="?", required=1, + parser.add_argument("-d_rpm2", "--new_debuginfo_rpm", + default="", nargs="?", help = "the new version debuginfo_rpm path or url") + parser.add_argument("-so1", "--old_so", default="", + nargs="?", + help = "the old version .so file") + parser.add_argument("-so2", "--new_so", default="", + nargs="?", + help = "the new version .so file") + parser.add_argument("-d_path1", "--old_debuginfo_path", default="", + nargs="?", + help = "the old version debuginfo file path") + parser.add_argument("-d_path2", "--new_debuginfo_path", default="", + nargs="?", + help = "the new version debuginfo file path") parser.add_argument("-d", "--work_path", default="", nargs="?", help="The work path to put rpm2cpio files and results" " (e.g. /home/tmp_abidiff default: /var/tmp/)") @@ -73,55 +101,41 @@ def parse_command_line(): help="show all infos includ changes in member name") return parser.parse_args() - -def do_curl(url, dest=None): - """ - Perform a curl operation for url. - If perform failure or write to dest failure, - the program exiting with an error. - """ - c = pycurl.Curl() - c.setopt(c.URL, url) - c.setopt(c.FOLLOWLOCATION, True) - c.setopt(c.FAILONERROR, True) - c.setopt(c.CONNECTTIMEOUT, 10) - c.setopt(c.TIMEOUT, 600) - c.setopt(c.LOW_SPEED_LIMIT, 1) - c.setopt(c.LOW_SPEED_TIME, 10) - buf = io.BytesIO() - c.setopt(c.WRITEDATA, buf) - try: - c.perform() - except pycurl.error as e: - print("Unable to fetch {}: {} or rpm path is wrong".format(url, e)) - sys.exit(1) - finally: - c.close() - - if dest: - try: - with open(dest, 'wb') as fp: - fp.write(buf.getvalue()) - except IOError as e: - if os.path.exists(dest): - os.unlink(dest) - print("Unable to write to {}: {}".format(dest, e)) - sys.exit(1) - -def find_so_file(path, word): +def find_so_file(path): """ - Try to find the so file. - return the full path of so file. + Try to find .so files in path. + return .so files. """ - base_word = word.split('-')[0][0:-1] - logging.debug("the rpm base name:%s", base_word) + so_files = [] for dirpath, dirnames, files in os.walk(path): - for filename in files: + for filename in files: fp = os.path.join(dirpath, filename) - if base_word in filename and ".so" in filename: - return fp - return path + if ".so" in filename and not os.path.islink(fp): + #fp = os.path.join(dirpath, filename) + so_files.append(fp) + return so_files + + +def find_all_so_file(path1, path2): + """ + Try to find all .so files. + """ + old_so = find_so_file(path1) + new_so = find_so_file(path2) + logging.debug("old_so:%s\n",old_so) + logging.debug("new_so:%s\n",new_so) + if old_so and new_so: + for so_file1 in old_so: + for so_file2 in new_so: + base_name1 = (os.path.basename(so_file1)).split('.')[0] + base_name2 = (os.path.basename(so_file2)).split('.')[0] + if base_name1 == base_name2: + all_so_pair[so_file1] = so_file2 + else: + logging.info("Not found so files") + sys.exit(0) + logging.debug("all so files:%s\n", all_so_pair) def get_rpm2cpio_path(work_path, abipath): @@ -146,23 +160,177 @@ def get_rpm_path(rpm_url, dest): rpm_name = os.path.basename(rpm_url) rpm_path = os.path.join(dest, rpm_name) logging.debug("downloading %s......", rpm_name) - do_curl(rpm_url, rpm_path) + subprocess.call(["curl", rpm_url, "-L", + "--connect-timeout", "10", + "--max-time", "600", + "-sS", "-o", rpm_path]) return rpm_path def get_work_path(config): + """ + Get the work path + return the path. + """ work_path = "/var/tmp" if config.work_path: work_path = os.path.abspath(config.work_path) logging.debug("work_path assigned:%s", work_path) return work_path + - -def main(): - """Entry point for check_abi""" - config = parse_command_line() - work_path = get_work_path(config) - +def do_rpm2cpio(rpm2cpio_path, rpm_file): + """ + Exec the rpm2cpio at rpm2cpio_path. + """ + os.chdir(rpm2cpio_path) + logging.debug("\n----working in path:%s----", os.getcwd()) + logging.debug("rpm2cpio %s", rpm_file) + subprocess.run("rpm2cpio {} | cpio -id".format(rpm_file), shell=True) + + +def merge_all_abidiff_files(all_abidiff_files, work_path, rpm_base_name): + """ + Merge the all diff files to merged_file. + return the merged_file. + """ + merged_file = os.path.join(work_path, "{}_all_abidiff.out".format(rpm_base_name)) + if os.path.exists(merged_file): + subprocess.run("rm -rf {}".format(merged_file), shell=True) + + ofile = open(merged_file, "a+") + for diff_file in all_abidiff_files: + diff_file_name = os.path.basename(diff_file) + ofile.write("---------------diffs in {}:----------------\n".format(diff_file_name)) + for txt in open(diff_file, "r"): + ofile.write(txt) + ofile.close() + return merged_file + + +def do_abidiff(config, work_path, base_name, old_debuginfo_path, new_debuginfo_path): + """ + Exec the abidiff and write result to files. + return the abidiff returncode. + """ + if not all_so_pair: + logging.info("There has no so file") + sys.exit(0) + else: + return_code = 0 + all_abidiff_files = [] + for old_so_file in all_so_pair: + new_so_file = all_so_pair[old_so_file] + logging.debug( "begin abidiff between %s and %s", old_so_file, new_so_file) + + abidiff_file = os.path.join(work_path, + "{}_{}_abidiff.out".format( + base_name, os.path.basename(new_so_file))) + + if config.show_all_info: + if old_debuginfo_path and new_debuginfo_path: + logging.debug("old_debuginfo_path:%s\nnew_debuginfo_path:%s", + old_debuginfo_path,new_debuginfo_path) + + ret = subprocess.run("abidiff {} {} --d1 {} --d2 {} " + "--harmless > {}".format( + old_so_file, + new_so_file, + old_debuginfo_path, + new_debuginfo_path, + abidiff_file), + shell=True) + else: + ret = subprocess.run("abidiff {} {} --harmless > {}".format( + old_so_file, new_so_file, + abidiff_file), shell=True) + else: + if old_debuginfo_path and new_debuginfo_path: + logging.debug("old_debuginfo_path:%s\nnew_debuginfo_path:%s", + old_debuginfo_path,new_debuginfo_path) + + ret = subprocess.run("abidiff {} {} --d1 {} --d2 {} > {} " + "--changed-fns --deleted-fns --added-fns".format( + old_so_file, new_so_file, + old_debuginfo_path, new_debuginfo_path, + abidiff_file), shell=True) + else: + ret = subprocess.run("abidiff {} {} > {} --changed-fns" + " --deleted-fns --added-fns".format( + old_so_file, new_so_file, + abidiff_file), shell=True) + + all_abidiff_files.append(abidiff_file) + logging.info("result write in: {}".format(abidiff_file)) + return_code |= ret.returncode + merged_file = merge_all_abidiff_files(all_abidiff_files, work_path, base_name) + logging.info("all results writed in: {}".format(merged_file)) + return return_code + + +def check_command(config): + """ + Check the command arguments + """ + if config.old_rpm or config.new_rpm or config.old_debuginfo_rpm or config.new_debuginfo_rpm: + if config.old_so or config.new_so or config.old_debuginfo_path or config.new_debuginfo_path: + logging.error("-rpm and -so cannot required at the same time") + sys.exit(0) + + if config.old_rpm or config.new_rpm: + if not config.old_rpm: + logging.error("-rpm1/--old_rpm argument is required") + sys.exit(0) + if not config.new_rpm: + logging.error("-rpm2/--new_rpm argument is required") + sys.exit(0) + if config.old_so or config.new_so: + if not config.old_so: + logging.error("-so1/--old_so argument is required") + sys.exit(0) + if not config.new_so: + logging.error("-so2/--new_so argument is required") + sys.exit(0) + if not os.path.isfile(config.old_so) or ".so" not in config.old_so: + logging.error("-so1 not exists or not a .so file") + sys.exit(0) + if not os.path.isfile(config.new_so) or ".so" not in config.new_so: + logging.error("-so2 not exists or not a .so file") + sys.exit(0) + + if config.old_debuginfo_path and not os.path.exists(config.old_debuginfo_path): + logging.error("-d_path1 the path not exists") + sys.exit(0) + if config.new_debuginfo_path and not os.path.exists(config.new_debuginfo_path): + logging.error("-d_path2 the path not exists") + sys.exit(0) + + if config.old_rpm and config.old_so: + logging.error("-rpm1/--old_rpm and -so1/--old_so cannot required at the same time") + sys.exit(0) + + if not config.old_rpm and not config.old_so: + logging.error("-rpm1/--old_rpm or -so1/--old_so are required") + sys.exit(0) + + +def check_result(returncode): + """ + Check the result of abidiff + """ + ABIDIFF_ERROR_BIT = 1 + if returncode == 0: + logging.info("No abidiff found") + elif returncode & ABIDIFF_ERROR_BIT: + logging.info("An unexpected error happened") + else: + logging.info("Found abidiffs") + + +def process_with_rpm(config, work_path): + """ + Process the file with type of rpm. + """ old_rpm2cpio_path = get_rpm2cpio_path(work_path, "old_abi") new_rpm2cpio_path = get_rpm2cpio_path(work_path, "new_abi") logging.debug("old_rpm2cpio_path:%s\nnew_rpm2cpio_path:%s", @@ -173,79 +341,64 @@ def main(): new_rpm = get_rpm_path(config.new_rpm, new_rpm2cpio_path) new_debuginfo_rpm = get_rpm_path(config.new_debuginfo_rpm, new_rpm2cpio_path) + logging.debug("old_rpm:%s\nold_debuginfo_rpm:%s\n" - "new_rpm:%s\nnew_debuginfo_rpm:%s", - old_rpm, - old_debuginfo_rpm, - new_rpm, - new_debuginfo_rpm) + "new_rpm:%s\nnew_debuginfo_rpm:%s", + old_rpm,old_debuginfo_rpm, + new_rpm,new_debuginfo_rpm) - os.chdir(old_rpm2cpio_path) - logging.debug("\n----old version working in path:%s----", os.getcwd()) - logging.debug("rpm2cpio %s", old_rpm) - subprocess.run("rpm2cpio {} | cpio -id".format(old_rpm), - shell=True) - - logging.debug("rpm2cpio %s", old_debuginfo_rpm) - subprocess.run("rpm2cpio {} | cpio -id".format(old_debuginfo_rpm), - shell=True) - - os.chdir(new_rpm2cpio_path) - logging.debug("\n----new version working in path:%s----", os.getcwd()) - logging.debug("rpm2cpio %s", new_rpm) - subprocess.run("rpm2cpio {} | cpio -id".format(new_rpm), - shell=True) - - logging.debug("rpm2cpio %s", new_debuginfo_rpm) - subprocess.run("rpm2cpio {} | cpio -id".format(new_debuginfo_rpm), - shell=True) + do_rpm2cpio(old_rpm2cpio_path, old_rpm) + do_rpm2cpio(old_rpm2cpio_path, old_debuginfo_rpm) + do_rpm2cpio(new_rpm2cpio_path, new_rpm) + do_rpm2cpio(new_rpm2cpio_path, new_debuginfo_rpm) os.chdir(work_path) logging.debug("\n----begin abidiff working in path:%s----", os.getcwd()) + + old_so_path = os.path.join(old_rpm2cpio_path, "usr/lib64") + new_so_path = os.path.join(new_rpm2cpio_path, "usr/lib64") + find_all_so_file(old_so_path, new_so_path) - old_so_file = find_so_file(os.path.join(old_rpm2cpio_path, "usr/lib64"), - os.path.basename(old_rpm)) - new_so_file = find_so_file(os.path.join(new_rpm2cpio_path, "usr/lib64"), - os.path.basename(new_rpm)) - old_debuginfo_path = os.path.join(old_rpm2cpio_path, "usr/lib/debug") new_debuginfo_path = os.path.join(new_rpm2cpio_path, "usr/lib/debug") - logging.debug("old_so_file:%s\nnew_so_file:%s\n" - "old_debuginfo_path:%s\nnew_debuginfo_path:%s", - old_so_file, - new_so_file, - old_debuginfo_path, - new_debuginfo_path) - - if not os.path.isfile(old_so_file) or not os.path.isfile(new_so_file): - logging.info("There has no so file") - sys.exit(0) - - abidiff_file = os.path.join(work_path, "{}_abidiff.out".format(os.path.basename(new_rpm))) - if config.show_all_info: - completed_process = subprocess.run("abidiff {} {} --d1 {} --d2 {} --harmless > {}".format( - old_so_file, - new_so_file, - old_debuginfo_path, - new_debuginfo_path, - abidiff_file), - shell=True) - else: - completed_process = subprocess.run("abidiff {} {} --d1 {} --d2 {} > {}".format( - old_so_file, - new_so_file, - old_debuginfo_path, - new_debuginfo_path, - abidiff_file), - shell=True) - ABIDIFF_ERROR_BIT = 1 - if completed_process.returncode == 0: - logging.info("No abidiff found") - elif completed_process.returncode & ABIDIFF_ERROR_BIT: - logging.info("An unexpected error happened") + rpm_base_name = os.path.basename(new_rpm).split('.')[0] + returncode = do_abidiff(config, work_path, rpm_base_name, + old_debuginfo_path, new_debuginfo_path) + check_result(returncode) + + +def process_with_so(config, work_path): + """ + Process the file with type of .so. + """ + old_so_path = os.path.abspath(config.old_so) + new_so_path = os.path.abspath(config.new_so) + all_so_pair[old_so_path] = new_so_path + os.chdir(work_path) + logging.debug("\n----begin abidiff with .so working in path:%s----", os.getcwd()) + + so_base_name = os.path.basename(old_so_path).split('.')[0] + if config.old_debuginfo_path: + old_debuginfo_path = os.path.abspath(config.old_debuginfo_path) + new_debuginfo_path = os.path.abspath(config.new_debuginfo_path) + returncode = do_abidiff(config, work_path, so_base_name, + old_debuginfo_path, new_debuginfo_path) else: - logging.info("Found abidiffs, results at: {}".format(abidiff_file)) + returncode = do_abidiff(config, work_path, so_base_name, None, None) + + check_result(returncode) + + +def main(): + """Entry point for check_abi""" + config = parse_command_line() + check_command(config) + work_path = get_work_path(config) + if config.old_rpm: + process_with_rpm(config, work_path) + if config.old_so: + process_with_so(config, work_path) sys.exit(0) -- Gitee From b4d7113659223a9abb3395c40344083601c40ae2 Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Fri, 24 Jul 2020 17:01:55 +0800 Subject: [PATCH 3/7] update advisors/check_abi.py. --- advisors/check_abi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index 6421bcba..a694337e 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -63,7 +63,7 @@ import os import logging #import pycurl import io -logging.basicConfig(format='%(message)s', level=logging.DEBUG) +logging.basicConfig(format='%(message)s', level=logging.INFO) all_so_pair = {} -- Gitee From 7586c77af91eceea9e35d5d82d3216f6ddb57d6a Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Mon, 27 Jul 2020 17:08:55 +0800 Subject: [PATCH 4/7] update advisors/check_abi.py. --- advisors/check_abi.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index a694337e..dfd7f042 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -23,32 +23,33 @@ (3) Command parameters Required parameters: - -rpm1 Specify the old version rpm path or url - (e.g. /home/test-1.0.rpm or https://example.com/test-1.0.rpm) + -rpm1 Specify the old version rpm path or url + (e.g. /home/test-1.0.rpm or https://example.com/test-1.0.rpm) - -rpm2 Specify the new version rpm path or url - (e.g. /home/test-2.0.rpm or https://example.com/test-2.0.rpm) + -rpm2 Specify the new version rpm path or url + (e.g. /home/test-2.0.rpm or https://example.com/test-2.0.rpm) - Or: - -so1 Specify the old version .so file - (e.g /home/test-1.0.so) + Or: + -so1 Specify the old version .so file + (e.g /home/test-1.0.so) - -so2 Specify the old version .so file - (e.g /home/test-2.0.so) + -so2 Specify the old version .so file + (e.g /home/test-2.0.so) Optional parameters: + + -d_rpm1 Specify the old version debuginfo_rpm path or url + (e.g. /home/test-debuginfo-1.0.rpm or https://example.com/test-debuginfo-1.0.rpm) - -d_rpm1 Specify the old version debuginfo_rpm path or url - (e.g. /home/test-debuginfo-1.0.rpm or https://example.com/test-debuginfo-1.0.rpm) - - -d_rpm2 Specify the new version debuginfo_rpm path or url - (e.g. /home/test-debuginfo-2.0.rpm or https://example.com/test-debuginfo-2.0.rpm) + -d_rpm2 Specify the new version debuginfo_rpm path or url + (e.g. /home/test-debuginfo-2.0.rpm or https://example.com/test-debuginfo-2.0.rpm) - -d_path1 Specify the old version debuginfo file path - (e.g. /home/test-1.0/lib/debug/) + Or: + -d_path1 Specify the old version debuginfo file path + (e.g. /home/test-1.0/lib/debug/) - -d_path2 Specify the new version debuginfo file path - (e.g. /home/test-2.0/lib/debug/) + -d_path2 Specify the new version debuginfo file path + (e.g. /home/test-2.0/lib/debug/) -d Specify the work path of the rpm2cpio default: /var/tmp/ -- Gitee From a4f272f908881aa960c9e043d6ecf3fc0b05dd4f Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Mon, 27 Jul 2020 17:13:12 +0800 Subject: [PATCH 5/7] update advisors/check_abi.py. --- advisors/check_abi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index dfd7f042..614b8580 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -16,7 +16,8 @@ """ (1) This script is used to check the interface changes between the old and new versions of the C/C++ language pack. - The final difference information result is saved in the xxx.abidiff.out file in the working directory + The final difference information result is saved in the xxx_all_abidiff.out file in the working directory + default path: /var/tmp/xxx_all_abidiff.out (2) To use this script, you must first install the Libabigail service, you can download and install libabigail-xxx.rpm in the community. -- Gitee From ff8fbd2c7856a9c606ced3f66058a4600def7aa6 Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Tue, 28 Jul 2020 10:06:07 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E8=A7=84=E8=8C=83=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- advisors/check_abi.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index 614b8580..597d2989 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -125,8 +125,8 @@ def find_all_so_file(path1, path2): """ old_so = find_so_file(path1) new_so = find_so_file(path2) - logging.debug("old_so:%s\n",old_so) - logging.debug("new_so:%s\n",new_so) + logging.debug("old_so:%s\n", old_so) + logging.debug("new_so:%s\n", new_so) if old_so and new_so: for so_file1 in old_so: for so_file2 in new_so: @@ -223,7 +223,7 @@ def do_abidiff(config, work_path, base_name, old_debuginfo_path, new_debuginfo_p all_abidiff_files = [] for old_so_file in all_so_pair: new_so_file = all_so_pair[old_so_file] - logging.debug( "begin abidiff between %s and %s", old_so_file, new_so_file) + logging.debug("begin abidiff between %s and %s", old_so_file, new_so_file) abidiff_file = os.path.join(work_path, "{}_{}_abidiff.out".format( @@ -232,7 +232,7 @@ def do_abidiff(config, work_path, base_name, old_debuginfo_path, new_debuginfo_p if config.show_all_info: if old_debuginfo_path and new_debuginfo_path: logging.debug("old_debuginfo_path:%s\nnew_debuginfo_path:%s", - old_debuginfo_path,new_debuginfo_path) + old_debuginfo_path, new_debuginfo_path) ret = subprocess.run("abidiff {} {} --d1 {} --d2 {} " "--harmless > {}".format( @@ -249,7 +249,7 @@ def do_abidiff(config, work_path, base_name, old_debuginfo_path, new_debuginfo_p else: if old_debuginfo_path and new_debuginfo_path: logging.debug("old_debuginfo_path:%s\nnew_debuginfo_path:%s", - old_debuginfo_path,new_debuginfo_path) + old_debuginfo_path, new_debuginfo_path) ret = subprocess.run("abidiff {} {} --d1 {} --d2 {} > {} " "--changed-fns --deleted-fns --added-fns".format( @@ -263,10 +263,10 @@ def do_abidiff(config, work_path, base_name, old_debuginfo_path, new_debuginfo_p abidiff_file), shell=True) all_abidiff_files.append(abidiff_file) - logging.info("result write in: {}".format(abidiff_file)) + logging.info("result write in: %s", abidiff_file) return_code |= ret.returncode merged_file = merge_all_abidiff_files(all_abidiff_files, work_path, base_name) - logging.info("all results writed in: {}".format(merged_file)) + logging.info("all results writed in: %s", merged_file) return return_code @@ -346,8 +346,8 @@ def process_with_rpm(config, work_path): logging.debug("old_rpm:%s\nold_debuginfo_rpm:%s\n" "new_rpm:%s\nnew_debuginfo_rpm:%s", - old_rpm,old_debuginfo_rpm, - new_rpm,new_debuginfo_rpm) + old_rpm, old_debuginfo_rpm, + new_rpm, new_debuginfo_rpm) do_rpm2cpio(old_rpm2cpio_path, old_rpm) do_rpm2cpio(old_rpm2cpio_path, old_debuginfo_rpm) -- Gitee From 9b44d3528b0a55ad0df4ca0e95a6efe7310904c8 Mon Sep 17 00:00:00 2001 From: wangchuangGG Date: Wed, 29 Jul 2020 09:37:09 +0800 Subject: [PATCH 7/7] update advisors/check_abi.py. --- advisors/check_abi.py | 82 ++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 47 deletions(-) diff --git a/advisors/check_abi.py b/advisors/check_abi.py index 597d2989..2ca05a32 100755 --- a/advisors/check_abi.py +++ b/advisors/check_abi.py @@ -72,35 +72,43 @@ all_so_pair = {} def parse_command_line(): """Parse the command line arguments.""" parser = argparse.ArgumentParser() - parser.add_argument("-rpm1", "--old_rpm", default="", - nargs="?", - help = "the old version rpm path or url") - parser.add_argument("-rpm2", "--new_rpm", default="", - nargs="?", - help = "the new version rpm path or url") - parser.add_argument("-d_rpm1", "--old_debuginfo_rpm", - default="", nargs="?", - help = "the old version debuginfo_rpm path or url") - parser.add_argument("-d_rpm2", "--new_debuginfo_rpm", - default="", nargs="?", - help = "the new version debuginfo_rpm path or url") - parser.add_argument("-so1", "--old_so", default="", - nargs="?", - help = "the old version .so file") - parser.add_argument("-so2", "--new_so", default="", - nargs="?", - help = "the new version .so file") - parser.add_argument("-d_path1", "--old_debuginfo_path", default="", - nargs="?", - help = "the old version debuginfo file path") - parser.add_argument("-d_path2", "--new_debuginfo_path", default="", - nargs="?", - help = "the new version debuginfo file path") + + ex_group1 = parser.add_mutually_exclusive_group(required=True) + ex_group1.add_argument("-rpm1", "--old_rpm", default="", + help = "the old version rpm path or url") + ex_group1.add_argument("-so1", "--old_so", default="", + help = "the old version .so file") + + ex_group2 = parser.add_mutually_exclusive_group(required=True) + ex_group2.add_argument("-rpm2", "--new_rpm", default="", + help = "the new version rpm path or url") + ex_group2.add_argument("-so2", "--new_so", default="", + help = "the new version .so file") + + ex_group3 = parser.add_mutually_exclusive_group() + ex_group3.add_argument("-d_rpm1", "--old_debuginfo_rpm", + default="", nargs="?", + help = "the old version debuginfo_rpm path or url") + ex_group3.add_argument("-d_path1", "--old_debuginfo_path", + default="", nargs="?", + help = "the old version debuginfo file path") + + ex_group4 = parser.add_mutually_exclusive_group() + ex_group4.add_argument("-d_rpm2", "--new_debuginfo_rpm", + default="", nargs="?", + help = "the new version debuginfo_rpm path or url") + ex_group4.add_argument("-d_path2", "--new_debuginfo_path", default="", + nargs="?", + help = "the new version debuginfo file path") + parser.add_argument("-d", "--work_path", default="", nargs="?", help="The work path to put rpm2cpio files and results" " (e.g. /home/tmp_abidiff default: /var/tmp/)") parser.add_argument("-all", "--show_all_info", action="store_true", default=False, help="show all infos includ changes in member name") + parser.add_argument("-rpms", "--rpms_path", default="", nargs="?", + help="Find the rpm packages in this path that calls this change interfaces" + " (e.g. /home/rpms)") return parser.parse_args() @@ -279,20 +287,7 @@ def check_command(config): logging.error("-rpm and -so cannot required at the same time") sys.exit(0) - if config.old_rpm or config.new_rpm: - if not config.old_rpm: - logging.error("-rpm1/--old_rpm argument is required") - sys.exit(0) - if not config.new_rpm: - logging.error("-rpm2/--new_rpm argument is required") - sys.exit(0) if config.old_so or config.new_so: - if not config.old_so: - logging.error("-so1/--old_so argument is required") - sys.exit(0) - if not config.new_so: - logging.error("-so2/--new_so argument is required") - sys.exit(0) if not os.path.isfile(config.old_so) or ".so" not in config.old_so: logging.error("-so1 not exists or not a .so file") sys.exit(0) @@ -302,18 +297,11 @@ def check_command(config): if config.old_debuginfo_path and not os.path.exists(config.old_debuginfo_path): logging.error("-d_path1 the path not exists") - sys.exit(0) + sys.exit(0) + if config.new_debuginfo_path and not os.path.exists(config.new_debuginfo_path): logging.error("-d_path2 the path not exists") - sys.exit(0) - - if config.old_rpm and config.old_so: - logging.error("-rpm1/--old_rpm and -so1/--old_so cannot required at the same time") - sys.exit(0) - - if not config.old_rpm and not config.old_so: - logging.error("-rpm1/--old_rpm or -so1/--old_so are required") - sys.exit(0) + sys.exit(0) def check_result(returncode): -- Gitee