debug_info_test: check that chrome was built with ICF enabled

For both amd64 and arm, when ICF (Identical Code Folding) is enabled,
there is >60,000 drop in the number of unique addresses of text symbols.
We check here that the drop is at least 10,000.

See https://crbug.com/813272#c18 for details.

BUG=chromium:813272
TEST='./debug_info_test.py /build/chell/usr/lib/debug/opt/google/chrome/chrome.debug'
TEST='./debug_info_test.py /build/elm/usr/lib/debug/opt/google/chrome/chrome.debug'

Change-Id: I23d1b48e6547bf3042096bed1c566ec50c5b2d66
Reviewed-on: https://chromium-review.googlesource.com/1053388
Commit-Ready: Rahul Chaudhry <rahulchaudhry@chromium.org>
Tested-by: Rahul Chaudhry <rahulchaudhry@chromium.org>
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Reviewed-by: Yunlian Jiang <yunlian@chromium.org>
diff --git a/debug_info_test/check_icf.py b/debug_info_test/check_icf.py
new file mode 100644
index 0000000..4ac67db
--- /dev/null
+++ b/debug_info_test/check_icf.py
@@ -0,0 +1,47 @@
+# 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 re
+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
+    Return:
+        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'))
+    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/debug_info_test.py b/debug_info_test/debug_info_test.py
index 99b8e01..f5afd64 100755
--- a/debug_info_test/debug_info_test.py
+++ b/debug_info_test/debug_info_test.py
@@ -8,11 +8,13 @@
 import subprocess
 import sys
 
+import check_icf
 import check_cus
 import check_exist
 
 elf_checks = [check_exist.check_exist_all,
-              check_cus.check_compile_units]
+              check_cus.check_compile_units,
+              check_icf.check_identical_code_folding]
 
 def scanelf(root):
     """find ELFs in root