Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1370e51

Browse files
author
Greg Clayton
committedSep 27, 2018
Fixes for GDB remote packet disassembler:
- Add latency timings to GDB packet log summary if timestamps are on log - Add the ability to plot the latencies for each packet type with --plot - Don't crash the script when target xml register info is in wierd format git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@343243 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8068b5c commit 1370e51

File tree

1 file changed

+131
-59
lines changed

1 file changed

+131
-59
lines changed
 

‎examples/python/gdbremote.py

+131-59
Original file line numberDiff line numberDiff line change
@@ -685,32 +685,33 @@ def rsp_qXfer(options, cmd, cmd_args, rsp):
685685
if extension == '.xml':
686686
response = Packet(rsp)
687687
xml_string = response.get_hex_ascii_str()
688-
ch = xml_string[0]
689-
if ch == 'l':
690-
xml_string = xml_string[1:]
691-
xml_root = ET.fromstring(xml_string)
692-
for reg_element in xml_root.findall("./feature/reg"):
693-
if not 'value_regnums' in reg_element.attrib:
694-
reg_info = RegisterInfo([])
695-
if 'name' in reg_element.attrib:
696-
reg_info.info[
697-
'name'] = reg_element.attrib['name']
698-
else:
699-
reg_info.info['name'] = 'unspecified'
700-
if 'encoding' in reg_element.attrib:
701-
reg_info.info['encoding'] = reg_element.attrib[
702-
'encoding']
703-
else:
704-
reg_info.info['encoding'] = 'uint'
705-
if 'offset' in reg_element.attrib:
706-
reg_info.info[
707-
'offset'] = reg_element.attrib['offset']
708-
if 'bitsize' in reg_element.attrib:
709-
reg_info.info[
710-
'bitsize'] = reg_element.attrib['bitsize']
711-
g_register_infos.append(reg_info)
712-
print 'XML for "%s":' % (data[2])
713-
ET.dump(xml_root)
688+
if xml_string:
689+
ch = xml_string[0]
690+
if ch == 'l':
691+
xml_string = xml_string[1:]
692+
xml_root = ET.fromstring(xml_string)
693+
for reg_element in xml_root.findall("./feature/reg"):
694+
if not 'value_regnums' in reg_element.attrib:
695+
reg_info = RegisterInfo([])
696+
if 'name' in reg_element.attrib:
697+
reg_info.info[
698+
'name'] = reg_element.attrib['name']
699+
else:
700+
reg_info.info['name'] = 'unspecified'
701+
if 'encoding' in reg_element.attrib:
702+
reg_info.info['encoding'] = reg_element.attrib[
703+
'encoding']
704+
else:
705+
reg_info.info['encoding'] = 'uint'
706+
if 'offset' in reg_element.attrib:
707+
reg_info.info[
708+
'offset'] = reg_element.attrib['offset']
709+
if 'bitsize' in reg_element.attrib:
710+
reg_info.info[
711+
'bitsize'] = reg_element.attrib['bitsize']
712+
g_register_infos.append(reg_info)
713+
print 'XML for "%s":' % (data[2])
714+
ET.dump(xml_root)
714715

715716

716717
def cmd_A(options, cmd, args):
@@ -810,6 +811,14 @@ def cmd_s(options, cmd, args):
810811
return False
811812

812813

