Skip to content

Commit 97ba3a6

Browse files
committed
esp/tests: Syncs tracing tests with IDF changes
1 parent 0b83ba8 commit 97ba3a6

File tree

5 files changed

+391
-121
lines changed

5 files changed

+391
-121
lines changed

testing/esp/debug_backend_tests.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,12 @@ def step_in(self):
291291
rsn = self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_STOPPED, 5)
292292
self.assertEqual(rsn, dbg.Gdb.TARGET_STOP_REASON_STEPPED)
293293

294-
def step_out(self):
294+
def step_out(self, tmo=None):
295295
""" Runs until current function retunrs (step out, "finish" command in GDB)
296296
"""
297297
self.gdb.exec_finish()
298298
self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_RUNNING, 5)
299-
rsn = self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_STOPPED, 5)
299+
rsn = self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_STOPPED, 5 if tmo is None else tmo)
300300
self.assertEqual(rsn, dbg.Gdb.TARGET_STOP_REASON_FN_FINISHED)
301301

302302
class DebuggerTestAppTests(DebuggerTestsBase):
@@ -368,7 +368,7 @@ def select_sub_test(self, sub_test_num):
368368

369369
def run_to_bp(self, exp_rsn, func_name):
370370
self.resume_exec()
371-
rsn = self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_STOPPED, 5)
371+
rsn = self.gdb.wait_target_state(dbg.Gdb.TARGET_STATE_STOPPED, 20)
372372
self.assertEqual(rsn, exp_rsn)
373373
cur_frame = self.gdb.get_current_frame()
374374
self.assertEqual(cur_frame['func'], func_name)
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
# espytrace
1+
# espytrace Python package
22

3+
This package implements base routines and classes for processing ESP32 application level trace data.
4+
- `apptrace.py` includes functionality which is common for all types of trace data.
5+
- `sysview.py` includes functionality which is specific for SystemView trace data format.

testing/esp/extra/espytrace/apptrace.py

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import os
23
try:
34
from urlparse import urlparse
@@ -16,6 +17,13 @@
1617
import elftools.elf.constants as elfconst
1718

1819

20+
def clock():
21+
if sys.version_info >= (3, 3):
22+
return time.process_time()
23+
else:
24+
return time.clock()
25+
26+
1927
def addr2line(toolchain, elf_path, addr):
2028
"""
2129
Creates trace reader.
@@ -170,12 +178,12 @@ def read(self, sz):
170178
see Reader.read()
171179
"""
172180
data = b''
173-
start_tm = time.clock()
181+
start_tm = clock()
174182
while not self.need_stop:
175183
data += self.trace_file.read(sz - len(data))
176184
if len(data) == sz:
177185
break
178-
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
186+
if self.timeout != -1 and clock() >= start_tm + self.timeout:
179187
raise ReaderTimeoutError(self.timeout, sz)
180188
if self.need_stop:
181189
raise ReaderShutdownRequest()
@@ -192,17 +200,17 @@ def get_pos(self):
192200
"""
193201
return self.trace_file.tell()
194202

195-
def readline(self):
203+
def readline(self, linesep=os.linesep):
196204
"""
197205
see Reader.read()
198206
"""
199207
line = ''
200-
start_tm = time.clock()
208+
start_tm = clock()
201209
while not self.need_stop:
202210
line += self.trace_file.readline().decode("utf-8")
203-
if line.endswith(os.linesep):
211+
if line.endswith(linesep):
204212
break
205-
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
213+
if self.timeout != -1 and clock() >= start_tm + self.timeout:
206214
raise ReaderTimeoutError(self.timeout, 1)
207215
if self.need_stop:
208216
raise ReaderShutdownRequest()
@@ -213,12 +221,12 @@ def forward(self, sz):
213221
see Reader.read()
214222
"""
215223
cur_pos = self.trace_file.tell()
216-
start_tm = time.clock()
224+
start_tm = clock()
217225
while not self.need_stop:
218226
file_sz = os.path.getsize(self.trace_file_path)
219227
if file_sz - cur_pos >= sz:
220228
break
221-
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
229+
if self.timeout != -1 and clock() >= start_tm + self.timeout:
222230
raise ReaderTimeoutError(self.timeout, sz)
223231
if self.need_stop:
224232
raise ReaderShutdownRequest()
@@ -351,6 +359,34 @@ def reader_create(trc_src, tmo):
351359
return None
352360

353361

