Added support for dumping 'x', 'X', 'qSymbol' packets. Also dump any XML retrieved from a qXfer packets.

llvm-svn: 242566
This commit is contained in:
Greg Clayton 2015-07-17 20:16:50 +00:00
parent 546a19628b
commit 205d6189b4
1 changed files with 121 additions and 15 deletions

View File

@ -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_args, rsp):
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, args):
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, rsp):
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, cmd, cmd_args, rsp):
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_args, rsp):
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_args, rsp):
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, args):
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, args):
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_deviation(floats):
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