[Lldb-commits] [lldb] r242566 - Added support for dumping 'x', 'X', 'qSymbol' packets. Also dump any XML retrieved from a qXfer packets.

Greg Clayton gclayton at apple.com
Fri Jul 17 13:16:50 PDT 2015


Author: gclayton
Date: Fri Jul 17 15:16:50 2015
New Revision: 242566

URL: http://llvm.org/viewvc/llvm-project?rev=242566&view=rev
Log:
Added support for dumping 'x', 'X', 'qSymbol' packets. Also dump any XML retrieved from a qXfer packets.


Modified:
    lldb/trunk/examples/python/gdbremote.py

Modified: lldb/trunk/examples/python/gdbremote.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/gdbremote.py?rev=242566&r1=242565&r2=242566&view=diff
==============================================================================
--- lldb/trunk/examples/python/gdbremote.py (original)
+++ lldb/trunk/examples/python/gdbremote.py Fri Jul 17 15:16:50 2015
@@ -33,6 +33,7 @@ import xml.etree.ElementTree as ET
 #----------------------------------------------------------------------
 g_log_file = ''
 g_byte_order = 'little'
+g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)')
 
 class TerminalColors:
     '''Simple terminal colors class'''
@@ -346,6 +347,13 @@ class Packet:
             self.str = self.str[1:]
         return ch
         
+    def skip_exact_string(self, s):
+        if self.str and self.str.startswith(s):
+            self.str = self.str[len(s):]
+            return True
+        else:
+            return False
+
     def get_hex_uint8(self):
         if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits:
             uval = int(self.str[0:2], 16)
@@ -399,6 +407,19 @@ class Packet:
             uval |= self.get_hex_uint8() << 56
         return uval
     
+    def get_number(self, fail_value=-1):
+        '''Get a number from the packet. The number must be in big endian format and should be parsed
+        according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with 
+        [1-9] means decimal, etc)'''
+        match = g_number_regex.match (self.str)
+        if match:
+            number_str = match.group(1)
+            self.str = self.str[len(number_str):]
+            return int(number_str, 0)
+        else:
+            return fail_value
+        
+        
     def get_hex_ascii_str(self, n=0):
         hex_chars = self.get_hex_chars(n)
         if hex_chars:
@@ -479,6 +500,7 @@ def get_thread_from_thread_suffix(str):
 
 def cmd_stop_reply(options, cmd, args):
     print "get_last_stop_info()"
+    return False
 
 def rsp_stop_reply(options, cmd, cmd_args, rsp):
     global g_byte_order