362+
class TraceEvent:
363+
"""
364+
Base class for all trace events.
365+
"""
366+
def __init__(self, name, core_id, evt_id):
367+
self.name = name
368+
self.ctx_name = 'None'
369+
self.in_irq = False
370+
self.core_id = core_id
371+
self.id = evt_id
372+
self.ts = 0
373+
self.params = {}
374+
375+
@property
376+
def ctx_desc(self):
377+
if self.in_irq:
378+
return 'IRQ "%s"' % self.ctx_name
379+
return 'task "%s"' % self.ctx_name
380+
381+
def to_jsonable(self):
382+
res = self.__dict__
383+
params = {}
384+
for p in self.params:
385+
params.update(self.params[p].to_jsonable())
386+
res['params'] = params
387+
return res
388+
389+
354390
class TraceDataProcessor:
355391
"""
356392
Base abstract class for all trace data processors.
@@ -432,17 +468,21 @@ def get_str_from_elf(felf, str_addr):
432468
string
433469
string or None if it was not found
434470
"""
435-
tgt_str = ""
471+
tgt_str = ''
436472
for sect in felf.iter_sections():
437473
if sect['sh_addr'] == 0 or (sect['sh_flags'] & elfconst.SH_FLAGS.SHF_ALLOC) == 0:
438474
continue
439475
if str_addr < sect['sh_addr'] or str_addr >= sect['sh_addr'] + sect['sh_size']:
440476
continue
441477
sec_data = sect.data()
442478
for i in range(str_addr - sect['sh_addr'], sect['sh_size']):
443-
if sec_data[i] == "\0":
479+
if type(sec_data) is str:
480+
ch = sec_data[i]
481+
else:
482+
ch = str(chr(sec_data[i]))
483+
if ch == '\0':
444484
break
445-
tgt_str += sec_data[i]
485+
tgt_str += ch
446486
if len(tgt_str) > 0:
447487
return tgt_str
448488
return None
@@ -488,9 +528,8 @@ def get_message(self, felf):
488528
fmt_str = get_str_from_elf(felf, self.fmt_addr)
489529
if not fmt_str:
490530
raise LogTraceParseError('Failed to find format string for 0x%x' % self.fmt_addr)
491-
i = 0
492531
prcnt_idx = 0
493-
while i < len(self.args):
532+
for i, arg in enumerate(self.args):
494533
prcnt_idx = fmt_str.find('%', prcnt_idx, -2) # TODO: check str ending with %
495534
if prcnt_idx == -1:
496535
break
@@ -502,7 +541,6 @@ def get_message(self, felf):
502541
self.args[i] = arg_str
503542
else:
504543
self.args[i] = '<None>'
505-
i += 1
506544
fmt_str = fmt_str.replace('%p', '%x')
507545
return fmt_str % tuple(self.args)
508546

@@ -591,66 +629,63 @@ class HeapTraceEvent:
591629
"""
592630
Heap trace event.
593631
"""
594-
def __init__(self, ctx_name, in_irq, core_id, ts, alloc, size, addr, callers, toolchain='', elf_path=''):
632+
def __init__(self, trace_event, alloc, toolchain='', elf_path=''):
595633
"""
596634
Constructor.
597635
598636
Parameters
599637
----------
600-
ctx_name : string
601-
name of event context (task or IRQ name)
602-
in_irq : bool
603-
True if event has been generated in IRQ context, otherwise False
604-
core_id : int
605-
core which generated the event
606-
ts : float
607-
event timestamp
638+
sys_view_event : TraceEvent
639+
trace event object related to this heap event
608640
alloc : bool
609641
True for allocation event, otherwise False
610-
size : int
611-
size of allocation; has no meaning for de-allocation event
612-
addr : int
613-
address of allocation/de-allocation
614-
callers : list
615-
list of callers (callstack) for event
616642
toolchain_pref : string
617643
toolchain prefix to retrieve source line locations using addresses
618644
elf_path : string
619645
path to ELF file to retrieve format strings for log messages
620646
"""
621-
self.ctx_name = ctx_name
622-
self.in_irq = in_irq
623-
self.core_id = core_id
624-
self.ts = ts
647+
self.trace_event = trace_event
625648
self.alloc = alloc
626-
self.size = size
627-
self.addr = addr
628-
self.callers = callers
629649
self.toolchain = toolchain
630650
self.elf_path = elf_path
651+
if self.alloc:
652+
self.size = self.trace_event.params['size'].value
653+
else:
654+
self.size = None
655+
656+
@property
657+
def addr(self):
658+
return self.trace_event.params['addr'].value
659+
660+
@property
661+
def callers(self):
662+
return self.trace_event.params['callers'].value
631663

632664
def __repr__(self):
633665
if len(self.toolchain) and len(self.elf_path):
634666
callers = os.linesep
635-
for addr in self.callers:
667+
for addr in self.trace_event.params['callers'].value:
668+
if addr == 0:
669+
break
636670
callers += '{}'.format(addr2line(self.toolchain, self.elf_path, addr))
637671
else:
638672
callers = ''
639-
for addr in self.callers:
673+
for addr in self.trace_event.params['callers'].value:
674+
if addr == 0:
675+
break
640676
if len(callers):
641677
callers += ':'
642678
callers += '0x{:x}'.format(addr)
643-
if self.in_irq:
644-
ctx_desc = 'IRQ "%s"' % self.ctx_name
645-
else:
646-
ctx_desc = 'task "%s"' % self.ctx_name
647679
if self.alloc:
648-
return "[{:.9f}] HEAP: Allocated {:d} bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.ts, self.size,
649-
self.addr, ctx_desc,
650-
self.core_id, callers)
680+
return "[{:.9f}] HEAP: Allocated {:d} bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.trace_event.ts,
681+
self.size, self.addr,
682+
self.trace_event.ctx_desc,
683+
self.trace_event.core_id,
684+
callers)
651685
else:
652-
return "[{:.9f}] HEAP: Freed bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.ts, self.addr, ctx_desc,
653-
self.core_id, callers)
686+
return "[{:.9f}] HEAP: Freed bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.trace_event.ts,
687+
self.addr, self.trace_event.ctx_desc,
688+
self.trace_event.core_id, callers)
654689

655690

656691
class BaseHeapTraceDataProcessorImpl:

0 commit comments

Comments
 (0)