From d900d08d813a290cbea672862707feff3c2c44ce Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Fri, 21 Aug 2015 15:25:03 -0700 Subject: [PATCH] Development/scripts: Add sanitizer dump support to stack Add trace parsing for sanitizer output. The output is different from debuggerd output (and we do not have control over it). Use two separate regexes and factor out the parsing into a method returning a tuple of data. Note: as we have no control over the prologue of the dump, we cannot change it to include information like the ABI. Thus, this functionality only works in a lunched tree, where the tool implicitly uses the symbols directory. Change-Id: Ic1189f4f65cf7728d1baec7055ecb549b0aa5f62 --- scripts/stack_core.py | 53 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/scripts/stack_core.py b/scripts/stack_core.py index 2d055f0ef..879ce3886 100755 --- a/scripts/stack_core.py +++ b/scripts/stack_core.py @@ -38,6 +38,7 @@ class TraceConverter: dalvik_native_thread_line = re.compile("(\".*\" sysTid=[0-9]+ nice=[0-9]+.*)") register_line = re.compile("$a") trace_line = re.compile("$a") + sanitizer_trace_line = re.compile("$a") value_line = re.compile("$a") code_line = re.compile("$a") trace_lines = [] @@ -79,7 +80,29 @@ class TraceConverter: # Or lines from AndroidFeedback crash report system logs like: # 03-25 00:51:05.520 I/DEBUG ( 65): #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so # Please note the spacing differences. - self.trace_line = re.compile("(.*)\#([0-9]+)[ \t]+(..)[ \t]+([0-9a-f]" + self.width + ")[ \t]+([^\r\n \t]*)( \((.*)\))?") # pylint: disable-msg=C6310 + self.trace_line = re.compile( + ".*" # Random start stuff. + "\#(?P[0-9]+)" # Frame number. + "[ \t]+..[ \t]+" # (space)pc(space). + "(?P[0-9a-f]" + self.width + ")[ \t]+" # Offset (hex number given without + # 0x prefix). + "(?P[^\r\n \t]*)" # Library name. + "(?P \((?P.*)\))?") # Is the symbol there? + # pylint: disable-msg=C6310 + # Sanitizer output. This is different from debuggerd output, and it is easier to handle this as + # its own regex. Example: + # 08-19 05:29:26.283 397 403 I : #0 0xb6a15237 (/system/lib/libclang_rt.asan-arm-android.so+0x4f237) + self.sanitizer_trace_line = re.compile( + ".*" # Random start stuff. + "\#(?P[0-9]+)" # Frame number. + "[ \t]+0x[0-9a-f]+[ \t]+" # PC, not interesting to us. + "\(" # Opening paren. + "(?P[^+]+)" # Library name. + "\+" # '+' + "0x(?P[0-9a-f]+)" # Offset (hex number given with + # 0x prefix). + "\)") # Closin paren. + # pylint: disable-msg=C6310 # Examples of matched value lines include: # bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so # bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so (symbol) @@ -143,6 +166,23 @@ class TraceConverter: self.ProcessLine(line) self.PrintOutput(self.trace_lines, self.value_lines) + def MatchTraceLine(self, line): + if self.trace_line.match(line): + match = self.trace_line.match(line) + return {"frame": match.group("frame"), + "offset": match.group("offset"), + "dso": match.group("dso"), + "symbol_present": bool(match.group("symbolpresent")), + "symbol_name": match.group("symbol")} + if self.sanitizer_trace_line.match(line): + match = self.sanitizer_trace_line.match(line) + return {"frame": match.group("frame"), + "offset": match.group("offset"), + "dso": match.group("dso"), + "symbol_present": False, + "symbol_name": None} + return None + def ProcessLine(self, line): ret = False process_header = self.process_info_line.search(line) @@ -184,11 +224,14 @@ class TraceConverter: symbol.ARCH = abi_header.group(2) self.UpdateAbiRegexes() return ret - if self.trace_line.match(line): + trace_line_dict = self.MatchTraceLine(line) + if trace_line_dict is not None: ret = True - match = self.trace_line.match(line) - (unused_0, frame, unused_1, - code_addr, area, symbol_present, symbol_name) = match.groups() + frame = trace_line_dict["frame"] + code_addr = trace_line_dict["offset"] + area = trace_line_dict["dso"] + symbol_present = trace_line_dict["symbol_present"] + symbol_name = trace_line_dict["symbol_name"] if frame <= self.last_frame and (self.trace_lines or self.value_lines): self.PrintOutput(self.trace_lines, self.value_lines)