Merge "Remove parameters from symbolized stack traces." am: a3fe9b1729 am: 84ae029abf
Original change: https://android-review.googlesource.com/c/platform/development/+/1875691 Change-Id: I1fd372ead3544203c97f300a2b8edb13128cd91e
This commit is contained in:
@@ -32,6 +32,7 @@ def main():
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--symbols-dir', '--syms', '--symdir', help='the symbols directory')
|
||||
group.add_argument('--symbols-zip', help='the symbols.zip file from a build')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help="include function parameters")
|
||||
parser.add_argument('file',
|
||||
metavar='FILE',
|
||||
default='-',
|
||||
@@ -52,6 +53,7 @@ def main():
|
||||
with zipfile.ZipFile(args.symbols_zip) as zf:
|
||||
zf.extractall(tmp.name)
|
||||
symbol.SYMBOLS_DIR = glob.glob("%s/out/target/product/*/symbols" % tmp.name)[0]
|
||||
symbol.VERBOSE = args.verbose
|
||||
if args.file == '-':
|
||||
print("Reading native crash info from stdin")
|
||||
f = sys.stdin
|
||||
|
||||
@@ -498,12 +498,15 @@ class TraceConverter:
|
||||
# display "a -> b -> c" in the stack trace instead of just "a -> c"
|
||||
info = symbol.SymbolInformation(lib, code_addr)
|
||||
nest_count = len(info) - 1
|
||||
for (source_symbol, source_location, object_symbol_with_offset) in info:
|
||||
for (source_symbol, source_location, symbol_with_offset) in info:
|
||||
if not source_symbol:
|
||||
if symbol_present:
|
||||
source_symbol = symbol.CallCppFilt(symbol_name)
|
||||
else:
|
||||
source_symbol = "<unknown>"
|
||||
if not symbol.VERBOSE:
|
||||
source_symbol = symbol.FormatSymbolWithoutParameters(source_symbol)
|
||||
symbol_with_offset = symbol.FormatSymbolWithoutParameters(symbol_with_offset)
|
||||
if not source_location:
|
||||
source_location = area
|
||||
if lib_name:
|
||||
@@ -515,11 +518,9 @@ class TraceConverter:
|
||||
arrow = "v-------------->"
|
||||
self.trace_lines.append((arrow, source_symbol, source_location))
|
||||
else:
|
||||
if not object_symbol_with_offset:
|
||||
object_symbol_with_offset = source_symbol
|
||||
self.trace_lines.append((code_addr,
|
||||
object_symbol_with_offset,
|
||||
source_location))
|
||||
if not symbol_with_offset:
|
||||
symbol_with_offset = source_symbol
|
||||
self.trace_lines.append((code_addr, symbol_with_offset, source_location))
|
||||
if self.code_line.match(line):
|
||||
# Code lines should be ignored. If this were exluded the 'code around'
|
||||
# sections would trigger value_line matches.
|
||||
|
||||
@@ -60,6 +60,7 @@ SYMBOLS_DIR = FindSymbolsDir()
|
||||
|
||||
ARCH = None
|
||||
|
||||
VERBOSE = False
|
||||
|
||||
# These are private. Do not access them from other modules.
|
||||
_CACHED_TOOLCHAIN = None
|
||||
@@ -484,6 +485,37 @@ def FormatSymbolWithOffset(symbol, offset):
|
||||
return symbol
|
||||
return "%s+%d" % (symbol, offset)
|
||||
|
||||
def FormatSymbolWithoutParameters(symbol):
|
||||
"""Remove parameters from function.
|
||||
|
||||
Rather than trying to parse the demangled C++ signature,
|
||||
it just removes matching top level parenthesis.
|
||||
"""
|
||||
if not symbol:
|
||||
return symbol
|
||||
|
||||
result = symbol
|
||||
result = result.replace(") const", ")") # Strip const keyword.
|
||||
result = result.replace("operator<<", "operator\u00AB") # Avoid unmatched '<'.
|
||||
result = result.replace("operator>>", "operator\u00BB") # Avoid unmatched '>'.
|
||||
result = result.replace("operator->", "operator\u2192") # Avoid unmatched '>'.
|
||||
|
||||
nested = [] # Keeps tract of current nesting level of parenthesis.
|
||||
for i in reversed(range(len(result))): # Iterate backward to make cutting easier.
|
||||
c = result[i]
|
||||
if c == ')' or c == '>':
|
||||
if len(nested) == 0:
|
||||
end = i + 1 # Mark the end of top-level pair.
|
||||
nested.append(c)
|
||||
if c == '(' or c == '<':
|
||||
if len(nested) == 0 or {')':'(', '>':'<'}[nested.pop()] != c:
|
||||
return symbol # Malformed: character does not match its pair.
|
||||
if len(nested) == 0 and c == '(' and (end - i) > 2:
|
||||
result = result[:i] + result[end:] # Remove substring (i, end).
|
||||
if len(nested) > 0:
|
||||
return symbol # Malformed: missing pair.
|
||||
|
||||
return result.strip()
|
||||
|
||||
def GetAbiFromToolchain(toolchain_var, bits):
|
||||
toolchain = os.environ.get(toolchain_var)
|
||||
@@ -748,5 +780,32 @@ class SetArchTests(unittest.TestCase):
|
||||
"Could not determine arch from input, use --arch=XXX to specify it",
|
||||
SetAbi, [])
|
||||
|
||||
class FormatSymbolWithoutParametersTests(unittest.TestCase):
|
||||
def test_c(self):
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo"), "foo")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo+42"), "foo+42")
|
||||
|
||||
def test_simple(self):
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo(int i)"), "foo")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo(int i)+42"), "foo+42")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("bar::foo(int i)+42"), "bar::foo+42")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("operator()"), "operator()")
|
||||
|
||||
def test_templates(self):
|
||||
self.assertEqual(FormatSymbolWithoutParameters("bar::foo<T>(vector<T>& v)"), "bar::foo<T>")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("bar<T>::foo(vector<T>& v)"), "bar<T>::foo")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("bar::foo<T>(vector<T<U>>& v)"), "bar::foo<T>")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("bar::foo<(EnumType)0>(vector<(EnumType)0>& v)"),
|
||||
"bar::foo<(EnumType)0>")
|
||||
|
||||
def test_nested(self):
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo(int i)::bar(int j)"), "foo::bar")
|
||||
|
||||
def test_unballanced(self):
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo(bar(int i)"), "foo(bar(int i)")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo)bar(int i)"), "foo)bar(int i)")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo<bar(int i)"), "foo<bar(int i)")
|
||||
self.assertEqual(FormatSymbolWithoutParameters("foo>bar(int i)"), "foo>bar(int i)")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user