message: stack decode: handle address offsets
  When using ASLR, we need to calculate the offset before looking
  up symbols in order to get a correct stack trace.
diff: @@ -21,7 +21,7 @@ import sys
  # 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,8 +45,13 @@ 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)
  + 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:
  @@ -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 @@ if __name__ == "__main__":
  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:
  