@@ -498,6 +520,7 @@ def rsp_stop_reply(options, cmd, cmd_arg
             elif key == 'jthreads' or key == 'jstopinfo':
                 key_value_pair[1] = binascii.unhexlify(key_value_pair[1])
         key_value_pairs.insert(0, ['signal', signo])
+        print 'Stop reply:'
         dump_key_value_pairs (key_value_pairs)
     elif stop_type == 'W':
         exit_status = packet.get_hex_uint8()
@@ -511,10 +534,45 @@ def cmd_unknown_packet(options, cmd, arg
         print "cmd: %s, args: %s", cmd, args
     else:
         print "cmd: %s", cmd
+    return False
+
+def cmd_qSymbol(options, cmd, args):
+    if args == ':':
+        print 'ready to serve symbols'
+    else:
+        packet = Packet(args)
+        symbol_addr = packet.get_hex_uint('big')
+        if symbol_addr is None:
+            if packet.skip_exact_string(':'):
+                symbol_name = packet.get_hex_ascii_str()
+                print 'lookup_symbol("%s") -> symbol not available yet' % (symbol_name)
+            else:
+                print 'error: bad command format'
+        else:
+            if packet.skip_exact_string(':'):
+                symbol_name = packet.get_hex_ascii_str()
+                print 'lookup_symbol("%s") -> 0x%x' % (symbol_name, symbol_addr)
+            else:
+                print 'error: bad command format'
+
+def rsp_qSymbol(options, cmd, cmd_args, rsp):
+    if len(rsp) == 0:
+        print "Unsupported"
+    else:
+        if rsp == "OK":
+            print "No more symbols to lookup"
+        else:
+            packet = Packet(rsp)
+            if packet.skip_exact_string("qSymbol:"):
+                symbol_name = packet.get_hex_ascii_str()
+                print 'lookup_symbol("%s")' % (symbol_name)
+            else:
+                print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp)
 
 def cmd_qXfer(options, cmd, args):
     # $qXfer:features:read:target.xml:0,1ffff#14
     print "read target special data %s" % (args)
+    return True
 
 def rsp_qXfer(options, cmd, cmd_args, rsp):
     data = string.split(cmd_args, ':')
@@ -544,14 +602,16 @@ def rsp_qXfer(options, cmd, cmd_args, rs
                             if 'bitsize' in reg_element.attrib:
                                 reg_info.info['bitsize'] = reg_element.attrib['bitsize']
                             g_register_infos.append(reg_info)
-                        
+                    print 'XML for "%s":' % (data[2])
+                    ET.dump(xml_root)
     
 def cmd_query_packet(options, cmd, args):
     if args:
-        print "query: %s, args: %s" % (cmd, args)
+        print "%s%s" % (cmd, args)
     else:
-        print "query: %s" % (cmd)
-
+        print "%s" % (cmd)
+    return False
+    
 def rsp_ok_error(rsp):
     print "rsp: ", rsp
 
@@ -584,6 +644,7 @@ def dump_key_value_pairs(key_value_pairs
 
 def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
     if rsp:
+        print '%s response:' % (cmd)
         packet = Packet(rsp)
         key_value_pairs = packet.get_key_value_pairs()
         dump_key_value_pairs(key_value_pairs)
@@ -592,9 +653,11 @@ def rsp_dump_key_value_pairs(options, cm
 
 def cmd_c(options, cmd, args):
     print "continue()"
+    return False
 
 def cmd_s(options, cmd, args):
     print "step()"
+    return False
     
 def cmd_vCont(options, cmd, args):
     if args == '?':
@@ -626,6 +689,7 @@ def cmd_vCont(options, cmd, args):
             print "extended_continue (%s)" % (s)
         else:
             print "extended_continue (%s, other-threads: suspend)" % (s)
+    return False
 
 def rsp_vCont(options, cmd, cmd_args, rsp):
     if cmd_args == '?':
@@ -663,10 +727,13 @@ def cmd_vAttach(options, cmd, args):
     if extra_command:
         print "%s%s(%s)" % (cmd, extra_command, args)
     else:
-        print "attach_pid(%s)" % args
+        print "attach(pid = %u)" % int(args, 16)
+    return False
+    
 
 def cmd_qRegisterInfo(options, cmd, args):
     print 'query_register_info(reg_num=%i)' % (int(args, 16))
+    return False
 
 def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
     global g_max_register_info_name_len
@@ -683,7 +750,7 @@ def rsp_qRegisterInfo(options, cmd, cmd_
         reg_info = RegisterInfo(packet.get_key_value_pairs())
         g_register_infos.append(reg_info)
         print reg_info
-        
+    return False
 
 def cmd_qThreadInfo(options, cmd, args):
     if cmd == 'qfThreadInfo':
@@ -691,6 +758,7 @@ def cmd_qThreadInfo(options, cmd, args):
     else: 
         query_type = 'subsequent'
     print 'get_current_thread_list(type=%s)' % (query_type)
+    return False
 
 def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
     packet = Packet(rsp)
@@ -710,12 +778,31 @@ def rsp_hex_big_endian(options, cmd, cmd
     uval = packet.get_hex_uint('big')
     print '%s: 0x%x' % (cmd, uval)
 
+def cmd_read_mem_bin(options, cmd, args):
+    # x0x7fff5fc39200,0x200
+    packet = Packet(args)
+    addr = packet.get_number()
+    comma = packet.get_char()
+    size = packet.get_number()
+    print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
+    return False
+
+def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp):
+    packet = Packet(cmd_args)
+    addr = packet.get_number()
+    comma = packet.get_char()
+    size = packet.get_number()
+    print 'memory:'
+    if size > 0:
+        dump_hex_memory_buffer (addr, rsp) 
+
 def cmd_read_memory(options, cmd, args):
     packet = Packet(args)
     addr = packet.get_hex_uint('big')
     comma = packet.get_char()
     size = packet.get_hex_uint('big')
-    print 'read_memory (addr = 0x%x, size = %u)' % (addr, size)
+    print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
+    return False
 
 def dump_hex_memory_buffer(addr, hex_byte_str):
     packet = Packet(hex_byte_str)
@@ -749,8 +836,9 @@ def cmd_write_memory(options, cmd, args)
     if packet.get_char() != ':':
         print 'error: invalid write memory command (missing colon after size)'
         return
-    print 'write_memory (addr = 0x%x, size = %u, data:' % (addr, size)
+    print 'write_memory (addr = 0x%16.16x, size = %u, data:' % (addr, size)
     dump_hex_memory_buffer (addr, packet.str) 
+    return False
 
 def cmd_alloc_memory(options, cmd, args):
     packet = Packet(args)
@@ -759,6 +847,7 @@ def cmd_alloc_memory(options, cmd, args)
         print 'error: invalid allocate memory command (missing comma after address)'
         return
     print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)
+    return False
 
 def rsp_alloc_memory(options, cmd, cmd_args, rsp):
     packet = Packet(rsp)
@@ -770,9 +859,9 @@ def cmd_dealloc_memory(options, cmd, arg
     addr = packet.get_hex_uint('big')
     if packet.get_char() != ',':
         print 'error: invalid allocate memory command (missing comma after address)'
-        return
-    print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
-
+    else:
+        print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
+    return False
 def rsp_memory_bytes(options, cmd, cmd_args, rsp):
     addr = Packet(cmd_args).get_hex_uint('big')
     dump_hex_memory_buffer (addr, rsp) 
@@ -813,6 +902,7 @@ def cmd_read_one_reg(options, cmd, args)
         s += ', tid = 0x%4.4x' % (tid)
     s += ')'
     print s
+    return False
 
 def rsp_read_one_reg(options, cmd, cmd_args, rsp):
     packet = Packet(cmd_args)
@@ -837,6 +927,7 @@ def cmd_write_one_reg(options, cmd, args
             s += ', tid = 0x%4.4x' % (tid)
         s += ')'
         print s
+    return False
 
 def dump_all_regs(packet):
     for reg_info in g_register_infos:
@@ -856,6 +947,7 @@ def cmd_read_all_regs(cmd, cmd_args):
         print 'read_all_register(thread = 0x%4.4x)' % tid
     else:
         print 'read_all_register()'
+    return False
 
 def rsp_read_all_regs(options, cmd, cmd_args, rsp):
     packet = Packet(rsp)
@@ -865,6 +957,7 @@ def cmd_write_all_regs(options, cmd, arg
     packet = Packet(args)
     print 'write_all_registers()'
     dump_all_regs (packet)
+    return False
     
 g_bp_types = [ "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ]
 
@@ -882,15 +975,18 @@ def cmd_bp(options, cmd, args):
     s += g_bp_types[bp_type]
     s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size)
     print s
+    return False
 
 def cmd_mem_rgn_info(options, cmd, args):
     packet = Packet(args)
     packet.get_char() # skip ':' character
     addr = packet.get_hex_uint('big')
     print 'get_memory_region_info (addr=0x%x)' % (addr)
+    return False
 
 def cmd_kill(options, cmd, args):
     print 'kill_process()'
+    return False
 
 gdb_remote_commands = {
     '\\?'                     : { 'cmd' : cmd_stop_reply    , 'rsp' : rsp_stop_reply          , 'name' : "stop reply pacpket"},
@@ -912,6 +1008,9 @@ gdb_remote_commands = {
     'qProcessInfo'            : { 'cmd' : cmd_query_packet  , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get process info" },
     'qSupported'              : { 'cmd' : cmd_query_packet  , 'rsp' : rsp_ok_means_supported  , 'name' : "query supported" },
     'qXfer:'                  : { 'cmd' : cmd_qXfer         , 'rsp' : rsp_qXfer               , 'name' : "qXfer" },
+    'qSymbol:'                : { 'cmd' : cmd_qSymbol       , 'rsp' : rsp_qSymbol             , 'name' : "qSymbol" },
+    'x'                       : { 'cmd' : cmd_read_mem_bin  , 'rsp' : rsp_mem_bin_bytes       , 'name' : "read memory binary" },
+    'X'                       : { 'cmd' : cmd_write_memory  , 'rsp' : rsp_ok_means_success    , 'name' : "write memory binary" },
     'm'                       : { 'cmd' : cmd_read_memory   , 'rsp' : rsp_memory_bytes        , 'name' : "read memory" },
     'M'                       : { 'cmd' : cmd_write_memory  , 'rsp' : rsp_ok_means_success    , 'name' : "write memory" },
     '_M'                      : { 'cmd' : cmd_alloc_memory  , 'rsp' : rsp_alloc_memory        , 'name' : "allocate memory" },
@@ -943,7 +1042,7 @@ def calculate_mean_and_standard_deviatio
 
 def parse_gdb_log_file(path, options):
     f = open(path)
-    parse_gdb_log(f)
+    parse_gdb_log(f, options)
     f.close()
     
 def parse_gdb_log(file, options):
@@ -974,6 +1073,7 @@ def parse_gdb_log(file, options):
     last_command = None
     last_command_args = None
     last_command_packet = None
+    hide_next_response = False
     for line in lines:
         m = packet_transmit_name_regex.search(line)
         is_command = False
@@ -983,12 +1083,16 @@ def parse_gdb_log(file, options):
             is_command = direction == 'send'
             packet = m.group('packet')
             sys.stdout.write(options.colors.green())
-            if not options.quiet:
+            if not options.quiet and not hide_next_response:
                 print '#  ', line
             sys.stdout.write(options.colors.reset())
                 
             #print 'direction = "%s", packet = "%s"' % (direction, packet)
             
+            if is_command:
+                print '-->',
+            else:
+                print '<--',
             if packet[0] == '+':
                 if not options.quiet: print 'ACK'
                 continue
@@ -1000,13 +1104,14 @@ def parse_gdb_log(file, options):
                 if m:
                     contents = m.group(1)
                     if is_command:
+                        hide_next_response = False
                         m = packet_names_regex.match (contents)
                         if m:
                             last_command = m.group(1)
                             packet_name = last_command
                             last_command_args = m.group(2)
                             last_command_packet = contents
-                            gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args)
+                            hide_next_response = gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args)
                         else:
                             packet_match = packet_name_regex.match (contents)
                             if packet_match:
@@ -1056,7 +1161,8 @@ def parse_gdb_log(file, options):
         # else:
         #     print line
     (average, std_dev) = calculate_mean_and_standard_deviation(packet_times)
-    print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev)
+    if average and std_dev:
+        print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev)
     if packet_total_times:
         total_packet_time = 0.0
         total_packet_count = 0





More information about the lldb-commits mailing list