diff --git a/tools/stack_decode.py b/tools/stack_decode.py index ffc71387bb1f0..87fe79d7fcc34 100755 --- a/tools/stack_decode.py +++ b/tools/stack_decode.py @@ -21,7 +21,7 @@ # contain backtrace output extract the address and call add2line to get the file # and line information. Output appended to end of original backtrace line. Output # any nonmatching lines unmodified. End when EOF received. -def decode_stacktrace_log(object_file, input_source): +def decode_stacktrace_log(object_file, input_source, address_offset=0): traces = {} # Match something like: # [backtrace] [bazel-out/local-dbg/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:84] @@ -45,9 +45,14 @@ def decode_stacktrace_log(object_file, input_source): stackaddr_match = asan_re.search(line) if stackaddr_match: address = stackaddr_match.groups()[0] + if address_offset != 0: + address = hex(int(address, 16) - address_offset) file_and_line_number = run_addr2line(object_file, address) file_and_line_number = trim_proc_cwd(file_and_line_number) - sys.stdout.write("%s %s" % (line.strip(), file_and_line_number)) + if address_offset != 0: + sys.stdout.write("%s->[%s] %s" % (line.strip(), address, file_and_line_number)) + else: + sys.stdout.write("%s %s" % (line.strip(), file_and_line_number)) continue else: # Pass through print all other log lines: @@ -72,6 +77,27 @@ def trim_proc_cwd(file_and_line_number): return re.sub(trim_regex, '', file_and_line_number) +# Execute pmap with a pid to calculate the addr offset +# +# Returns list of extended process memory information. +def run_pmap(pid): + return subprocess.check_output(['pmap', '-qX', str(pid)]).decode('utf-8')[1:] + + +# Find the virtual address offset of the process. This may be needed due ASLR. +# +# Returns the virtual address offset as an integer, or 0 if unable to determine. +def find_address_offset(pid): + try: + proc_memory = run_pmap(pid) + match = re.search(r'([a-f0-9]+)\s+r-xp', proc_memory) + if match is None: + return 0 + return int(match.group(1), 16) + except (subprocess.CalledProcessError, PermissionError): + return 0 + + if __name__ == "__main__": if len(sys.argv) > 2 and sys.argv[1] == '-s': decode_stacktrace_log(sys.argv[2], sys.stdin) @@ -81,7 +107,8 @@ def trim_proc_cwd(file_and_line_number): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) - decode_stacktrace_log(sys.argv[1], rununder.stdout) + offset = find_address_offset(rununder.pid) + decode_stacktrace_log(sys.argv[1], rununder.stdout, offset) rununder.wait() sys.exit(rununder.returncode) # Pass back test pass/fail result else: