aboutsummaryrefslogtreecommitdiff
path: root/debug_info_test
diff options
context:
space:
mode:
Diffstat (limited to 'debug_info_test')
-rw-r--r--debug_info_test/allowlist.py71
-rw-r--r--debug_info_test/check_cus.py107
-rw-r--r--debug_info_test/check_exist.py140
-rw-r--r--debug_info_test/check_icf.py81
-rw-r--r--debug_info_test/check_ngcc.py29
-rwxr-xr-xdebug_info_test/debug_info_test.py87
6 files changed, 260 insertions, 255 deletions
diff --git a/debug_info_test/allowlist.py b/debug_info_test/allowlist.py
index 9cf42af0..70bb776a 100644
--- a/debug_info_test/allowlist.py
+++ b/debug_info_test/allowlist.py
@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Allowlist functions."""
-from __future__ import print_function
import glob
import os
@@ -19,50 +18,50 @@ import re
# The performance bottleneck of this script is readelf. Unless this becomes
# slower than readelf, don't waste time here.
def is_allowlisted(list_name, pattern):
- """Check whether the given pattern is specified in the allowlist.
+ """Check whether the given pattern is specified in the allowlist.
- Args:
- list_name: name of the allowlist.
- pattern: the target string.
+ Args:
+ list_name: name of the allowlist.
+ pattern: the target string.
- Returns:
- True if matched otherwise False.
- """
- return pattern and allowlists[list_name].match(pattern)
+ Returns:
+ True if matched otherwise False.
+ """
+ return pattern and allowlists[list_name].match(pattern)
def prepare_allowlist(patterns):
- """Join and compile the re patterns.
+ """Join and compile the re patterns.
- Args:
- patterns: regex patterns.
+ Args:
+ patterns: regex patterns.
- Returns:
- A compiled re object.
- """
- return re.compile('|'.join(patterns))
+ Returns:
+ A compiled re object.
+ """
+ return re.compile("|".join(patterns))
def load_allowlists(dirname):
- """Load allowlists under dirname.
-
- An allowlist ends with .allowlist.
-
- Args:
- dirname: path to the dir.
-
- Returns:
- A dictionary of 'filename' -> allowlist matcher.
- """
- wlist = {}
- for fn in glob.glob(os.path.join(dirname, '*.allowlist')):
- key = os.path.splitext(os.path.basename(fn))[0]
- with open(fn, 'r', encoding='utf-8') as f:
- patterns = f.read().splitlines()
- patterns = [l for l in patterns if l != '']
- patterns = [l for l in patterns if l[0] != '#']
- wlist[key] = prepare_allowlist(patterns)
- return wlist
+ """Load allowlists under dirname.
+
+ An allowlist ends with .allowlist.
+
+ Args:
+ dirname: path to the dir.
+
+ Returns:
+ A dictionary of 'filename' -> allowlist matcher.
+ """
+ wlist = {}
+ for fn in glob.glob(os.path.join(dirname, "*.allowlist")):
+ key = os.path.splitext(os.path.basename(fn))[0]
+ with open(fn, "r", encoding="utf-8") as f:
+ patterns = f.read().splitlines()
+ patterns = [l for l in patterns if l != ""]
+ patterns = [l for l in patterns if l[0] != "#"]
+ wlist[key] = prepare_allowlist(patterns)
+ return wlist
allowlists = load_allowlists(os.path.dirname(__file__))
diff --git a/debug_info_test/check_cus.py b/debug_info_test/check_cus.py
index 41123259..dbf22d08 100644
--- a/debug_info_test/check_cus.py
+++ b/debug_info_test/check_cus.py
@@ -1,75 +1,78 @@
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""check compile units."""
-from __future__ import print_function
import os
import subprocess
import check_ngcc
+
cu_checks = [check_ngcc.not_by_gcc]
def check_compile_unit(dso_path, producer, comp_path):
- """check all compiler flags used to build the compile unit.
+ """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.
+ 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__)
+ 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
+ return failed
def check_compile_units(dso_path):
- """check all compile units in the given dso.
-
- Args:
- dso_path: path to the dso.
-
- Returns:
- True if everything looks fine otherwise False.
- """
-
- failed = set()
- producer = ''
- comp_path = ''
-
- readelf = subprocess.Popen(
- ['llvm-dwarfdump', '--recurse-depth=0', dso_path],
- stdout=subprocess.PIPE,
- stderr=open(os.devnull, 'w'),
- encoding='utf-8')
- for l in readelf.stdout:
- if 'DW_TAG_compile_unit' in l:
- if producer:
+ """check all compile units in the given dso.
+
+ Args:
+ dso_path: path to the dso.
+
+ Returns:
+ True if everything looks fine otherwise False.
+ """
+
+ failed = set()
+ producer = ""
+ comp_path = ""
+
+ readelf = subprocess.Popen(
+ ["llvm-dwarfdump", "--recurse-depth=0", dso_path],
+ stdout=subprocess.PIPE,
+ stderr=open(os.devnull, "w"),
+ encoding="utf-8",
+ )
+ 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))
- 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
+
+ if failed:
+ print("%s failed check: %s" % (dso_path, " ".join(failed)))
+ return False
+
+ return True
diff --git a/debug_info_test/check_exist.py b/debug_info_test/check_exist.py
index 898dae45..863c591f 100644
--- a/debug_info_test/check_exist.py
+++ b/debug_info_test/check_exist.py
@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""check whether intended components exists in the given dso."""
-from __future__ import print_function
import os
import subprocess
@@ -14,89 +13,90 @@ from allowlist import is_allowlisted
def check_debug_info(dso_path, readelf_content):
- """Check whether debug info section exists in the elf file.
+ """Check whether debug info section exists in the elf file.
- Args:
- dso_path: path to the dso.
- readelf_content: debug info dumped by command readelf.
+ Args:
+ dso_path: path to the dso.
+ readelf_content: debug info dumped by command readelf.
- Returns:
- True if debug info section exists, otherwise False.
- """
+ Returns:
+ True if debug info section exists, otherwise False.
+ """
- # Return True if it is allowlisted
- if is_allowlisted('exist_debug_info', dso_path):
- return True
+ # Return True if it is allowlisted
+ if is_allowlisted("exist_debug_info", dso_path):
+ return True
- for l in readelf_content:
- if 'debug_info' in l:
- return True
- return False
+ for l in readelf_content:
+ if "debug_info" in l:
+ return True
+ return False
def check_producer(dso_path, readelf_content):
- """Check whether DW_AT_producer exists in each compile unit.
-
- Args:
- dso_path: path to the dso.
- readelf_content: debug info dumped by command readelf.
-
- Returns:
- True if DW_AT_producer exists in each compile unit, otherwise False.
- Notice: If no compile unit in DSO, also return True.
- """
-
- # Return True if it is allowlisted
- if is_allowlisted('exist_producer', dso_path):
- return True
-
- # Indicate if there is a producer under each cu
- cur_producer = False
-
- first_cu = True
- producer_exist = True
-
- for l in readelf_content:
- if 'DW_TAG_compile_unit' in l:
- if not first_cu and not cur_producer:
+ """Check whether DW_AT_producer exists in each compile unit.
+
+ Args:
+ dso_path: path to the dso.
+ readelf_content: debug info dumped by command readelf.
+
+ Returns:
+ True if DW_AT_producer exists in each compile unit, otherwise False.
+ Notice: If no compile unit in DSO, also return True.
+ """
+
+ # Return True if it is allowlisted
+ if is_allowlisted("exist_producer", dso_path):
+ return True
+
+ # Indicate if there is a producer under each cu
+ cur_producer = False
+
+ first_cu = True
+ producer_exist = True
+
+ for l in readelf_content:
+ if "DW_TAG_compile_unit" in l:
+ if not first_cu and not cur_producer:
+ producer_exist = False
+ break
+ first_cu = False
+ cur_producer = False
+ elif "DW_AT_producer" in l:
+ cur_producer = True
+
+ # Check whether last producer of compile unit exists in the elf,
+ # also return True if no cu in the DSO.
+ if not first_cu and not cur_producer:
producer_exist = False
- break
- first_cu = False
- cur_producer = False
- elif 'DW_AT_producer' in l:
- cur_producer = True
- # Check whether last producer of compile unit exists in the elf,
- # also return True if no cu in the DSO.
- if not first_cu and not cur_producer:
- producer_exist = False
-
- return producer_exist
+ return producer_exist
def check_exist_all(dso_path):
- """check whether intended components exists in the given dso.
+ """check whether intended components exists in the given dso.
- Args:
- dso_path: path to the dso.
+ Args:
+ dso_path: path to the dso.
- Returns:
- True if everything looks fine otherwise False.
- """
+ Returns:
+ True if everything looks fine otherwise False.
+ """
- readelf = subprocess.Popen(
- ['llvm-dwarfdump', '--recurse-depth=0', dso_path],
- stdout=subprocess.PIPE,
- stderr=open(os.devnull, 'w'),
- encoding='utf-8')
- readelf_content = list(readelf.stdout)
+ readelf = subprocess.Popen(
+ ["llvm-dwarfdump", "--recurse-depth=0", dso_path],
+ stdout=subprocess.PIPE,
+ stderr=open(os.devnull, "w"),
+ encoding="utf-8",
+ )
+ readelf_content = list(readelf.stdout)
- exist_checks = [check_debug_info, check_producer]
+ exist_checks = [check_debug_info, check_producer]
- for e in exist_checks:
- if not e(dso_path, readelf_content):
- check_failed = e.__module__ + ': ' + e.__name__
- print('%s failed check: %s' % (dso_path, check_failed))
- return False
+ for e in exist_checks:
+ if not e(dso_path, readelf_content):
+ check_failed = e.__module__ + ": " + e.__name__
+ print("%s failed check: %s" % (dso_path, check_failed))
+ return False
- return True
+ return True
diff --git a/debug_info_test/check_icf.py b/debug_info_test/check_icf.py
index a46968e7..a717d81e 100644
--- a/debug_info_test/check_icf.py
+++ b/debug_info_test/check_icf.py
@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""check whether chrome was built with identical code folding."""
-from __future__ import print_function
import os
import re
@@ -13,41 +12,43 @@ import subprocess
def check_identical_code_folding(dso_path):
- """check whether chrome was built with identical code folding.
-
- Args:
- dso_path: path to the dso.
-
- Returns:
- False if the dso is chrome and it was not built with icf,
- True otherwise.
- """
-
- if not dso_path.endswith('/chrome.debug'):
- return True
-
- # Run 'nm' on the chrome binary and read the output.
- nm = subprocess.Popen(['nm', dso_path],
- stdout=subprocess.PIPE,
- stderr=open(os.devnull, 'w'),
- encoding='utf-8')
- nm_output, _ = nm.communicate()
-
- # Search for addresses of text symbols.
- text_addresses = re.findall('^[0-9a-f]+[ ]+[tT] ', nm_output, re.MULTILINE)
-
- # Calculate number of text symbols in chrome binary.
- num_text_addresses = len(text_addresses)
-
- # Calculate number of unique text symbols in chrome binary.
- num_unique_text_addresses = len(set(text_addresses))
-
- # Check that the number of duplicate symbols is at least 10,000.
- # - https://crbug.com/813272#c18
- if num_text_addresses - num_unique_text_addresses >= 10000:
- return True
-
- print('%s was not built with ICF' % dso_path)
- print(' num_text_addresses = %d' % num_text_addresses)
- print(' num_unique_text_addresses = %d' % num_unique_text_addresses)
- return False
+ """check whether chrome was built with identical code folding.
+
+ Args:
+ dso_path: path to the dso.
+
+ Returns:
+ False if the dso is chrome and it was not built with icf,
+ True otherwise.
+ """
+
+ if not dso_path.endswith("/chrome.debug"):
+ return True
+
+ # Run 'nm' on the chrome binary and read the output.
+ nm = subprocess.Popen(
+ ["nm", dso_path],
+ stdout=subprocess.PIPE,
+ stderr=open(os.devnull, "w"),
+ encoding="utf-8",
+ )
+ nm_output, _ = nm.communicate()
+
+ # Search for addresses of text symbols.
+ text_addresses = re.findall("^[0-9a-f]+[ ]+[tT] ", nm_output, re.MULTILINE)
+
+ # Calculate number of text symbols in chrome binary.
+ num_text_addresses = len(text_addresses)
+
+ # Calculate number of unique text symbols in chrome binary.
+ num_unique_text_addresses = len(set(text_addresses))
+
+ # Check that the number of duplicate symbols is at least 10,000.
+ # - https://crbug.com/813272#c18
+ if num_text_addresses - num_unique_text_addresses >= 10000:
+ return True
+
+ print("%s was not built with ICF" % dso_path)
+ print(" num_text_addresses = %d" % num_text_addresses)
+ print(" num_unique_text_addresses = %d" % num_unique_text_addresses)
+ return False
diff --git a/debug_info_test/check_ngcc.py b/debug_info_test/check_ngcc.py
index c86c220a..bbb58741 100644
--- a/debug_info_test/check_ngcc.py
+++ b/debug_info_test/check_ngcc.py
@@ -1,30 +1,29 @@
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Check whether the compile unit is not built by gcc."""
-from __future__ import print_function
from allowlist import is_allowlisted
def not_by_gcc(dso_path, producer, comp_path):
- """Check whether the compile unit is not built by gcc.
+ """Check whether the compile unit is not built by gcc.
- 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.
+ 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_allowlisted('ngcc_comp_path', comp_path):
- return True
+ Returns:
+ False if compiled by gcc otherwise True.
+ """
+ if is_allowlisted("ngcc_comp_path", comp_path):
+ return True
- if is_allowlisted('ngcc_dso_path', dso_path):
- return True
+ if is_allowlisted("ngcc_dso_path", dso_path):
+ return True
- return 'GNU C' not in producer
+ return "GNU C" not in producer
diff --git a/debug_info_test/debug_info_test.py b/debug_info_test/debug_info_test.py
index ae7e9f48..c324bf4c 100755
--- a/debug_info_test/debug_info_test.py
+++ b/debug_info_test/debug_info_test.py
@@ -1,67 +1,70 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Test for debug info."""
-from __future__ import print_function
import os
import subprocess
import sys
-import check_icf
import check_cus
import check_exist
+import check_icf
+
elf_checks = [
- check_exist.check_exist_all, check_cus.check_compile_units,
- check_icf.check_identical_code_folding
+ check_exist.check_exist_all,
+ check_cus.check_compile_units,
+ check_icf.check_identical_code_folding,
]
def scanelf(root):
- """Find ELFs in root.
+ """Find ELFs in root.
- Args:
- root: root dir to start with the search.
+ 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,
- encoding='utf-8')
- return [l.strip() for l in p.stdout]
+ Returns:
+ Filenames of ELFs in root.
+ """
+ p = subprocess.Popen(
+ ["scanelf", "-y", "-B", "-F", "%F", "-R", root],
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ 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))
+ 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))