diff options
Diffstat (limited to 'utils/check_cfc')
| -rwxr-xr-x | utils/check_cfc/check_cfc.py | 32 | ||||
| -rwxr-xr-x | utils/check_cfc/obj_diff.py | 26 | ||||
| -rwxr-xr-x | utils/check_cfc/test_check_cfc.py | 10 | 
3 files changed, 59 insertions, 9 deletions
| diff --git a/utils/check_cfc/check_cfc.py b/utils/check_cfc/check_cfc.py index 3def36eb62f4d..c6ab9abf23528 100755 --- a/utils/check_cfc/check_cfc.py +++ b/utils/check_cfc/check_cfc.py @@ -213,16 +213,18 @@ def set_input_file(args, input_file):  def is_normal_compile(args):      """Check if this is a normal compile which will output an object file rather -    than a preprocess or link.""" +    than a preprocess or link. args is a list of command line arguments."""      compile_step = '-c' in args      # Bitcode cannot be disassembled in the same way      bitcode = '-flto' in args or '-emit-llvm' in args      # Version and help are queries of the compiler and override -c if specified      query = '--version' in args or '--help' in args +    # Options to output dependency files for make +    dependency = '-M' in args or '-MM' in args      # Check if the input is recognised as a source file (this may be too      # strong a restriction)      input_is_valid = bool(get_input_file(args)) -    return compile_step and not bitcode and not query and input_is_valid +    return compile_step and not bitcode and not query and not dependency and input_is_valid  def run_step(command, my_env, error_on_failure):      """Runs a step of the compilation. Reports failure as exception.""" @@ -282,12 +284,24 @@ class dash_s_no_change(WrapperCheck):          run_step(alternate_command, my_env,                   "Error compiling with -via-file-asm") -        # Compare disassembly (returns first diff if differs) -        difference = obj_diff.compare_object_files(self._output_file_a, -                                                   output_file_b) -        if difference: -            raise WrapperCheckException( -                "Code difference detected with -S\n{}".format(difference)) +        # Compare if object files are exactly the same +        exactly_equal = obj_diff.compare_exact(self._output_file_a, output_file_b) +        if not exactly_equal: +            # Compare disassembly (returns first diff if differs) +            difference = obj_diff.compare_object_files(self._output_file_a, +                                                       output_file_b) +            if difference: +                raise WrapperCheckException( +                    "Code difference detected with -S\n{}".format(difference)) + +            # Code is identical, compare debug info +            dbgdifference = obj_diff.compare_debug_info(self._output_file_a, +                                                        output_file_b) +            if dbgdifference: +                raise WrapperCheckException( +                    "Debug info difference detected with -S\n{}".format(dbgdifference)) + +            raise WrapperCheckException("Object files not identical with -S\n")          # Clean up temp file if comparison okay          os.remove(output_file_b) @@ -367,7 +381,7 @@ if __name__ == '__main__':                  checker.perform_check(arguments_a, my_env)              except WrapperCheckException as e:                  # Check failure -                print(e.msg, file=sys.stderr) +                print("{} {}".format(get_input_file(arguments_a), e.msg), file=sys.stderr)                  # Remove file to comply with build system expectations (no                  # output file if failed) diff --git a/utils/check_cfc/obj_diff.py b/utils/check_cfc/obj_diff.py index 6f932b3172daa..cc4c2a97d5e5b 100755 --- a/utils/check_cfc/obj_diff.py +++ b/utils/check_cfc/obj_diff.py @@ -4,6 +4,7 @@ from __future__ import print_function  import argparse  import difflib +import filecmp  import os  import subprocess  import sys @@ -26,6 +27,15 @@ def disassemble(objfile):          sys.exit(1)      return filter(keep_line, out.split(os.linesep)) +def dump_debug(objfile): +    """Dump all of the debug info from a file.""" +    p = subprocess.Popen([disassembler, '-WliaprmfsoRt', objfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) +    (out, err) = p.communicate() +    if p.returncode or err: +        print("Dump debug failed: {}".format(objfile)) +        sys.exit(1) +    return filter(keep_line, out.split(os.linesep)) +  def first_diff(a, b, fromfile, tofile):      """Returns the first few lines of a difference, if there is one.  Python      diff can be very slow with large objects and the most interesting changes @@ -63,6 +73,22 @@ def compare_object_files(objfilea, objfileb):      disb = disassemble(objfileb)      return first_diff(disa, disb, objfilea, objfileb) +def compare_debug_info(objfilea, objfileb): +    """Compare debug info of two different files. +       Allowing unavoidable differences, such as filenames. +       Return the first difference if the debug info differs, or None. +       If there are differences in the code, there will almost certainly be differences in the debug info too. +    """ +    dbga = dump_debug(objfilea) +    dbgb = dump_debug(objfileb) +    return first_diff(dbga, dbgb, objfilea, objfileb) + +def compare_exact(objfilea, objfileb): +    """Byte for byte comparison between object files. +       Returns True if equal, False otherwise. +    """ +    return filecmp.cmp(objfilea, objfileb) +  if __name__ == '__main__':      parser = argparse.ArgumentParser()      parser.add_argument('objfilea', nargs=1) diff --git a/utils/check_cfc/test_check_cfc.py b/utils/check_cfc/test_check_cfc.py index 0eee5b83842b3..e304ff59277d0 100755 --- a/utils/check_cfc/test_check_cfc.py +++ b/utils/check_cfc/test_check_cfc.py @@ -103,6 +103,16 @@ class TestCheckCFC(unittest.TestCase):              check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '--version']))          self.assertFalse(              check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '--help'])) +        # Outputting dependency files is not a normal compile +        self.assertFalse( +            check_cfc.is_normal_compile(['clang', '-c', '-M', 'test.cpp'])) +        self.assertFalse( +            check_cfc.is_normal_compile(['clang', '-c', '-MM', 'test.cpp'])) +        # Creating a dependency file as a side effect still outputs an object file +        self.assertTrue( +            check_cfc.is_normal_compile(['clang', '-c', '-MD', 'test.cpp'])) +        self.assertTrue( +            check_cfc.is_normal_compile(['clang', '-c', '-MMD', 'test.cpp']))      def test_replace_output_file(self):          self.assertEqual(check_cfc.replace_output_file( | 
