X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=decoders%2Farm_itm%2Fpd.py;h=5970f27c0f9c2b97120562e6cf075b2cac7e24c8;hp=e32cce3b7256cb32d8ed8ac1c30872b1f975ab8f;hb=0a1661caef534aeac73dbf2cf6d0e0778bb9865c;hpb=686f0c3621cd8ef7264f3e45e0218f2ebdfb612a diff --git a/decoders/arm_itm/pd.py b/decoders/arm_itm/pd.py index e32cce3..5970f27 100644 --- a/decoders/arm_itm/pd.py +++ b/decoders/arm_itm/pd.py @@ -14,13 +14,13 @@ ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## along with this program; if not, see . ## import sigrokdecode as srd import string import subprocess +import re ARM_EXCEPTIONS = { 0: 'Thread', @@ -37,7 +37,7 @@ ARM_EXCEPTIONS = { } class Decoder(srd.Decoder): - api_version = 2 + api_version = 3 id = 'arm_itm' name = 'ARM ITM' longname = 'ARM Instrumentation Trace Macroblock' @@ -46,11 +46,12 @@ class Decoder(srd.Decoder): inputs = ['uart'] outputs = ['arm_itm'] options = ( - {'id': 'addr2line', 'desc': 'addr2line path', - 'default': 'arm-none-eabi-addr2line'}, - {'id': 'addr2line_opts', 'desc': 'addr2line options', - 'default': '-f -C -s -p'}, - {'id': 'elffile', 'desc': '.elf path', 'default': ''}, + {'id': 'objdump', 'desc': 'objdump path', + 'default': 'arm-none-eabi-objdump'}, + {'id': 'objdump_opts', 'desc': 'objdump options', + 'default': '-lSC'}, + {'id': 'elffile', 'desc': '.elf path', + 'default': ''}, ) annotations = ( ('trace', 'Trace information'), @@ -63,7 +64,8 @@ class Decoder(srd.Decoder): ('mode_thread', 'Current mode: thread'), ('mode_irq', 'Current mode: IRQ'), ('mode_exc', 'Current mode: Exception'), - ('location', 'Current location') + ('location', 'Current location'), + ('function', 'Current function'), ) annotation_rows = ( ('trace', 'Trace information', (0, 1)), @@ -72,21 +74,65 @@ class Decoder(srd.Decoder): ('dwt_watchpoint', 'DWT watchpoint', (4,)), ('dwt_exc', 'Exception trace', (5,)), ('dwt_pc', 'Program counter', (6,)), - ('mode', 'Current mode', (7, 8, 9,)), + ('mode', 'Current mode', (7, 8, 9)), ('location', 'Current location', (10,)), + ('function', 'Current function', (11,)), ) - def __init__(self, **kwargs): + def __init__(self): + self.reset() + + def reset(self): self.buf = [] self.syncbuf = [] self.swpackets = {} self.prevsample = 0 self.dwt_timestamp = 0 self.current_mode = None - self.current_loc = None + self.file_lookup = {} + self.func_lookup = {} def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) + self.load_objdump() + + def load_objdump(self): + '''Parse disassembly obtained from objdump into a lookup tables''' + if not (self.options['objdump'] and self.options['elffile']): + return + + opts = [self.options['objdump']] + opts += self.options['objdump_opts'].split() + opts += [self.options['elffile']] + + try: + disasm = subprocess.check_output(opts) + except subprocess.CalledProcessError: + return + + disasm = disasm.decode('utf-8', 'replace') + + instpat = re.compile('\s*([0-9a-fA-F]+):\t+([0-9a-fA-F ]+)\t+([a-zA-Z][^;]+)\s*;?.*') + filepat = re.compile('[^\s]+[/\\\\]([a-zA-Z0-9._-]+:[0-9]+)(?:\s.*)?') + funcpat = re.compile('[0-9a-fA-F]+\s*<([^>]+)>:.*') + + prev_file = '' + prev_func = '' + + for line in disasm.split('\n'): + m = instpat.match(line) + if m: + addr = int(m.group(1), 16) + self.file_lookup[addr] = prev_file + self.func_lookup[addr] = prev_func + else: + m = funcpat.match(line) + if m: + prev_func = m.group(1) + else: + m = filepat.match(line) + if m: + prev_file = m.group(1) def get_packet_type(self, byte): '''Identify packet type based on its first byte. @@ -125,26 +171,17 @@ class Decoder(srd.Decoder): else: self.current_mode = (self.startsample, new_mode) - def location_change(self, new_pc): - if self.options['addr2line'] and self.options['elffile']: - opts = [self.options['addr2line'], '-e', self.options['elffile']] - opts += self.options['addr2line_opts'].split() - opts += ['0x%08x' % new_pc] - - try: - new_loc = subprocess.check_output(opts) - except subprocess.CalledProcessError: - return - - new_loc = new_loc.decode('utf-8', 'replace').strip() + def location_change(self, pc): + new_loc = self.file_lookup.get(pc) + new_func = self.func_lookup.get(pc) + ss = self.startsample + es = self.prevsample - if self.current_loc is not None: - start, loc = self.current_loc - if loc == new_loc: - return # Still on same line. - self.put(start, self.startsample, self.out_ann, [10, [loc]]) + if new_loc is not None: + self.put(ss, es, self.out_ann, [10, [new_loc]]) - self.current_loc = (self.startsample, new_loc) + if new_func is not None: + self.put(ss, es, self.out_ann, [11, [new_func]]) def fallback(self, buf): ptype = self.get_packet_type(buf[0])