814+
def cmd_qSpeedTest(options, cmd, args):
815+
print("qSpeedTest: cmd='%s', args='%s'" % (cmd, args))
816+
817+
818+
def rsp_qSpeedTest(options, cmd, cmd_args, rsp):
819+
print("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp, cmd, args))
820+
821+
813822
def cmd_vCont(options, cmd, args):
814823
if args == '?':
815824
print "%s: get supported extended continue modes" % (cmd)
@@ -861,8 +870,10 @@ def rsp_vCont(options, cmd, cmd_args, rsp):
861870
s += 'step'
862871
elif mode == 'S':
863872
s += 'step with signal'
864-
else:
865-
s += 'unrecognized vCont mode: ', mode
873+
elif mode == 't':
874+
s += 'stop'
875+
# else:
876+
# s += 'unrecognized vCont mode: ', str(mode)
866877
print s
867878
elif rsp:
868879
if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X':
@@ -933,7 +944,7 @@ def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
933944
def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
934945
if rsp == '':
935946
print "%s%s is not supported" % (cmd, cmd_args)
936-
else:
947+
else:
937948
packet = Packet(rsp)
938949
uval = packet.get_hex_uint('big')
939950
print '%s: 0x%x' % (cmd, uval)
@@ -1225,6 +1236,7 @@ def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp):
12251236
'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"},
12261237
'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"},
12271238
'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"},
1239+
'qSpeedTest': {'cmd':cmd_qSpeedTest, 'rsp': rsp_qSpeedTest, 'name': 'speed test packdet'},
12281240
'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"},
12291241
'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"},
12301242
's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"},
@@ -1283,6 +1295,49 @@ def parse_gdb_log_file(path, options):
12831295
f.close()
12841296

12851297

