Skip to content

Commit e7c4381

Browse files
Tasssadarjonathandreyer
authored andcommitted
Make esp32_exception_decoder more generic (platformio#1357)
1 parent e071960 commit e7c4381

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

monitor/filter_exception_decoder.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
class Esp32ExceptionDecoder(DeviceMonitorFilterBase):
3333
NAME = "esp32_exception_decoder"
3434

35-
BACKTRACE_PATTERN = re.compile(r"^Backtrace:(((\s?0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8}))+)")
36-
BACKTRACE_ADDRESS_PATTERN = re.compile(r'0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8}')
35+
ADDR_PATTERN = re.compile(r"((?:0x[0-9a-fA-F]{8}[: ]?)+)\s?$")
36+
ADDR_SPLIT = re.compile(r"[ :]")
37+
PREFIX_RE = re.compile(r"^ *")
3738

3839
def __call__(self):
3940
self.buffer = ""
@@ -56,7 +57,8 @@ def __call__(self):
5657
def setup_paths(self):
5758
self.project_dir = os.path.abspath(self.project_dir)
5859
try:
59-
data = load_build_metadata(self.project_dir, self.environment)
60+
data = load_build_metadata(self.project_dir, self.environment, cache=True)
61+
6062
self.firmware_path = data["prog_path"]
6163
if not os.path.isfile(self.firmware_path):
6264
sys.stderr.write(
@@ -100,38 +102,65 @@ def rx(self, text):
100102
self.buffer = ""
101103
last = idx + 1
102104

103-
m = self.BACKTRACE_PATTERN.match(line)
105+
m = self.ADDR_PATTERN.search(line)
104106
if m is None:
105107
continue
106108

107-
trace = self.get_backtrace(m)
108-
if len(trace) != "":
109+
trace = self.build_backtrace(line, m.group(1))
110+
if trace:
109111
text = text[: idx + 1] + trace + text[idx + 1 :]
110112
last += len(trace)
111113
return text
112114

113-
def get_backtrace(self, match):
114-
trace = "\n"
115+
def is_address_ignored(self, address):
116+
return address in ("", "0x00000000")
117+
118+
def filter_addresses(self, adresses_str):
119+
addresses = self.ADDR_SPLIT.split(adresses_str)
120+
size = len(addresses)
121+
while size > 1 and self.is_address_ignored(addresses[size-1]):
122+
size -= 1
123+
return addresses[:size]
124+
125+
def build_backtrace(self, line, address_match):
126+
addresses = self.filter_addresses(address_match)
127+
if not addresses:
128+
return ""
129+
130+
prefix_match = self.PREFIX_RE.match(line)
131+
prefix = prefix_match.group(0) if prefix_match is not None else ""
132+
133+
trace = ""
115134
enc = "mbcs" if IS_WINDOWS else "utf-8"
116135
args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path]
117136
try:
118-
for i, addr in enumerate(self.BACKTRACE_ADDRESS_PATTERN.findall(match.group(1))):
137+
i = 0
138+
for addr in addresses:
119139
output = (
120140
subprocess.check_output(args + [addr])
121141
.decode(enc)
122142
.strip()
123143
)
144+
145+
# newlines happen with inlined methods
124146
output = output.replace(
125147
"\n", "\n "
126-
) # newlines happen with inlined methods
148+
)
149+
150+
# throw out addresses not from ELF
151+
if output == "?? ??:0":
152+
continue
153+
127154
output = self.strip_project_dir(output)
128-
trace += " #%-2d %s in %s\n" % (i, addr, output)
155+
trace += "%s #%-2d %s in %s\n" % (prefix, i, addr, output)
156+
i += 1
129157
except subprocess.CalledProcessError as e:
130158
sys.stderr.write(
131159
"%s: failed to call %s: %s\n"
132160
% (self.__class__.__name__, self.addr2line_path, e)
133161
)
134-
return trace
162+
163+
return trace + "\n" if trace else ""
135164

136165
def strip_project_dir(self, trace):
137166
while True:

0 commit comments

Comments
 (0)