1*810390e3Srobert#!/usr/bin/env bash
23cab2bb3Spatrick
33cab2bb3Spatrick# The lines that we're looking to symbolize look like this:
43cab2bb3Spatrick  #0 ./a.out(_foo+0x3e6) [0x55a52e64c696]
53cab2bb3Spatrick# ... which come from the backtrace_symbols() symbolisation function used by
63cab2bb3Spatrick# default in Scudo's implementation of GWP-ASan.
73cab2bb3Spatrick
83cab2bb3Spatrickwhile read -r line; do
93cab2bb3Spatrick  # Check that this line needs symbolization.
103cab2bb3Spatrick  should_symbolize="$(echo $line |\
113cab2bb3Spatrick     grep -E '^[ ]*\#.*\(.*\+0x[0-9a-f]+\) \[0x[0-9a-f]+\]$')"
123cab2bb3Spatrick
133cab2bb3Spatrick  if [ -z "$should_symbolize" ]; then
143cab2bb3Spatrick    echo "$line"
153cab2bb3Spatrick    continue
163cab2bb3Spatrick  fi
173cab2bb3Spatrick
183cab2bb3Spatrick  # Carve up the input line into sections.
193cab2bb3Spatrick  binary_name="$(echo $line | grep -oE ' .*\(' | rev | cut -c2- | rev |\
203cab2bb3Spatrick      cut -c2-)"
213cab2bb3Spatrick  function_name="$(echo $line | grep -oE '\([^+]*' | cut -c2-)"
223cab2bb3Spatrick  function_offset="$(echo $line | grep -oE '\(.*\)' | grep -oE '\+.*\)' |\
233cab2bb3Spatrick      cut -c2- | rev | cut -c2- | rev)"
243cab2bb3Spatrick  frame_number="$(echo $line | grep -oE '\#[0-9]+ ')"
253cab2bb3Spatrick
263cab2bb3Spatrick  if [ -z "$function_name" ]; then
273cab2bb3Spatrick    # If the offset is binary-relative, just resolve that.
28d89ec533Spatrick    symbolized="$(echo $function_offset | addr2line -ie $binary_name)"
293cab2bb3Spatrick  else
303cab2bb3Spatrick    # Otherwise, the offset is function-relative. Get the address of the
313cab2bb3Spatrick    # function, and add it to the offset, then symbolize.
323cab2bb3Spatrick    function_addr="0x$(echo $function_offset |\
333cab2bb3Spatrick       nm --defined-only $binary_name 2> /dev/null |\
343cab2bb3Spatrick       grep -E " $function_name$" | cut -d' ' -f1)"
353cab2bb3Spatrick
363cab2bb3Spatrick    # Check that we could get the function address from nm.
373cab2bb3Spatrick    if [ -z "$function_addr" ]; then
383cab2bb3Spatrick      echo "$line"
393cab2bb3Spatrick      continue
403cab2bb3Spatrick    fi
413cab2bb3Spatrick
423cab2bb3Spatrick    # Add the function address and offset to get the offset into the binary.
433cab2bb3Spatrick    binary_offset="$(printf "0x%X" "$((function_addr+function_offset))")"
44d89ec533Spatrick    symbolized="$(echo $binary_offset | addr2line -ie $binary_name)"
453cab2bb3Spatrick  fi
463cab2bb3Spatrick
473cab2bb3Spatrick  # Check that it symbolized properly. If it didn't, output the old line.
483cab2bb3Spatrick  echo $symbolized | grep -E ".*\?.*:" > /dev/null
493cab2bb3Spatrick  if [ "$?" -eq "0" ]; then
503cab2bb3Spatrick    echo "$line"
513cab2bb3Spatrick    continue
523cab2bb3Spatrick  else
533cab2bb3Spatrick    echo "${frame_number}${symbolized}"
543cab2bb3Spatrick  fi
55d89ec533Spatrickdone 2> >(grep -v "addr2line: DWARF error: could not find variable specification")
56