1298+
def round_up(n, incr):
1299+
return float(((int(n) + incr) / incr) * incr)
1300+
1301+
1302+
def plot_latencies(sec_times):
1303+
# import numpy as np
1304+
import matplotlib.pyplot as plt
1305+
1306+
for (i, name) in enumerate(sec_times.keys()):
1307+
times = sec_times[name]
1308+
if len(times) <= 1:
1309+
continue
1310+
plt.subplot(2, 1, 1)
1311+
plt.title('Packet "%s" Times' % (name))
1312+
plt.xlabel('Packet')
1313+
units = 'ms'
1314+
adj_times = []
1315+
max_time = 0.0
1316+
for time in times:
1317+
time = time * 1000.0
1318+
adj_times.append(time)
1319+
if time > max_time:
1320+
max_time = time
1321+
if max_time < 1.0:
1322+
units = 'us'
1323+
max_time = 0.0
1324+
for i in range(len(adj_times)):
1325+
adj_times[i] *= 1000.0
1326+
if adj_times[i] > max_time:
1327+
max_time = adj_times[i]
1328+
plt.ylabel('Time (%s)' % (units))
1329+
max_y = None
1330+
for i in [5.0, 10.0, 25.0, 50.0]:
1331+
if max_time < i:
1332+
max_y = round_up(max_time, i)
1333+
break
1334+
if max_y is None:
1335+
max_y = round_up(max_time, 100.0)
1336+
plt.ylim(0.0, max_y)
1337+
plt.plot(adj_times, 'o-')
1338+
plt.show()
1339+
1340+
12861341
def parse_gdb_log(file, options):
12871342
'''Parse a GDB log file that was generated by enabling logging with:
12881343
(lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
@@ -1306,10 +1361,11 @@ def parse_gdb_log(file, options):
13061361

13071362
base_time = 0.0
13081363
last_time = 0.0
1309-
packet_send_time = 0.0
1364+
min_time = 100000000.0
13101365
packet_total_times = {}
1311-
packet_times = []
1312-
packet_count = {}
1366+
all_packet_times = []
1367+
packet_times = {}
1368+
packet_counts = {}
13131369
lines = file.read().splitlines()
13141370
last_command = None
13151371
last_command_args = None
@@ -1412,32 +1468,39 @@ def parse_gdb_log(file, options):
14121468
curr_time = float(match.group(2))
14131469
if last_time and not is_command:
14141470
delta = curr_time - last_time
1415-
packet_times.append(delta)
1471+
all_packet_times.append(delta)
14161472
delta = 0.0
14171473
if base_time:
14181474
delta = curr_time - last_time
14191475
else:
14201476
base_time = curr_time
14211477

1422-
if is_command:
1423-
packet_send_time = curr_time
1424-
elif line.find('read packet: $') >= 0 and packet_name:
1425-
if packet_name in packet_total_times:
1426-
packet_total_times[packet_name] += delta
1427-
packet_count[packet_name] += 1
1428-
else:
1429-
packet_total_times[packet_name] = delta
1430-
packet_count[packet_name] = 1
1431-
packet_name = None
1478+
if not is_command:
1479+
if line.find('read packet: $') >= 0 and packet_name:
1480+
if packet_name in packet_total_times:
1481+
packet_total_times[packet_name] += delta
1482+
packet_counts[packet_name] += 1
1483+
else:
1484+
packet_total_times[packet_name] = delta
1485+
packet_counts[packet_name] = 1
1486+
if packet_name not in packet_times:
1487+
packet_times[packet_name] = []
1488+
packet_times[packet_name].append(delta)
1489+
packet_name = None
1490+
if min_time > delta:
1491+
min_time = delta
14321492

14331493
if not options or not options.quiet:
1434-
print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
1494+
print '%s%.6f %+.6f%s' % (match.group(1),
1495+
curr_time - base_time,
1496+
delta,
1497+
match.group(3))
14351498
last_time = curr_time
14361499
# else:
14371500
# print line
1438-
(average, std_dev) = calculate_mean_and_standard_deviation(packet_times)
1501+
(average, std_dev) = calculate_mean_and_standard_deviation(all_packet_times)
14391502
if average and std_dev:
1440-
print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev)
1503+
print '%u packets with average packet time of %f and standard deviation of %f' % (len(all_packet_times), average, std_dev)
14411504
if packet_total_times:
14421505
total_packet_time = 0.0
14431506
total_packet_count = 0
@@ -1446,19 +1509,21 @@ def parse_gdb_log(file, options):
14461509
# print 'value = (%s) %s' % (type(vvv), vvv)
14471510
# if type(vvv) == 'float':
14481511
total_packet_time += vvv
1449-
for key, vvv in packet_count.items():
1512+
for key, vvv in packet_counts.items():
14501513
total_packet_count += vvv
14511514

1452-
print '#---------------------------------------------------'
1515+
print '#------------------------------------------------------------'
14531516
print '# Packet timing summary:'
1454-
print '# Totals: time = %6f, count = %6d' % (total_packet_time, total_packet_count)
1455-
print '#---------------------------------------------------'
1456-
print '# Packet Time (sec) Percent Count '
1457-
print '#------------------------- ---------- ------- ------'
1517+
print '# Totals: time = %6f, count = %6d' % (total_packet_time,
1518+
total_packet_count)
1519+
print '# Min packet time: time = %6f' % (min_time)
1520+
print '#------------------------------------------------------------'
1521+
print '# Packet Time (sec) Percent Count Latency'
1522+
print '#------------------------- ----------- ------- ------ -------'
14581523
if options and options.sort_count:
14591524
res = sorted(
1460-
packet_count,
1461-
key=packet_count.__getitem__,
1525+
packet_counts,
1526+
key=packet_counts.__getitem__,
14621527
reverse=True)
14631528
else:
14641529
res = sorted(
@@ -1471,11 +1536,12 @@ def parse_gdb_log(file, options):
14711536
packet_total_time = packet_total_times[item]
14721537
packet_percent = (
14731538
packet_total_time / total_packet_time) * 100.0
1474-
if packet_percent >= 10.0:
1475-
print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
1476-
else:
1477-
print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
1478-
1539+
packet_count = packet_counts[item]
1540+
print " %24s %11.6f %5.2f%% %6d %9.6f" % (
1541+
item, packet_total_time, packet_percent, packet_count,
1542+
float(packet_total_time) / float(packet_count))
1543+
if options.plot:
1544+
plot_latencies(packet_times)
14791545

14801546
if __name__ == '__main__':
14811547
usage = "usage: gdbremote [options]"
@@ -1491,6 +1557,12 @@ def parse_gdb_log(file, options):
14911557
dest='verbose',
14921558
help='display verbose debug info',
14931559
default=False)
1560+
parser.add_option(
1561+
'--plot',
1562+
action='store_true',
1563+
dest='plot',
1564+
help='plot packet latencies by packet type',
1565+
default=False)
14941566
parser.add_option(
14951567
'-q',
14961568
'--quiet',

0 commit comments

Comments
 (0)
This repository has been archived.