summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/configure/check_debug_ranges.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/configure/check_debug_ranges.py')
-rw-r--r--python/mozbuild/mozbuild/configure/check_debug_ranges.py68
1 files changed, 68 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/configure/check_debug_ranges.py b/python/mozbuild/mozbuild/configure/check_debug_ranges.py
new file mode 100644
index 0000000000..f82624c14f
--- /dev/null
+++ b/python/mozbuild/mozbuild/configure/check_debug_ranges.py
@@ -0,0 +1,68 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This script returns the number of items for the DW_AT_ranges corresponding
+# to a given compilation unit. This is used as a helper to find a bug in some
+# versions of GNU ld.
+
+import re
+import subprocess
+import sys
+
+
+def get_range_for(compilation_unit, debug_info):
+ """Returns the range offset for a given compilation unit
+ in a given debug_info."""
+ name = ranges = ""
+ search_cu = False
+ for nfo in debug_info.splitlines():
+ if "DW_TAG_compile_unit" in nfo:
+ search_cu = True
+ elif "DW_TAG_" in nfo or not nfo.strip():
+ if name == compilation_unit and ranges != "":
+ return int(ranges, 16)
+ name = ranges = ""
+ search_cu = False
+ if search_cu:
+ if "DW_AT_name" in nfo:
+ name = nfo.rsplit(None, 1)[1]
+ elif "DW_AT_ranges" in nfo:
+ ranges = nfo.rsplit(None, 1)[1]
+ return None
+
+
+def get_range_length(range, debug_ranges):
+ """Returns the number of items in the range starting at the
+ given offset."""
+ length = 0
+ for line in debug_ranges.splitlines():
+ m = re.match("\s*([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)", line)
+ if m and int(m.group(1), 16) == range:
+ length += 1
+ return length
+
+
+def main(bin, compilation_unit):
+ p = subprocess.Popen(
+ ["objdump", "-W", bin],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ )
+ (out, err) = p.communicate()
+ sections = re.split("\n(Contents of the|The section) ", out)
+ debug_info = [s for s in sections if s.startswith(".debug_info")]
+ debug_ranges = [s for s in sections if s.startswith(".debug_ranges")]
+ if not debug_ranges or not debug_info:
+ return 0
+
+ range = get_range_for(compilation_unit, debug_info[0])
+ if range is not None:
+ return get_range_length(range, debug_ranges[0])
+
+ return -1
+
+
+if __name__ == "__main__":
+ print(main(*sys.argv[1:]))