aboutsummaryrefslogtreecommitdiff
path: root/debug_info_test
diff options
context:
space:
mode:
authorTing-Yuan Huang <laszio@chromium.org>2018-02-28 14:35:48 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-03-02 20:47:16 -0800
commit340542b21c30cd62a68d19f086edef36d849971b (patch)
treecae122ce8c6126141c298516d0575a067a9efe7d /debug_info_test
parentedcf3d33a602438104cafd76f534fa8007e9de7b (diff)
downloadtoolchain-utils-340542b21c30cd62a68d19f086edef36d849971b.tar.gz
debug_info_test: Run tests based on debug info
debug_info_test calls tests on the given ELF files. When a directory is supplied, all ELFs will be searched and tested recursively. BUG=chromium:817648 TEST=debug_info_test /build/kip/usr/lib/debug Change-Id: Ibcb1ac2de19df9227eb6e242d611ec841d4b589f Reviewed-on: https://chromium-review.googlesource.com/942465 Commit-Ready: Ting-Yuan Huang <laszio@chromium.org> Tested-by: Ting-Yuan Huang <laszio@chromium.org> Reviewed-by: Ting-Yuan Huang <laszio@chromium.org> Reviewed-by: Yunlian Jiang <yunlian@chromium.org>
Diffstat (limited to 'debug_info_test')
-rw-r--r--debug_info_test/check_clang.py26
-rw-r--r--debug_info_test/check_cus.py67
-rw-r--r--debug_info_test/clang_comp_path.whitelist4
-rw-r--r--debug_info_test/clang_dso_path.whitelist12
-rwxr-xr-xdebug_info_test/debug_info_test.py53
-rw-r--r--debug_info_test/whitelist.py57
6 files changed, 219 insertions, 0 deletions
diff --git a/debug_info_test/check_clang.py b/debug_info_test/check_clang.py
new file mode 100644
index 00000000..a6d056ed
--- /dev/null
+++ b/debug_info_test/check_clang.py
@@ -0,0 +1,26 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from whitelist import is_whitelisted
+
+def is_built_with_clang(dso_path, producer, comp_path):
+ """Check whether the compile unit is built by clang.
+
+ Args:
+ dso_path: path to the elf/dso
+ producer: DW_AT_producer contains the compiler command line.
+ comp_path: DW_AT_comp_dir + DW_AT_name
+
+ Returns:
+ False if compiled by gcc otherwise True
+ """
+ if is_whitelisted('clang_comp_path', comp_path):
+ return True
+
+ if is_whitelisted('clang_dso_path', dso_path):
+ return True
+
+ if 'clang version' not in producer:
+ return False
+ return True
diff --git a/debug_info_test/check_cus.py b/debug_info_test/check_cus.py
new file mode 100644
index 00000000..88fcf275
--- /dev/null
+++ b/debug_info_test/check_cus.py
@@ -0,0 +1,67 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+
+import check_clang
+
+cu_checks = [check_clang.is_built_with_clang]
+
+def check_compile_unit(dso_path, producer, comp_path):
+ """check all compiler flags used to build the compile unit.
+
+ Args:
+ dso_path: path to the elf/dso
+ producer: DW_AT_producer contains the compiler command line.
+ comp_path: DW_AT_comp_dir + DW_AT_name
+
+ Returns:
+ A set of failed tests.
+ """
+ failed = set()
+ for c in cu_checks:
+ if not c(dso_path, producer, comp_path):
+ failed.add(c.__module__)
+
+ return failed
+
+def check_compile_units(dso_path):
+ """check all compile units in the given dso.
+
+ Args:
+ dso_path: path to the dso
+ Return:
+ True if everything looks fine otherwise False.
+ """
+
+ failed = set()
+ producer = ''
+ comp_path = ''
+
+ readelf = subprocess.Popen(['readelf', '--debug-dump=info',
+ '--dwarf-depth=1', dso_path],
+ stdout=subprocess.PIPE,
+ stderr=open(os.devnull, 'w'))
+ for l in readelf.stdout:
+ if 'DW_TAG_compile_unit' in l:
+ if producer:
+ failed = failed.union(check_compile_unit(dso_path, producer,
+ comp_path))
+ producer = ''
+ comp_path = ''
+ elif 'DW_AT_producer' in l:
+ producer = l
+ elif 'DW_AT_name' in l:
+ comp_path = os.path.join(comp_path, l.split(':')[-1].strip())
+ elif 'DW_AT_comp_dir' in l:
+ comp_path = os.path.join(l.split(':')[-1].strip(), comp_path)
+ if producer:
+ failed = failed.union(check_compile_unit(dso_path, producer, comp_path))
+
+ if failed:
+ print('%s failed check: %s' % (dso_path, ' '.join(failed)))
+ return False
+
+ return True
diff --git a/debug_info_test/clang_comp_path.whitelist b/debug_info_test/clang_comp_path.whitelist
new file mode 100644
index 00000000..45df0547
--- /dev/null
+++ b/debug_info_test/clang_comp_path.whitelist
@@ -0,0 +1,4 @@
+# These are generally objects linked from system libraries such as glibc
+# and libgcc.
+.*/glibc-.*/
+.*/libgcc/.*
diff --git a/debug_info_test/clang_dso_path.whitelist b/debug_info_test/clang_dso_path.whitelist
new file mode 100644
index 00000000..74f520ea
--- /dev/null
+++ b/debug_info_test/clang_dso_path.whitelist
@@ -0,0 +1,12 @@
+# modules we don't care:
+.*/binutils/.*
+.*/binutils-bin/.*
+.*/libpepflashplayer\.so\.debug
+.*/opt/punybench/bin/.*
+.*/telemetry_dep/.*
+.*/unixbench/.*
+.*/opt/google/containers/android/.*
+.*/libmali\.so.*\.debug
+# todos:
+.*/flashrom_s.debug
+.*/ec_ctl.debug
diff --git a/debug_info_test/debug_info_test.py b/debug_info_test/debug_info_test.py
new file mode 100755
index 00000000..cf3148db
--- /dev/null
+++ b/debug_info_test/debug_info_test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+import check_cus
+
+elf_checks = [check_cus.check_compile_units]
+
+def scanelf(root):
+ """find ELFs in root
+
+ Args:
+ root: root dir to start with the search.
+ Returns:
+ Filenames of ELFs in root.
+ """
+ p = subprocess.Popen(['scanelf', '-y', '-B', '-F', '%F', '-R', root],
+ stdout=subprocess.PIPE)
+ return [l.strip() for l in p.stdout]
+
+def Main(argv):
+ if len(argv) < 2:
+ print('usage: %s [file|dir]')
+ return 1
+
+ files = []
+ cand = argv[1]
+ if os.path.isfile(cand):
+ files = [cand]
+ elif os.path.isdir(cand):
+ files = scanelf(cand)
+ else:
+ print('usage: %s [file|dir]')
+ return 1
+
+ failed = False
+ for f in files:
+ for c in elf_checks:
+ if not c(f):
+ failed = True
+
+ if failed:
+ return 1
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/debug_info_test/whitelist.py b/debug_info_test/whitelist.py
new file mode 100644
index 00000000..99a457c0
--- /dev/null
+++ b/debug_info_test/whitelist.py
@@ -0,0 +1,57 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import glob
+import re
+
+# Matching a string of length m in an NFA of size n is O(mn^2), but the
+# performance also depends largely on the implementation. It appears to be fast
+# enough according to the tests.
+#
+# The performance bottleneck of this script is readelf. Unless this becomes
+# slower than readelf, don't waste time here.
+def is_whitelisted(list_name, pattern):
+ """chech whether the given pattern is specified in the whitelist.
+
+ Args:
+ list_name: name of the whitelist
+ pattern: the target string
+ Returns:
+ True if matched otherwise False
+ """
+ return pattern and whitelists[list_name].match(pattern)
+
+def prepare_whitelist(patterns):
+ """Join and compile the re patterns.
+
+ Args:
+ patterns: regex patterns.
+ Return:
+ A compiled re object
+ """
+ return re.compile('|'.join(patterns))
+
+def load_whitelists(dirname):
+ """Load whitelists under dirname.
+
+ A whitelist ends with .whitelist.
+
+ Args:
+ dirname: path to the dir.
+ Returns:
+ A dictionary of 'filename' -> whitelist matcher.
+ """
+ wlist = {}
+ for fn in glob.glob(os.path.join(dirname, '*.whitelist')):
+ key = os.path.splitext(os.path.basename(fn))[0]
+ with open(fn, 'r') as f:
+ patterns = f.read().splitlines()
+ patterns = [l for l in patterns if l[0] != '#']
+ patterns = [l for l in patterns if l != '']
+ wlist[key] = prepare_whitelist(patterns)
+ return wlist
+
+
+whitelists = load_whitelists(os.path.dirname(__file__))