diff options
Diffstat (limited to 'scripts/disasm-gdb-remote.pl')
-rwxr-xr-x | scripts/disasm-gdb-remote.pl | 2283 |
1 files changed, 0 insertions, 2283 deletions
diff --git a/scripts/disasm-gdb-remote.pl b/scripts/disasm-gdb-remote.pl deleted file mode 100755 index e4c7066ff21f..000000000000 --- a/scripts/disasm-gdb-remote.pl +++ /dev/null @@ -1,2283 +0,0 @@ -#!/usr/bin/perl - -use strict; - -#---------------------------------------------------------------------- -# Globals -#---------------------------------------------------------------------- -our $unimplemented_str = "UNIMPLEMENTED"; -our $success_str = "OK"; -our $swap = 1; -our $addr_size = 4; -our $thread_suffix_supported = 0; -our $max_bytes_per_line = 32; -our $addr_format = sprintf("0x%%%u.%ux", $addr_size*2, $addr_size*2); -our $pid_format = "%04.4x"; -our $tid_format = "%04.4x"; -our $reg8_href = { extract => \&get8, format => "0x%2.2x" }; -our $reg16_href = { extract => \&get16, format => "0x%4.4x" }; -our $reg32_href = { extract => \&get32, format => "0x%8.8x" }; -our $reg64_href = { extract => \&get64, format => "0x%s" }; -our $reg80_href = { extract => \&get80, format => "0x%s" }; -our $reg128_href = { extract => \&get128, format => "0x%s" }; -our $reg256_href = { extract => \&get256, format => "0x%s" }; -our $float32_href = { extract => \&get32, format => "0x%8.8x" }; -our $float64_href = { extract => \&get64, format => "0x%s" }; -our $float96_href = { extract => \&get96, format => "0x%s" }; -our $curr_cmd = undef; -our $curr_full_cmd = undef; -our %packet_times; -our $curr_time = 0.0; -our $last_time = 0.0; -our $base_time = 0.0; -our $packet_start_time = 0.0; -our $reg_cmd_reg; -our %reg_map = ( - 'i386-gdb' => [ - { name => 'eax', info => $reg32_href }, - { name => 'ecx', info => $reg32_href }, - { name => 'edx', info => $reg32_href }, - { name => 'ebx', info => $reg32_href }, - { name => 'esp', info => $reg32_href }, - { name => 'ebp', info => $reg32_href }, - { name => 'esi', info => $reg32_href }, - { name => 'edi', info => $reg32_href }, - { name => 'eip', info => $reg32_href }, - { name => 'eflags', info => $reg32_href }, - { name => 'cs', info => $reg32_href }, - { name => 'ss', info => $reg32_href }, - { name => 'ds', info => $reg32_href }, - { name => 'es', info => $reg32_href }, - { name => 'fs', info => $reg32_href }, - { name => 'gs', info => $reg32_href }, - { name => 'st0', info => $reg80_href }, - { name => 'st1', info => $reg80_href }, - { name => 'st2', info => $reg80_href }, - { name => 'st3', info => $reg80_href }, - { name => 'st4', info => $reg80_href }, - { name => 'st5', info => $reg80_href }, - { name => 'st6', info => $reg80_href }, - { name => 'st7', info => $reg80_href }, - { name => 'fctrl', info => $reg32_href }, - { name => 'fstat', info => $reg32_href }, - { name => 'ftag', info => $reg32_href }, - { name => 'fiseg', info => $reg32_href }, - { name => 'fioff', info => $reg32_href }, - { name => 'foseg', info => $reg32_href }, - { name => 'fooff', info => $reg32_href }, - { name => 'fop', info => $reg32_href }, - { name => 'xmm0', info => $reg128_href }, - { name => 'xmm1', info => $reg128_href }, - { name => 'xmm2', info => $reg128_href }, - { name => 'xmm3', info => $reg128_href }, - { name => 'xmm4', info => $reg128_href }, - { name => 'xmm5', info => $reg128_href }, - { name => 'xmm6', info => $reg128_href }, - { name => 'xmm7', info => $reg128_href }, - { name => 'mxcsr', info => $reg32_href }, - { name => 'mm0', info => $reg64_href }, - { name => 'mm1', info => $reg64_href }, - { name => 'mm2', info => $reg64_href }, - { name => 'mm3', info => $reg64_href }, - { name => 'mm4', info => $reg64_href }, - { name => 'mm5', info => $reg64_href }, - { name => 'mm6', info => $reg64_href }, - { name => 'mm7', info => $reg64_href }, - ], - - 'i386-lldb' => [ - { name => 'eax', info => $reg32_href }, - { name => 'ebx', info => $reg32_href }, - { name => 'ecx', info => $reg32_href }, - { name => 'edx', info => $reg32_href }, - { name => 'edi', info => $reg32_href }, - { name => 'esi', info => $reg32_href }, - { name => 'ebp', info => $reg32_href }, - { name => 'esp', info => $reg32_href }, - { name => 'ss', info => $reg32_href }, - { name => 'eflags', info => $reg32_href }, - { name => 'eip', info => $reg32_href }, - { name => 'cs', info => $reg32_href }, - { name => 'ds', info => $reg32_href }, - { name => 'es', info => $reg32_href }, - { name => 'fs', info => $reg32_href }, - { name => 'gs', info => $reg32_href }, - { name => 'fctrl', info => $reg16_href }, - { name => 'fstat', info => $reg16_href }, - { name => 'ftag', info => $reg8_href }, - { name => 'fop', info => $reg16_href }, - { name => 'fioff', info => $reg32_href }, - { name => 'fiseg', info => $reg16_href }, - { name => 'fooff', info => $reg32_href }, - { name => 'foseg', info => $reg16_href }, - { name => 'mxcsr', info => $reg32_href }, - { name => 'mxcsrmask', info => $reg32_href }, - { name => 'stmm0', info => $reg80_href }, - { name => 'stmm1', info => $reg80_href }, - { name => 'stmm2', info => $reg80_href }, - { name => 'stmm3', info => $reg80_href }, - { name => 'stmm4', info => $reg80_href }, - { name => 'stmm5', info => $reg80_href }, - { name => 'stmm6', info => $reg80_href }, - { name => 'stmm7', info => $reg80_href }, - { name => 'xmm0', info => $reg128_href }, - { name => 'xmm1', info => $reg128_href }, - { name => 'xmm2', info => $reg128_href }, - { name => 'xmm3', info => $reg128_href }, - { name => 'xmm4', info => $reg128_href }, - { name => 'xmm5', info => $reg128_href }, - { name => 'xmm6', info => $reg128_href }, - { name => 'xmm7', info => $reg128_href }, - { name => 'trapno', info => $reg32_href }, - { name => 'err', info => $reg32_href }, - { name => 'faultvaddr', info => $reg32_href }, - ], - - 'arm-gdb' => [ - { name => 'r0' , info => $reg32_href }, - { name => 'r1' , info => $reg32_href }, - { name => 'r2' , info => $reg32_href }, - { name => 'r3' , info => $reg32_href }, - { name => 'r4' , info => $reg32_href }, - { name => 'r5' , info => $reg32_href }, - { name => 'r6' , info => $reg32_href }, - { name => 'r7' , info => $reg32_href }, - { name => 'r8' , info => $reg32_href }, - { name => 'r9' , info => $reg32_href }, - { name => 'r10' , info => $reg32_href }, - { name => 'r11' , info => $reg32_href }, - { name => 'r12' , info => $reg32_href }, - { name => 'sp' , info => $reg32_href }, - { name => 'lr' , info => $reg32_href }, - { name => 'pc' , info => $reg32_href }, - { name => 'f0' , info => $float96_href }, - { name => 'f1' , info => $float96_href }, - { name => 'f2' , info => $float96_href }, - { name => 'f3' , info => $float96_href }, - { name => 'f4' , info => $float96_href }, - { name => 'f5' , info => $float96_href }, - { name => 'f6' , info => $float96_href }, - { name => 'f7' , info => $float96_href }, - { name => 'fps' , info => $reg32_href }, - { name => 'cpsr' , info => $reg32_href }, - { name => 's0' , info => $float32_href }, - { name => 's1' , info => $float32_href }, - { name => 's2' , info => $float32_href }, - { name => 's3' , info => $float32_href }, - { name => 's4' , info => $float32_href }, - { name => 's5' , info => $float32_href }, - { name => 's6' , info => $float32_href }, - { name => 's7' , info => $float32_href }, - { name => 's8' , info => $float32_href }, - { name => 's9' , info => $float32_href }, - { name => 's10' , info => $float32_href }, - { name => 's11' , info => $float32_href }, - { name => 's12' , info => $float32_href }, - { name => 's13' , info => $float32_href }, - { name => 's14' , info => $float32_href }, - { name => 's15' , info => $float32_href }, - { name => 's16' , info => $float32_href }, - { name => 's17' , info => $float32_href }, - { name => 's18' , info => $float32_href }, - { name => 's19' , info => $float32_href }, - { name => 's20' , info => $float32_href }, - { name => 's21' , info => $float32_href }, - { name => 's22' , info => $float32_href }, - { name => 's23' , info => $float32_href }, - { name => 's24' , info => $float32_href }, - { name => 's25' , info => $float32_href }, - { name => 's26' , info => $float32_href }, - { name => 's27' , info => $float32_href }, - { name => 's28' , info => $float32_href }, - { name => 's29' , info => $float32_href }, - { name => 's30' , info => $float32_href }, - { name => 's31' , info => $float32_href }, - { name => 'fpscr' , info => $reg32_href }, - { name => 'd16' , info => $float64_href }, - { name => 'd17' , info => $float64_href }, - { name => 'd18' , info => $float64_href }, - { name => 'd19' , info => $float64_href }, - { name => 'd20' , info => $float64_href }, - { name => 'd21' , info => $float64_href }, - { name => 'd22' , info => $float64_href }, - { name => 'd23' , info => $float64_href }, - { name => 'd24' , info => $float64_href }, - { name => 'd25' , info => $float64_href }, - { name => 'd26' , info => $float64_href }, - { name => 'd27' , info => $float64_href }, - { name => 'd28' , info => $float64_href }, - { name => 'd29' , info => $float64_href }, - { name => 'd30' , info => $float64_href }, - { name => 'd31' , info => $float64_href }, - ], - - - 'arm-lldb' => [ - { name => 'r0' , info => $reg32_href }, - { name => 'r1' , info => $reg32_href }, - { name => 'r2' , info => $reg32_href }, - { name => 'r3' , info => $reg32_href }, - { name => 'r4' , info => $reg32_href }, - { name => 'r5' , info => $reg32_href }, - { name => 'r6' , info => $reg32_href }, - { name => 'r7' , info => $reg32_href }, - { name => 'r8' , info => $reg32_href }, - { name => 'r9' , info => $reg32_href }, - { name => 'r10' , info => $reg32_href }, - { name => 'r11' , info => $reg32_href }, - { name => 'r12' , info => $reg32_href }, - { name => 'sp' , info => $reg32_href }, - { name => 'lr' , info => $reg32_href }, - { name => 'pc' , info => $reg32_href }, - { name => 'cpsr' , info => $reg32_href }, - { name => 's0' , info => $float32_href }, - { name => 's1' , info => $float32_href }, - { name => 's2' , info => $float32_href }, - { name => 's3' , info => $float32_href }, - { name => 's4' , info => $float32_href }, - { name => 's5' , info => $float32_href }, - { name => 's6' , info => $float32_href }, - { name => 's7' , info => $float32_href }, - { name => 's8' , info => $float32_href }, - { name => 's9' , info => $float32_href }, - { name => 's10' , info => $float32_href }, - { name => 's11' , info => $float32_href }, - { name => 's12' , info => $float32_href }, - { name => 's13' , info => $float32_href }, - { name => 's14' , info => $float32_href }, - { name => 's15' , info => $float32_href }, - { name => 's16' , info => $float32_href }, - { name => 's17' , info => $float32_href }, - { name => 's18' , info => $float32_href }, - { name => 's19' , info => $float32_href }, - { name => 's20' , info => $float32_href }, - { name => 's21' , info => $float32_href }, - { name => 's22' , info => $float32_href }, - { name => 's23' , info => $float32_href }, - { name => 's24' , info => $float32_href }, - { name => 's25' , info => $float32_href }, - { name => 's26' , info => $float32_href }, - { name => 's27' , info => $float32_href }, - { name => 's28' , info => $float32_href }, - { name => 's29' , info => $float32_href }, - { name => 's30' , info => $float32_href }, - { name => 's31' , info => $float32_href }, - { name => 'd0' , info => $float64_href }, - { name => 'd1' , info => $float64_href }, - { name => 'd2' , info => $float64_href }, - { name => 'd3' , info => $float64_href }, - { name => 'd4' , info => $float64_href }, - { name => 'd5' , info => $float64_href }, - { name => 'd6' , info => $float64_href }, - { name => 'd7' , info => $float64_href }, - { name => 'd8' , info => $float64_href }, - { name => 'd9' , info => $float64_href }, - { name => 'd10' , info => $float64_href }, - { name => 'd11' , info => $float64_href }, - { name => 'd12' , info => $float64_href }, - { name => 'd13' , info => $float64_href }, - { name => 'd14' , info => $float64_href }, - { name => 'd15' , info => $float64_href }, - { name => 'd16' , info => $float64_href }, - { name => 'd17' , info => $float64_href }, - { name => 'd18' , info => $float64_href }, - { name => 'd19' , info => $float64_href }, - { name => 'd20' , info => $float64_href }, - { name => 'd21' , info => $float64_href }, - { name => 'd22' , info => $float64_href }, - { name => 'd23' , info => $float64_href }, - { name => 'd24' , info => $float64_href }, - { name => 'd25' , info => $float64_href }, - { name => 'd26' , info => $float64_href }, - { name => 'd27' , info => $float64_href }, - { name => 'd28' , info => $float64_href }, - { name => 'd29' , info => $float64_href }, - { name => 'd30' , info => $float64_href }, - { name => 'd31' , info => $float64_href }, - { name => 'fpscr' , info => $reg32_href }, - { name => 'exc' , info => $reg32_href }, - { name => 'fsr' , info => $reg32_href }, - { name => 'far' , info => $reg32_href }, - ], - - 'x86_64-gdb' => [ - { name => 'rax' , info => $reg64_href }, - { name => 'rbx' , info => $reg64_href }, - { name => 'rcx' , info => $reg64_href }, - { name => 'rdx' , info => $reg64_href }, - { name => 'rsi' , info => $reg64_href }, - { name => 'rdi' , info => $reg64_href }, - { name => 'rbp' , info => $reg64_href }, - { name => 'rsp' , info => $reg64_href }, - { name => 'r8' , info => $reg64_href }, - { name => 'r9' , info => $reg64_href }, - { name => 'r10' , info => $reg64_href }, - { name => 'r11' , info => $reg64_href }, - { name => 'r12' , info => $reg64_href }, - { name => 'r13' , info => $reg64_href }, - { name => 'r14' , info => $reg64_href }, - { name => 'r15' , info => $reg64_href }, - { name => 'rip' , info => $reg64_href }, - { name => 'eflags' , info => $reg32_href }, - { name => 'cs' , info => $reg32_href }, - { name => 'ss' , info => $reg32_href }, - { name => 'ds' , info => $reg32_href }, - { name => 'es' , info => $reg32_href }, - { name => 'fs' , info => $reg32_href }, - { name => 'gs' , info => $reg32_href }, - { name => 'stmm0' , info => $reg80_href }, - { name => 'stmm1' , info => $reg80_href }, - { name => 'stmm2' , info => $reg80_href }, - { name => 'stmm3' , info => $reg80_href }, - { name => 'stmm4' , info => $reg80_href }, - { name => 'stmm5' , info => $reg80_href }, - { name => 'stmm6' , info => $reg80_href }, - { name => 'stmm7' , info => $reg80_href }, - { name => 'fctrl' , info => $reg32_href }, - { name => 'fstat' , info => $reg32_href }, - { name => 'ftag' , info => $reg32_href }, - { name => 'fiseg' , info => $reg32_href }, - { name => 'fioff' , info => $reg32_href }, - { name => 'foseg' , info => $reg32_href }, - { name => 'fooff' , info => $reg32_href }, - { name => 'fop' , info => $reg32_href }, - { name => 'xmm0' , info => $reg128_href }, - { name => 'xmm1' , info => $reg128_href }, - { name => 'xmm2' , info => $reg128_href }, - { name => 'xmm3' , info => $reg128_href }, - { name => 'xmm4' , info => $reg128_href }, - { name => 'xmm5' , info => $reg128_href }, - { name => 'xmm6' , info => $reg128_href }, - { name => 'xmm7' , info => $reg128_href }, - { name => 'xmm8' , info => $reg128_href }, - { name => 'xmm9' , info => $reg128_href }, - { name => 'xmm10' , info => $reg128_href }, - { name => 'xmm11' , info => $reg128_href }, - { name => 'xmm12' , info => $reg128_href }, - { name => 'xmm13' , info => $reg128_href }, - { name => 'xmm14' , info => $reg128_href }, - { name => 'xmm15' , info => $reg128_href }, - { name => 'mxcsr' , info => $reg32_href }, - ], - - 'x86_64-lldb' => [ - { name => 'rax' , info => $reg64_href }, - { name => 'rbx' , info => $reg64_href }, - { name => 'rcx' , info => $reg64_href }, - { name => 'rdx' , info => $reg64_href }, - { name => 'rdi' , info => $reg64_href }, - { name => 'rsi' , info => $reg64_href }, - { name => 'rbp' , info => $reg64_href }, - { name => 'rsp' , info => $reg64_href }, - { name => 'r8 ' , info => $reg64_href }, - { name => 'r9 ' , info => $reg64_href }, - { name => 'r10' , info => $reg64_href }, - { name => 'r11' , info => $reg64_href }, - { name => 'r12' , info => $reg64_href }, - { name => 'r13' , info => $reg64_href }, - { name => 'r14' , info => $reg64_href }, - { name => 'r15' , info => $reg64_href }, - { name => 'rip' , info => $reg64_href }, - { name => 'rflags' , info => $reg64_href }, - { name => 'cs' , info => $reg64_href }, - { name => 'fs' , info => $reg64_href }, - { name => 'gs' , info => $reg64_href }, - { name => 'fctrl' , info => $reg16_href }, - { name => 'fstat' , info => $reg16_href }, - { name => 'ftag' , info => $reg8_href }, - { name => 'fop' , info => $reg16_href }, - { name => 'fioff' , info => $reg32_href }, - { name => 'fiseg' , info => $reg16_href }, - { name => 'fooff' , info => $reg32_href }, - { name => 'foseg' , info => $reg16_href }, - { name => 'mxcsr' , info => $reg32_href }, - { name => 'mxcsrmask' , info => $reg32_href }, - { name => 'stmm0' , info => $reg80_href }, - { name => 'stmm1' , info => $reg80_href }, - { name => 'stmm2' , info => $reg80_href }, - { name => 'stmm3' , info => $reg80_href }, - { name => 'stmm4' , info => $reg80_href }, - { name => 'stmm5' , info => $reg80_href }, - { name => 'stmm6' , info => $reg80_href }, - { name => 'stmm7' , info => $reg80_href }, - { name => 'xmm0' , info => $reg128_href }, - { name => 'xmm1' , info => $reg128_href }, - { name => 'xmm2' , info => $reg128_href }, - { name => 'xmm3' , info => $reg128_href }, - { name => 'xmm4' , info => $reg128_href }, - { name => 'xmm5' , info => $reg128_href }, - { name => 'xmm6' , info => $reg128_href }, - { name => 'xmm7' , info => $reg128_href }, - { name => 'xmm8' , info => $reg128_href }, - { name => 'xmm9' , info => $reg128_href }, - { name => 'xmm10' , info => $reg128_href }, - { name => 'xmm11' , info => $reg128_href }, - { name => 'xmm12' , info => $reg128_href }, - { name => 'xmm13' , info => $reg128_href }, - { name => 'xmm14' , info => $reg128_href }, - { name => 'xmm15' , info => $reg128_href }, - { name => 'trapno' , info => $reg32_href }, - { name => 'err' , info => $reg32_href }, - { name => 'faultvaddr' , info => $reg64_href }, - ] -); - -our $max_register_name_len = 0; -calculate_max_register_name_length(); -our @point_types = ( "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ); -our $opt_v = 0; # verbose -our $opt_g = 0; # debug -our $opt_q = 0; # quiet -our $opt_r = undef; -use Getopt::Std; -getopts('gvqr:'); - -our $registers_aref = undef; - -if (length($opt_r)) -{ - if (exists $reg_map{$opt_r}) - { - $registers_aref = $reg_map{$opt_r}; - } - else - { - die "Can't get registers group for '$opt_r'\n"; - } -} - -sub extract_key_value_pairs -{ - my $kv_href = {}; - my $arrayref = shift; - my $str = join('',@$arrayref); - my @kv_strs = split(/;/, $str); - foreach my $kv_str (@kv_strs) - { - my ($key, $value) = split(/:/, $kv_str); - $kv_href->{$key} = $value; - } - return $kv_href; -} - -sub get_thread_from_thread_suffix -{ - if ($thread_suffix_supported) - { - my $arrayref = shift; - # Skip leading semi-colon if needed - $$arrayref[0] == ';' and shift @$arrayref; - my $thread_href = extract_key_value_pairs ($arrayref); - if (exists $thread_href->{thread}) - { - return $thread_href->{thread}; - } - } - return undef; -} - -sub calculate_max_register_name_length -{ - $max_register_name_len = 7; - foreach my $reg_href (@$registers_aref) - { - my $name_len = length($reg_href->{name}); - if ($max_register_name_len < $name_len) - { - $max_register_name_len = $name_len; - } - } -} -#---------------------------------------------------------------------- -# Hash that maps command characters to the appropriate functions using -# the command character as the key and the value being a reference to -# the dump function for dumping the command itself. -#---------------------------------------------------------------------- -our %cmd_callbacks = -( - '?' => \&dump_last_signal_cmd, - 'H' => \&dump_set_thread_cmd, - 'T' => \&dump_thread_is_alive_cmd, - 'q' => \&dump_general_query_cmd, - 'Q' => \&dump_general_set_cmd, - 'g' => \&dump_read_regs_cmd, - 'G' => \&dump_write_regs_cmd, - 'p' => \&dump_read_single_register_cmd, - 'P' => \&dump_write_single_register_cmd, - 'm' => \&dump_read_mem_cmd, - 'M' => \&dump_write_mem_cmd, - 'X' => \&dump_write_mem_binary_cmd, - 'Z' => \&dump_bp_wp_command, - 'z' => \&dump_bp_wp_command, - 'k' => \&dump_kill_cmd, - 'A' => \&dump_A_command, - 'c' => \&dump_continue_cmd, - 's' => \&dump_continue_cmd, - 'C' => \&dump_continue_with_signal_cmd, - 'S' => \&dump_continue_with_signal_cmd, - '_M' => \&dump_allocate_memory_cmd, - '_m' => \&dump_deallocate_memory_cmd, - # extended commands - 'v' => \&dump_extended_cmd -); - -#---------------------------------------------------------------------- -# Hash that maps command characters to the appropriate functions using -# the command character as the key and the value being a reference to -# the dump function for the response to the command. -#---------------------------------------------------------------------- -our %rsp_callbacks = -( - 'c' => \&dump_stop_reply_packet, - 's' => \&dump_stop_reply_packet, - 'C' => \&dump_stop_reply_packet, - '?' => \&dump_stop_reply_packet, - 'T' => \&dump_thread_is_alive_rsp, - 'H' => \&dump_set_thread_rsp, - 'q' => \&dump_general_query_rsp, - 'g' => \&dump_read_regs_rsp, - 'p' => \&dump_read_single_register_rsp, - 'm' => \&dump_read_mem_rsp, - '_M' => \&dump_allocate_memory_rsp, - - # extended commands - 'v' => \&dump_extended_rsp, -); - - -sub dump_register_value -{ - my $indent = shift; - my $arrayref = shift; - my $reg_num = shift; - - if ($reg_num >= @$registers_aref) - { - printf("\tinvalid register index %d\n", $reg_num); - return; - } - - my $reg_href = $$registers_aref[$reg_num]; - my $reg_name = $reg_href->{name}; - if ($$arrayref[0] eq '#') - { - printf("\t%*s: error: EOS reached when trying to read register %d\n", $max_register_name_len, $reg_name, $reg_num); - } - - my $reg_info = $reg_href->{info}; - my $reg_extract = $reg_info->{extract}; - my $reg_format = $reg_info->{format}; - my $reg_val = &$reg_extract($arrayref); - if ($indent) { - printf("\t%*s = $reg_format", $max_register_name_len, $reg_name, $reg_val); - } else { - printf("%s = $reg_format", $reg_name, $reg_val); - } -} - -#---------------------------------------------------------------------- -# Extract the command into an array of ASCII char strings for easy -# processing -#---------------------------------------------------------------------- -sub extract_command -{ - my $cmd_str = shift; - my @cmd_chars = split(/ */, $cmd_str); - if ($cmd_chars[0] ne '$') - { - # only set the current command if it isn't a reply - $curr_cmd = $cmd_chars[0]; - } - return @cmd_chars; -} - -#---------------------------------------------------------------------- -# Strip the 3 checksum array entries after we don't need them anymore -#---------------------------------------------------------------------- -sub strip_checksum -{ - my $arrayref = shift; - splice(@$arrayref, -3); -} - -#---------------------------------------------------------------------- -# Dump all strings in array by joining them together with no space -# between them -#---------------------------------------------------------------------- -sub dump_chars -{ - print join('',@_); -} - -#---------------------------------------------------------------------- -# Check if the response is an error 'EXX' -#---------------------------------------------------------------------- -sub is_error_response -{ - if ($_[0] eq 'E') - { - shift; - print "ERROR = " . join('',@_) . "\n"; - return 1; - } - return 0; -} - -#---------------------------------------------------------------------- -# 'H' command -#---------------------------------------------------------------------- -sub dump_set_thread_cmd -{ - my $cmd = shift; - my $mod = shift; - print "set_thread ( $mod, " . join('',@_) . " )\n"; -} - -#---------------------------------------------------------------------- -# 'T' command -#---------------------------------------------------------------------- -our $T_cmd_tid = -1; -sub dump_thread_is_alive_cmd -{ - my $cmd = shift; - $T_cmd_tid = get_hex(\@_); - printf("thread_is_alive ( $tid_format )\n", $T_cmd_tid); -} - -sub dump_thread_is_alive_rsp -{ - my $rsp = join('',@_); - - printf("thread_is_alive ( $tid_format ) =>", $T_cmd_tid); - if ($rsp eq 'OK') - { - print " alive.\n"; - } - else - { - print " dead.\n"; - } -} - -#---------------------------------------------------------------------- -# 'H' response -#---------------------------------------------------------------------- -sub dump_set_thread_rsp -{ - if (!is_error_response(@_)) - { - print join('',@_) . "\n"; - } -} - -#---------------------------------------------------------------------- -# 'q' command -#---------------------------------------------------------------------- -our $gen_query_cmd; -our $qRegisterInfo_reg_num = -1; -sub dump_general_query_cmd -{ - $gen_query_cmd = join('',@_); - if ($gen_query_cmd eq 'qC') - { - print 'get_current_pid ()'; - } - elsif ($gen_query_cmd eq 'qfThreadInfo') - { - print 'get_first_active_threads ()'; - } - elsif ($gen_query_cmd eq 'qsThreadInfo') - { - print 'get_subsequent_active_threads ()'; - } - elsif (index($gen_query_cmd, 'qThreadExtraInfo') == 0) - { - # qThreadExtraInfo,id - print 'get_thread_extra_info ()'; - } - elsif (index($gen_query_cmd, 'qThreadStopInfo') == 0) - { - # qThreadStopInfoXXXX - @_ = splice(@_, length('qThreadStopInfo')); - my $tid = get_addr(\@_); - printf('get_thread_stop_info ( thread = 0x%4.4x )', $tid); - } - elsif (index($gen_query_cmd, 'qSymbol:') == 0) - { - # qCRC:addr,length - print 'gdb_ready_to_serve_symbol_lookups ()'; - } - elsif (index($gen_query_cmd, 'qCRC:') == 0) - { - # qCRC:addr,length - @_ = splice(@_, length('qCRC:')); - my $address = get_addr(\@_); - shift @_; - my $length = join('', @_); - printf("compute_crc (addr = $addr_format, length = $length)", $address); - } - elsif (index($gen_query_cmd, 'qGetTLSAddr:') == 0) - { - # qGetTLSAddr:thread-id,offset,lm - @_ = splice(@_, length('qGetTLSAddr:')); - my ($tid, $offset, $lm) = split (/,/, join('', @_)); - print "get_thread_local_storage_addr (thread-id = $tid, offset = $offset, lm = $lm)"; - } - elsif ($gen_query_cmd eq 'qOffsets') - { - print 'get_section_offsets ()'; - } - elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) - { - @_ = splice(@_, length('qRegisterInfo')); - $qRegisterInfo_reg_num = get_hex(\@_); - - printf "get_dynamic_register_info ($qRegisterInfo_reg_num)"; - } - else - { - print $gen_query_cmd; - } - print "\n"; -} - -#---------------------------------------------------------------------- -# 'q' response -#---------------------------------------------------------------------- -sub dump_general_query_rsp -{ - my $gen_query_rsp = join('',@_); - my $gen_query_rsp_len = length ($gen_query_rsp); - if ($gen_query_cmd eq 'qC' and index($gen_query_rsp, 'QC') == 0) - { - shift @_; shift @_; - my $pid = get_hex(\@_); - printf("pid = $pid_format\n", $pid); - return; - } - elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) - { - if ($gen_query_rsp_len == 0) - { - print "$unimplemented_str\n"; - } - else - { - if (index($gen_query_rsp, 'name') == 0) - { - $qRegisterInfo_reg_num == 0 and $registers_aref = []; - - my @name_and_values = split (/;/, $gen_query_rsp); - - my $reg_name = undef; - my $byte_size = 0; - my $pseudo = 0; - foreach (@name_and_values) - { - my ($name, $value) = split /:/; - if ($name eq "name") { $reg_name = $value; } - elsif ($name eq "bitsize") { $byte_size = $value / 8; } - elsif ($name eq "container-regs") { $pseudo = 1; } - } - if (defined $reg_name and $byte_size > 0) - { - if ($byte_size == 4) {push @$registers_aref, { name => $reg_name, info => $reg32_href , pseudo => $pseudo };} - elsif ($byte_size == 8) {push @$registers_aref, { name => $reg_name, info => $reg64_href , pseudo => $pseudo };} - elsif ($byte_size == 1) {push @$registers_aref, { name => $reg_name, info => $reg8_href , pseudo => $pseudo };} - elsif ($byte_size == 2) {push @$registers_aref, { name => $reg_name, info => $reg16_href , pseudo => $pseudo };} - elsif ($byte_size == 10) {push @$registers_aref, { name => $reg_name, info => $reg80_href , pseudo => $pseudo };} - elsif ($byte_size == 12) {push @$registers_aref, { name => $reg_name, info => $float96_href , pseudo => $pseudo };} - elsif ($byte_size == 16) {push @$registers_aref, { name => $reg_name, info => $reg128_href , pseudo => $pseudo };} - elsif ($byte_size == 32) {push @$registers_aref, { name => $reg_name, info => $reg256_href , pseudo => $pseudo };} - } - } - elsif ($gen_query_rsp_len == 3 and index($gen_query_rsp, 'E') == 0) - { - calculate_max_register_name_length(); - } - } - } - elsif ($gen_query_cmd =~ 'qThreadStopInfo') - { - dump_stop_reply_packet (@_); - } - if (dump_standard_response(\@_)) - { - # Do nothing... - } - else - { - print join('',@_) . "\n"; - } -} - -#---------------------------------------------------------------------- -# 'Q' command -#---------------------------------------------------------------------- -our $gen_set_cmd; -sub dump_general_set_cmd -{ - $gen_query_cmd = join('',@_); - if ($gen_query_cmd eq 'QStartNoAckMode') - { - print "StartNoAckMode ()" - } - elsif ($gen_query_cmd eq 'QThreadSuffixSupported') - { - $thread_suffix_supported = 1; - print "ThreadSuffixSupported ()" - } - elsif (index($gen_query_cmd, 'QSetMaxPayloadSize:') == 0) - { - @_ = splice(@_, length('QSetMaxPayloadSize:')); - my $max_payload_size = get_hex(\@_); - # QSetMaxPayloadSize:XXXX where XXXX is a hex length of the max - # packet payload size supported by gdb - printf("SetMaxPayloadSize ( 0x%x (%u))", $max_payload_size, $max_payload_size); - } - elsif (index ($gen_query_cmd, 'QSetSTDIN:') == 0) - { - @_ = splice(@_, length('QSetSTDIN:')); - printf ("SetSTDIN (path ='%s')\n", get_hex_string (\@_)); - } - elsif (index ($gen_query_cmd, 'QSetSTDOUT:') == 0) - { - @_ = splice(@_, length('QSetSTDOUT:')); - printf ("SetSTDOUT (path ='%s')\n", get_hex_string (\@_)); - } - elsif (index ($gen_query_cmd, 'QSetSTDERR:') == 0) - { - @_ = splice(@_, length('QSetSTDERR:')); - printf ("SetSTDERR (path ='%s')\n", get_hex_string (\@_)); - } - else - { - print $gen_query_cmd; - } - print "\n"; -} - -#---------------------------------------------------------------------- -# 'k' command -#---------------------------------------------------------------------- -sub dump_kill_cmd -{ - my $cmd = shift; - print "kill (" . join('',@_) . ")\n"; -} - -#---------------------------------------------------------------------- -# 'g' command -#---------------------------------------------------------------------- -sub dump_read_regs_cmd -{ - my $cmd = shift; - print "read_registers ()\n"; -} - -#---------------------------------------------------------------------- -# 'G' command -#---------------------------------------------------------------------- -sub dump_write_regs_cmd -{ - print "write_registers:\n"; - my $cmd = shift; - foreach my $reg_href (@$registers_aref) - { - last if ($_[0] eq '#'); - if ($reg_href->{pseudo} == 0) - { - my $reg_info_href = $reg_href->{info}; - my $reg_name = $reg_href->{name}; - my $reg_extract = $reg_info_href->{extract}; - my $reg_format = $reg_info_href->{format}; - my $reg_val = &$reg_extract(\@_); - printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); - } - } -} - -sub dump_read_regs_rsp -{ - print "read_registers () =>\n"; - if (!is_error_response(@_)) - { - # print join('',@_) . "\n"; - foreach my $reg_href (@$registers_aref) - { - last if ($_[0] eq '#'); - if ($reg_href->{pseudo} == 0) - { - my $reg_info_href = $reg_href->{info}; - my $reg_name = $reg_href->{name}; - my $reg_extract = $reg_info_href->{extract}; - my $reg_format = $reg_info_href->{format}; - my $reg_val = &$reg_extract(\@_); - printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); - } - } - } -} - -sub dump_read_single_register_rsp -{ - dump_register_value(0, \@_, $reg_cmd_reg); - print "\n"; -} - -#---------------------------------------------------------------------- -# '_M' - allocate memory command (LLDB extension) -# -# Command: '_M' -# Arg1: Hex byte size as big endian hex string -# Separator: ',' -# Arg2: permissions as string that must be a string that contains any -# combination of 'r' (readable) 'w' (writable) or 'x' (executable) -# -# Returns: The address that was allocated as a big endian hex string -# on success, else an error "EXX" where XX are hex bytes -# that indicate an error code. -# -# Examples: -# _M10,rw # allocate 16 bytes with read + write permissions -# _M100,rx # allocate 256 bytes with read + execute permissions -#---------------------------------------------------------------------- -sub dump_allocate_memory_cmd -{ - shift; shift; # shift off the '_' and the 'M' - my $byte_size = get_addr(\@_); - shift; # Skip ',' - printf("allocate_memory ( byte_size = %u (0x%x), permissions = %s)\n", $byte_size, $byte_size, join('',@_)); -} - -sub dump_allocate_memory_rsp -{ - if (@_ == 3 and $_[0] == 'E') - { - printf("allocated memory addr = ERROR (%s))\n", join('',@_)); - } - else - { - printf("allocated memory addr = 0x%s\n", join('',@_)); - } -} - -#---------------------------------------------------------------------- -# '_m' - deallocate memory command (LLDB extension) -# -# Command: '_m' -# Arg1: Hex address as big endian hex string -# -# Returns: "OK" on success "EXX" on error -# -# Examples: -# _m201000 # Free previously allocated memory at address 0x201000 -#---------------------------------------------------------------------- -sub dump_deallocate_memory_cmd -{ - shift; shift; # shift off the '_' and the 'm' - printf("deallocate_memory ( addr = 0x%s)\n", join('',@_)); -} - - -#---------------------------------------------------------------------- -# 'p' command -#---------------------------------------------------------------------- -sub dump_read_single_register_cmd -{ - my $cmd = shift; - $reg_cmd_reg = get_hex(\@_); - my $thread = get_thread_from_thread_suffix (\@_); - my $reg_href = $$registers_aref[$reg_cmd_reg]; - - if (defined $thread) - { - print "read_register ( reg = \"$reg_href->{name}\", thread = $thread )\n"; - } - else - { - print "read_register ( reg = \"$reg_href->{name}\" )\n"; - } -} - - -#---------------------------------------------------------------------- -# 'P' command -#---------------------------------------------------------------------- -sub dump_write_single_register_cmd -{ - my $cmd = shift; - my $reg_num = get_hex(\@_); - shift (@_); # Discard the '=' - - print "write_register ( "; - dump_register_value(0, \@_, $reg_num); - my $thread = get_thread_from_thread_suffix (\@_); - if (defined $thread) - { - print ", thread = $thread"; - } - print " )\n"; -} - -#---------------------------------------------------------------------- -# 'm' command -#---------------------------------------------------------------------- -our $read_mem_address = 0; -sub dump_read_mem_cmd -{ - my $cmd = shift; - $read_mem_address = get_addr(\@_); - shift; # Skip ',' - printf("read_mem ( $addr_format, %s )\n", $read_mem_address, join('',@_)); -} - -#---------------------------------------------------------------------- -# 'm' response -#---------------------------------------------------------------------- -sub dump_read_mem_rsp -{ - # If the memory read was 2 or 4 bytes, print it out in native format - # instead of just as bytes. - my $num_nibbles = @_; - if ($num_nibbles == 2) - { - printf(" 0x%2.2x", get8(\@_)); - } - elsif ($num_nibbles == 4) - { - printf(" 0x%4.4x", get16(\@_)); - } - elsif ($num_nibbles == 8) - { - printf(" 0x%8.8x", get32(\@_)); - } - elsif ($num_nibbles == 16) - { - printf(" 0x%s", get64(\@_)); - } - else - { - my $curr_address = $read_mem_address; - my $nibble; - my $nibble_offset = 0; - my $max_nibbles_per_line = 2 * $max_bytes_per_line; - foreach $nibble (@_) - { - if (($nibble_offset % $max_nibbles_per_line) == 0) - { - ($nibble_offset > 0) and print "\n "; - printf("$addr_format: ", $curr_address + $nibble_offset/2); - } - (($nibble_offset % 2) == 0) and print ' '; - print $nibble; - $nibble_offset++; - } - } - print "\n"; -} - -#---------------------------------------------------------------------- -# 'c' or 's' command -#---------------------------------------------------------------------- -sub dump_continue_cmd -{ - my $cmd = shift; - my $cmd_str; - $cmd eq 'c' and $cmd_str = 'continue'; - $cmd eq 's' and $cmd_str = 'step'; - my $address = -1; - if (@_) - { - my $address = get_addr(\@_); - printf("%s ($addr_format)\n", $cmd_str, $address); - } - else - { - printf("%s ()\n", $cmd_str); - } -} - -#---------------------------------------------------------------------- -# 'Css' continue (C) with signal (ss where 'ss' is two hex digits) -# 'Sss' step (S) with signal (ss where 'ss' is two hex digits) -#---------------------------------------------------------------------- -sub dump_continue_with_signal_cmd -{ - my $cmd = shift; - my $address = -1; - my $cmd_str; - $cmd eq 'c' and $cmd_str = 'continue'; - $cmd eq 's' and $cmd_str = 'step'; - my $signal = get_hex(\@_); - if (@_) - { - my $address = 0; - if (@_ && $_[0] == ';') - { - shift; - $address = get_addr(\@_); - } - } - - if ($address != -1) - { - printf("%s_with_signal (signal = 0x%2.2x, address = $addr_format)\n", $cmd_str, $signal, $address); - } - else - { - printf("%s_with_signal (signal = 0x%2.2x)\n", $cmd_str, $signal); - } -} - -#---------------------------------------------------------------------- -# 'A' command -#---------------------------------------------------------------------- -sub dump_A_command -{ - my $cmd = get_expected_char(\@_, 'A') or print "error: incorrect command letter for argument packet, expected 'A'\n"; - printf("set_program_arguments (\n"); - do - { - my $arg_len = get_uint(\@_); - get_expected_char(\@_, ',') or die "error: missing comma after argument length...?\n"; - my $arg_idx = get_uint(\@_); - get_expected_char(\@_, ',') or die "error: missing comma after argument number...?\n"; - - my $arg = ''; - my $num_hex8_bytes = $arg_len/2; - for (1 .. $num_hex8_bytes) - { - $arg .= sprintf("%c", get8(\@_)) - } - printf(" <%3u> argv[%u] = '%s'\n", $arg_len, $arg_idx, $arg); - if (@_ > 0) - { - get_expected_char(\@_, ',') or die "error: missing comma after argument argument ASCII hex bytes...?\n"; - } - } while (@_ > 0); - printf(" )\n"); -} - - -#---------------------------------------------------------------------- -# 'z' and 'Z' command -#---------------------------------------------------------------------- -sub dump_bp_wp_command -{ - my $cmd = shift; - my $type = shift; - shift; # Skip ',' - my $address = get_addr(\@_); - shift; # Skip ',' - my $length = join('',@_); - if ($cmd eq 'z') - { - printf("remove $point_types[$type]($addr_format, %d)\n", $address, $length); - } - else - { - printf("insert $point_types[$type]($addr_format, %d)\n", $address, $length); - } -} - - -#---------------------------------------------------------------------- -# 'X' command -#---------------------------------------------------------------------- -sub dump_write_mem_binary_cmd -{ - my $cmd = shift; - my $address = get_addr(\@_); - shift; # Skip ',' - - my ($length, $binary) = split(/:/, join('',@_)); - printf("write_mem_binary ( $addr_format, %d, %s)\n", $address, $length, $binary); - -} - -#---------------------------------------------------------------------- -# 'M' command -#---------------------------------------------------------------------- -sub dump_write_mem_cmd -{ - my $cmd = shift; - my $address = get_addr(\@_); - shift; # Skip ',' - my ($length, $hex_bytes) = split(/:/, join('',@_)); -# printf("write_mem ( $addr_format, %d, %s)\n", $address, $length, $hex_bytes); - printf("write_mem ( addr = $addr_format, len = %d (0x%x), bytes = ", $address, $length, $length); - splice(@_, 0, length($length)+1); - - my $curr_address = $address; - my $nibble; - my $nibble_count = 0; - my $max_nibbles_per_line = 2 * $max_bytes_per_line; - foreach $nibble (@_) - { - (($nibble_count % 2) == 0) and print ' '; - print $nibble; - $nibble_count++; - } - - # If the memory to write is 2 or 4 bytes, print it out in native format - # instead of just as bytes. - if (@_ == 4) - { - printf(" ( 0x%4.4x )", get16(\@_)); - } - elsif (@_ == 8) - { - printf(" ( 0x%8.8x )", get32(\@_)); - } - print " )\n"; - -} - -#---------------------------------------------------------------------- -# 'v' command -#---------------------------------------------------------------------- -our $extended_rsp_callback = 0; -sub dump_extended_cmd -{ - $extended_rsp_callback = 0; - if (join('', @_[0..4]) eq "vCont") - { - dump_extended_continue_cmd(splice(@_,5)); - } - elsif (join('', @_[0..7]) eq 'vAttach;') - { - dump_attach_command (splice(@_,8)); - } - elsif (join('', @_[0..11]) eq 'vAttachWait;') - { - dump_attach_wait_command (splice(@_,12)); - } -} - -#---------------------------------------------------------------------- -# 'v' response -#---------------------------------------------------------------------- -sub dump_extended_rsp -{ - if ($extended_rsp_callback) - { - &$extended_rsp_callback(@_); - } - $extended_rsp_callback = 0; -} - -#---------------------------------------------------------------------- -# 'vAttachWait' command -#---------------------------------------------------------------------- -sub dump_attach_wait_command -{ - print "attach_wait ( "; - while (@_) - { - printf("%c", get8(\@_)) - } - printf " )\n"; - -} - -#---------------------------------------------------------------------- -# 'vAttach' command -#---------------------------------------------------------------------- -sub dump_attach_command -{ - printf("attach ( pid = %i )", get_hex(\@_)); - $extended_rsp_callback = \&dump_stop_reply_packet; -} - -#---------------------------------------------------------------------- -# 'vCont' command -#---------------------------------------------------------------------- -sub dump_extended_continue_cmd -{ - print "extended_continue ( "; - my $cmd = shift; - if ($cmd eq '?') - { - print "list supported modes )\n"; - $extended_rsp_callback = \&dump_extended_continue_rsp; - } - elsif ($cmd eq ';') - { - $extended_rsp_callback = \&dump_stop_reply_packet; - my $i = 0; - while ($#_ >= 0) - { - if ($i > 0) - { - print ", "; - } - my $continue_cmd = shift; - my $tmp; - if ($continue_cmd eq 'c') - { - print "continue"; - } - elsif ($continue_cmd eq 'C') - { - print "continue with signal "; - print shift; - print shift; - } - elsif ($continue_cmd eq 's') - { - print "step"; - } - elsif ($continue_cmd eq 'S') - { - print "step with signal "; - print shift; - print shift; - } - - if ($_[0] eq ':') - { - shift; # Skip ':' - print " for thread "; - while ($#_ >= 0) - { - $tmp = shift; - if (length($tmp) > 0 && $tmp ne ';') { - print $tmp; - } else { - last; - } - } - } - $i++; - } - - printf " )\n"; - } -} - -#---------------------------------------------------------------------- -# 'vCont' response -#---------------------------------------------------------------------- -sub dump_extended_continue_rsp -{ - if (scalar(@_) == 0) - { - print "$unimplemented_str\n"; - } - else - { - print "extended_continue supports " . join('',@_) . "\n"; - } -} - -#---------------------------------------------------------------------- -# Dump the command ascii for any unknown commands -#---------------------------------------------------------------------- -sub dump_other_cmd -{ - print "other = " . join('',@_) . "\n"; -} - -#---------------------------------------------------------------------- -# Check to see if the response was unsupported with appropriate checksum -#---------------------------------------------------------------------- -sub rsp_is_unsupported -{ - return join('',@_) eq "#00"; -} - -#---------------------------------------------------------------------- -# Check to see if the response was "OK" with appropriate checksum -#---------------------------------------------------------------------- -sub rsp_is_OK -{ - return join('',@_) eq "OK#9a"; -} - -#---------------------------------------------------------------------- -# Dump a response for an unknown command -#---------------------------------------------------------------------- -sub dump_other_rsp -{ - print "other = " . join('',@_) . "\n"; -} - -#---------------------------------------------------------------------- -# Get a byte from the ascii string assuming that the 2 nibble ascii -# characters are in hex. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get8 -{ - my $arrayref = shift; - my $val = hex(shift(@$arrayref) . shift(@$arrayref)); - return $val; -} - -#---------------------------------------------------------------------- -# Get a 16 bit integer and swap if $swap global is set to a non-zero -# value. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get16 -{ - my $arrayref = shift; - my $val = 0; - if ($swap) - { - $val = get8($arrayref) | - get8($arrayref) << 8; - } - else - { - $val = get8($arrayref) << 8 | - get8($arrayref) ; - } - return $val; -} - -#---------------------------------------------------------------------- -# Get a 32 bit integer and swap if $swap global is set to a non-zero -# value. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get32 -{ - my $arrayref = shift; - my $val = 0; - if ($swap) - { - $val = get8($arrayref) | - get8($arrayref) << 8 | - get8($arrayref) << 16 | - get8($arrayref) << 24 ; - } - else - { - $val = get8($arrayref) << 24 | - get8($arrayref) << 16 | - get8($arrayref) << 8 | - get8($arrayref) ; - } - return $val; -} - -#---------------------------------------------------------------------- -# Get a 64 bit hex value as a string -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get64 -{ - my $arrayref = shift; - my $val = ''; - my @nibbles; - if ($swap) - { - push @nibbles, splice(@$arrayref, 14, 2); - push @nibbles, splice(@$arrayref, 12, 2); - push @nibbles, splice(@$arrayref, 10, 2); - push @nibbles, splice(@$arrayref, 8, 2); - push @nibbles, splice(@$arrayref, 6, 2); - push @nibbles, splice(@$arrayref, 4, 2); - push @nibbles, splice(@$arrayref, 2, 2); - push @nibbles, splice(@$arrayref, 0, 2); - } - else - { - (@nibbles) = splice(@$arrayref, 0, ((64/8) * 2)); - } - $val = join('', @nibbles); - return $val; -} - -#---------------------------------------------------------------------- -# Get a 80 bit hex value as a string -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get80 -{ - my $arrayref = shift; - my $val = ''; - my @nibbles; - if ($swap) - { - push @nibbles, splice(@$arrayref, 18, 2); - push @nibbles, splice(@$arrayref, 16, 2); - push @nibbles, splice(@$arrayref, 14, 2); - push @nibbles, splice(@$arrayref, 12, 2); - push @nibbles, splice(@$arrayref, 10, 2); - push @nibbles, splice(@$arrayref, 8, 2); - push @nibbles, splice(@$arrayref, 6, 2); - push @nibbles, splice(@$arrayref, 4, 2); - push @nibbles, splice(@$arrayref, 2, 2); - push @nibbles, splice(@$arrayref, 0, 2); - } - else - { - (@nibbles) = splice(@$arrayref, 0, ((80/8) * 2)); - } - $val = join('', @nibbles); - return $val; -} - -#---------------------------------------------------------------------- -# Get a 96 bit hex value as a string -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get96 -{ - my $arrayref = shift; - my $val = ''; - my @nibbles; - if ($swap) - { - push @nibbles, splice(@$arrayref, 22, 2); - push @nibbles, splice(@$arrayref, 20, 2); - push @nibbles, splice(@$arrayref, 18, 2); - push @nibbles, splice(@$arrayref, 16, 2); - push @nibbles, splice(@$arrayref, 14, 2); - push @nibbles, splice(@$arrayref, 12, 2); - push @nibbles, splice(@$arrayref, 10, 2); - push @nibbles, splice(@$arrayref, 8, 2); - push @nibbles, splice(@$arrayref, 6, 2); - push @nibbles, splice(@$arrayref, 4, 2); - push @nibbles, splice(@$arrayref, 2, 2); - push @nibbles, splice(@$arrayref, 0, 2); - } - else - { - (@nibbles) = splice(@$arrayref, 0, ((96/8) * 2)); - } - $val = join('', @nibbles); - return $val; -} - -#---------------------------------------------------------------------- -# Get a 128 bit hex value as a string -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get128 -{ - my $arrayref = shift; - my $val = ''; - my @nibbles; - if ($swap) - { - push @nibbles, splice(@$arrayref, 30, 2); - push @nibbles, splice(@$arrayref, 28, 2); - push @nibbles, splice(@$arrayref, 26, 2); - push @nibbles, splice(@$arrayref, 24, 2); - push @nibbles, splice(@$arrayref, 22, 2); - push @nibbles, splice(@$arrayref, 20, 2); - push @nibbles, splice(@$arrayref, 18, 2); - push @nibbles, splice(@$arrayref, 16, 2); - push @nibbles, splice(@$arrayref, 14, 2); - push @nibbles, splice(@$arrayref, 12, 2); - push @nibbles, splice(@$arrayref, 10, 2); - push @nibbles, splice(@$arrayref, 8, 2); - push @nibbles, splice(@$arrayref, 6, 2); - push @nibbles, splice(@$arrayref, 4, 2); - push @nibbles, splice(@$arrayref, 2, 2); - push @nibbles, splice(@$arrayref, 0, 2); - } - else - { - (@nibbles) = splice(@$arrayref, 0, ((128/8) * 2)); - } - $val = join('', @nibbles); - return $val; -} - -#---------------------------------------------------------------------- -# Get a 256 bit hex value as a string -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get256 -{ - my $arrayref = shift; - my $val = ''; - my @nibbles; - if ($swap) - { - push @nibbles, splice(@$arrayref, 62, 2); - push @nibbles, splice(@$arrayref, 60, 2); - push @nibbles, splice(@$arrayref, 58, 2); - push @nibbles, splice(@$arrayref, 56, 2); - push @nibbles, splice(@$arrayref, 54, 2); - push @nibbles, splice(@$arrayref, 52, 2); - push @nibbles, splice(@$arrayref, 50, 2); - push @nibbles, splice(@$arrayref, 48, 2); - push @nibbles, splice(@$arrayref, 46, 2); - push @nibbles, splice(@$arrayref, 44, 2); - push @nibbles, splice(@$arrayref, 42, 2); - push @nibbles, splice(@$arrayref, 40, 2); - push @nibbles, splice(@$arrayref, 38, 2); - push @nibbles, splice(@$arrayref, 36, 2); - push @nibbles, splice(@$arrayref, 34, 2); - push @nibbles, splice(@$arrayref, 32, 2); - push @nibbles, splice(@$arrayref, 30, 2); - push @nibbles, splice(@$arrayref, 28, 2); - push @nibbles, splice(@$arrayref, 26, 2); - push @nibbles, splice(@$arrayref, 24, 2); - push @nibbles, splice(@$arrayref, 22, 2); - push @nibbles, splice(@$arrayref, 20, 2); - push @nibbles, splice(@$arrayref, 18, 2); - push @nibbles, splice(@$arrayref, 16, 2); - push @nibbles, splice(@$arrayref, 14, 2); - push @nibbles, splice(@$arrayref, 12, 2); - push @nibbles, splice(@$arrayref, 10, 2); - push @nibbles, splice(@$arrayref, 8, 2); - push @nibbles, splice(@$arrayref, 6, 2); - push @nibbles, splice(@$arrayref, 4, 2); - push @nibbles, splice(@$arrayref, 2, 2); - push @nibbles, splice(@$arrayref, 0, 2); - } - else - { - (@nibbles) = splice(@$arrayref, 0, ((256/8) * 2)); - } - $val = join('', @nibbles); - return $val; -} - -#---------------------------------------------------------------------- -# Get an unsigned integer value by grabbing items off the front of -# the array stopping when a non-digit char string is encountered. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it -#---------------------------------------------------------------------- -sub get_uint -{ - my $arrayref = shift; - @$arrayref == 0 and return 0; - my $val = 0; - while ($$arrayref[0] =~ /[0-9]/) - { - $val = $val * 10 + int(shift(@$arrayref)); - } - return $val; -} - -#---------------------------------------------------------------------- -# Check the first character in the array and if it matches the expected -# character, return that character, else return undef; -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it. If the expected -# character doesn't match, it won't touch the array. If the first -# character does match, it will shift it off and return it. -#---------------------------------------------------------------------- -sub get_expected_char -{ - my $arrayref = shift; - my $expected_char = shift; - if ($expected_char eq $$arrayref[0]) - { - return shift(@$arrayref); - } - return undef; -} -#---------------------------------------------------------------------- -# Get a hex value by grabbing items off the front of the array and -# stopping when a non-hex char string is encountered. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get_hex -{ - my $arrayref = shift; - my $my_swap = @_ ? shift : 0; - my $shift = 0; - my $val = 0; - while ($$arrayref[0] =~ /[0-9a-fA-F]/) - { - if ($my_swap) - { - my $byte = hex(shift(@$arrayref)) << 4 | hex(shift(@$arrayref)); - $val |= $byte << $shift; - $shift += 8; - } - else - { - $val <<= 4; - $val |= hex(shift(@$arrayref)); - } - } - return $val; -} - -#---------------------------------------------------------------------- -# Get an address value by grabbing items off the front of the array. -# -# The argument for this function needs to be a reference to an array -# that contains single character strings and the array will get -# updated by shifting characters off the front of it (no leading # "0x") -#---------------------------------------------------------------------- -sub get_addr -{ - get_hex(shift); -} - -sub get_hex_string -{ - my $arrayref = shift; - my $str = ''; - while ($$arrayref[0] =~ /[0-9a-fA-F]/ and $$arrayref[1] =~ /[0-9a-fA-F]/) - { - my $hi_nibble = hex(shift(@$arrayref)); - my $lo_nibble = hex(shift(@$arrayref)); - my $byte = ($hi_nibble << 4) | $lo_nibble; - $str .= chr($byte); - } - return $str; -} - -sub dump_stop_reply_data -{ - while ($#_ >= 0) - { - last unless ($_[0] ne '#'); - - - my $key = ''; - my $value = ''; - my $comment = ''; - if ($_[0] =~ /[0-9a-fA-F]/ && $_[1] =~ /[0-9a-fA-F]/) - { - my $reg_num = get8(\@_); - shift(@_); # Skip ':' - if (defined ($registers_aref) && $reg_num < @$registers_aref) - { - dump_register_value(1, \@_, $reg_num); - print "\n"; - shift(@_); # Skip ';' - next; - } - $key = sprintf("reg %u", $reg_num); - } - my $char; - - if (length($key) == 0) - { - while (1) - { - $char = shift(@_); - if (length($char) == 0 or $char eq ':' or $char eq '#') { last; } - $key .= $char; - } - } - - while (1) - { - $char = shift(@_); - if (length($char) == 0 or $char eq ';' or $char eq '#') { last; } - $value .= $char; - } - if ($key eq 'metype') - { - our %metype_to_name = ( - '1' => ' (EXC_BAD_ACCESS)', - '2' => ' (EXC_BAD_INSTRUCTION)', - '3' => ' (EXC_ARITHMETIC)', - '4' => ' (EXC_EMULATION)', - '5' => ' (EXC_SOFTWARE)', - '6' => ' (EXC_BREAKPOINT)', - '7' => ' (EXC_SYSCALL)', - '8' => ' (EXC_MACH_SYSCALL)', - '9' => ' (EXC_RPC_ALERT)', - '10' => ' (EXC_CRASH)' - ); - if (exists $metype_to_name{$value}) - { - $comment = $metype_to_name{$value}; - } - } - printf("\t%*s = %s$comment\n", $max_register_name_len, $key, $value); - } -} - -#---------------------------------------------------------------------- -# Dumps a Stop Reply Packet which happens in response to a step, -# continue, last signal, and probably a few other commands. -#---------------------------------------------------------------------- -sub dump_stop_reply_packet -{ - my $what = shift(@_); - if ($what eq 'S' or $what eq 'T') - { - my $signo = get8(\@_); - - our %signo_to_name = ( - '1' => ' SIGHUP', - '2' => ' SIGINT', - '3' => ' SIGQUIT', - '4' => ' SIGILL', - '5' => ' SIGTRAP', - '6' => ' SIGABRT', - '7' => ' SIGPOLL/SIGEMT', - '8' => ' SIGFPE', - '9' => ' SIGKILL', - '10' => ' SIGBUS', - '11' => ' SIGSEGV', - '12' => ' SIGSYS', - '13' => ' SIGPIPE', - '14' => ' SIGALRM', - '15' => ' SIGTERM', - '16' => ' SIGURG', - '17' => ' SIGSTOP', - '18' => ' SIGTSTP', - '19' => ' SIGCONT', - '20' => ' SIGCHLD', - '21' => ' SIGTTIN', - '22' => ' SIGTTOU', - '23' => ' SIGIO', - '24' => ' SIGXCPU', - '25' => ' SIGXFSZ', - '26' => ' SIGVTALRM', - '27' => ' SIGPROF', - '28' => ' SIGWINCH', - '29' => ' SIGINFO', - '30' => ' SIGUSR1', - '31' => ' SIGUSR2', - '145' => ' TARGET_EXC_BAD_ACCESS', # 0x91 - '146' => ' TARGET_EXC_BAD_INSTRUCTION', # 0x92 - '147' => ' TARGET_EXC_ARITHMETIC', # 0x93 - '148' => ' TARGET_EXC_EMULATION', # 0x94 - '149' => ' TARGET_EXC_SOFTWARE', # 0x95 - '150' => ' TARGET_EXC_BREAKPOINT' # 0x96 - ); - my $signo_str = sprintf("%i", $signo); - my $signo_name = ''; - if (exists $signo_to_name{$signo_str}) - { - $signo_name = $signo_to_name{$signo_str}; - } - printf ("signal (signo=%u$signo_name)\n", $signo); - dump_stop_reply_data (@_); - } - elsif ($what eq 'W') - { - print 'process_exited( ' . shift(@_) . shift(@_) . " )\n"; - } - elsif ($what eq 'X') - { - print 'process_terminated( ' . shift(@_) . shift(@_) . " )\n"; - } - elsif ($what eq 'O') - { - my $console_output = ''; - my $num_hex8_bytes = @_/2; - for (1 .. $num_hex8_bytes) - { - $console_output .= sprintf("%c", get8(\@_)) - } - - print "program_console_output('$console_output')\n"; - } -} - -#---------------------------------------------------------------------- -# '?' command -#---------------------------------------------------------------------- -sub dump_last_signal_cmd -{ - my $cmd = shift; - print 'last_signal (' . join('',@_) . ")\n"; -} - -sub dump_raw_command -{ - my $cmd_aref = shift; - my $callback_ref; - $curr_cmd = $$cmd_aref[0]; - - if ($curr_cmd eq 'q' or $curr_cmd eq 'Q' or $curr_cmd eq '_') - { - $curr_full_cmd = ''; - foreach my $ch (@$cmd_aref) - { - $ch !~ /[A-Za-z_]/ and last; - $curr_full_cmd .= $ch; - } - } - else - { - $curr_full_cmd = $curr_cmd; - } - - $curr_cmd eq '_' and $curr_cmd .= $$cmd_aref[1]; - $callback_ref = $cmd_callbacks{$curr_cmd}; - if ($callback_ref) - { - &$callback_ref(@$cmd_aref); - } - else - { - # Strip the command byte for responses since we injected that above - dump_other_cmd(@$cmd_aref); - } -} - -sub dump_standard_response -{ - my $cmd_aref = shift; - - my $cmd_len = scalar(@$cmd_aref); - if ($cmd_len == 0) - { - print "$unimplemented_str\n"; - return 1; - } - - my $response = join('', @$cmd_aref); - if ($response eq 'OK') - { - print "$success_str\n"; - return 1; - } - - if ($cmd_len == 3 and index($response, 'E') == 0) - { - print "ERROR: " . substr($response, 1) . "\n"; - return 1; - } - - return 0; -} -sub dump_raw_response -{ - my $cmd_aref = shift; - my $callback_ref; - - if ($packet_start_time != 0.0) - { - if (length($curr_full_cmd) > 0) - { - $packet_times{$curr_full_cmd} += $curr_time - $packet_start_time; - } - else - { - $packet_times{$curr_cmd} += $curr_time - $packet_start_time; - } - $packet_start_time = 0.0; - } - - $callback_ref = $rsp_callbacks{$curr_cmd}; - - if ($callback_ref) - { - &$callback_ref(@$cmd_aref); - } - else - { - dump_standard_response($cmd_aref) or dump_other_rsp(@$cmd_aref); - } - -} -#---------------------------------------------------------------------- -# Dumps any command and handles simple error checking on the responses -# for commands that are unsupported or OK. -#---------------------------------------------------------------------- -sub dump_command -{ - my $cmd_str = shift; - - # Dump the original command string if verbose is on - if ($opt_v) - { - print "dump_command($cmd_str)\n "; - } - - my @cmd_chars = extract_command($cmd_str); - my $is_cmd = 1; - - my $cmd = $cmd_chars[0]; - if ($cmd eq '$') - { - $is_cmd = 0; # Note that this is a reply - $cmd = $curr_cmd; # set the command byte appropriately - shift @cmd_chars; # remove the '$' from the cmd bytes - } - - # Check for common responses across all commands and handle them - # if we can - if ( $is_cmd == 0 ) - { - if (rsp_is_unsupported(@cmd_chars)) - { - print "$unimplemented_str\n"; - return; - } - elsif (rsp_is_OK(@cmd_chars)) - { - print "$success_str\n"; - return; - } - # Strip the checksum information for responses - strip_checksum(\@cmd_chars); - } - - my $callback_ref; - if ($is_cmd) { - $callback_ref = $cmd_callbacks{$cmd}; - } else { - $callback_ref = $rsp_callbacks{$cmd}; - } - - if ($callback_ref) - { - &$callback_ref(@cmd_chars); - } - else - { - # Strip the command byte for responses since we injected that above - if ($is_cmd) { - dump_other_cmd(@cmd_chars); - } else { - dump_other_rsp(@cmd_chars); - } - - } -} - - -#---------------------------------------------------------------------- -# Process a gdbserver log line by looking for getpkt and putkpt and -# tossing any other lines. - -#---------------------------------------------------------------------- -sub process_log_line -{ - my $line = shift; - #($opt_v and $opt_g) and print "# $line"; - - my $extract_cmd = 0; - my $delta_time = 0.0; - if ($line =~ /^(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$/) - { - my $leading_space = $1; - $curr_time = $2; - $line = $3; - if ($base_time == 0.0) - { - $base_time = $curr_time; - } - else - { - $delta_time = $curr_time - $last_time; - } - printf ("(%.6f, %+.6f): ", $curr_time - $base_time, $delta_time); - $last_time = $curr_time; - } - else - { - $curr_time = 0.0 - } - - if ($line =~ /getpkt /) - { - $extract_cmd = 1; - print "\n--> "; - $packet_start_time = $curr_time; - } - elsif ($line =~ /putpkt /) - { - $extract_cmd = 1; - print "<-- "; - } - elsif ($line =~ /.*Sent: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) - { - $opt_g and print "maintenance dump-packets command: $1\n"; - my @raw_cmd_bytes = split(/ */, $1); - $packet_start_time = $curr_time; - print "\n--> "; - dump_raw_command(\@raw_cmd_bytes); - process_log_line($2); - } - elsif ($line =~ /.*Recvd: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) - { - $opt_g and print "maintenance dump-packets reply: $1\n"; - my @raw_rsp_bytes = split(/ */, $1); - print "<-- "; - dump_raw_response(\@raw_rsp_bytes); - print "\n"; - } - elsif ($line =~ /getpkt: (.*)/) - { - if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) - { - $opt_g and print "command: $1\n"; - my @raw_cmd_bytes = split(/ */, $1); - print "--> "; - $packet_start_time = $curr_time; - dump_raw_command(\@raw_cmd_bytes); - } - elsif ($1 =~ /\+/) - { - #print "--> ACK\n"; - } - elsif ($1 =~ /-/) - { - #print "--> NACK\n"; - } - } - elsif ($line =~ /putpkt: (.*)/) - { - if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) - { - $opt_g and print "response: $1\n"; - my @raw_rsp_bytes = split(/ */, $1); - print "<-- "; - dump_raw_response(\@raw_rsp_bytes); - print "\n"; - } - elsif ($1 =~ /\+/) - { - #print "<-- ACK\n"; - } - elsif ($1 =~ /-/) - { - #print "<-- NACK\n"; - } - } - elsif ($line =~ /send packet: (.*)/) - { - if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) - { - $opt_g and print "command: $1\n"; - my @raw_cmd_bytes = split(/ */, $1); - print "--> "; - $packet_start_time = $curr_time; - dump_raw_command(\@raw_cmd_bytes); - } - elsif ($1 =~ /\+/) - { - #print "--> ACK\n"; - } - elsif ($1 =~ /-/) - { - #print "--> NACK\n"; - } - } - elsif ($line =~ /read packet: (.*)/) - { - if ($1 =~ /\$([^#]*)#[0-9a-fA-F]{2}/) - { - $opt_g and print "response: $1\n"; - my @raw_rsp_bytes = split(/ */, $1); - print "<-- "; - dump_raw_response(\@raw_rsp_bytes); - print "\n"; - } - elsif ($1 =~ /\+/) - { - #print "<-- ACK\n"; - } - elsif ($1 =~ /-/) - { - #print "<-- NACK\n"; - } - } - elsif ($line =~ /Sending packet: \$([^#]+)#[0-9a-fA-F]{2}\.\.\.(.*)/) - { - $opt_g and print "command: $1\n"; - my @raw_cmd_bytes = split(/ */, $1); - print "\n--> "; - $packet_start_time = $curr_time; - dump_raw_command(\@raw_cmd_bytes); - process_log_line($2); - } - elsif ($line =~ /Packet received: (.*)/) - { - $opt_g and print "response: $1\n"; - my @raw_rsp_bytes = split(/ */, $1); - print "<-- "; - dump_raw_response(\@raw_rsp_bytes); - print "\n"; - } - - if ($extract_cmd) - { - my $beg = index($line, '("') + 2; - my $end = rindex($line, '");'); - $packet_start_time = $curr_time; - dump_command(substr($line, $beg, $end - $beg)); - } -} - - -our $line_num = 0; -while(<>) -{ - $line_num++; - $opt_q or printf("# %5d: $_", $line_num); - process_log_line($_); -} - -if (%packet_times) -{ - print "----------------------------------------------------------------------\n"; - print "Packet timing summary:\n"; - print "----------------------------------------------------------------------\n"; - print "Packet Time %\n"; - print "---------------------- -------- ------\n"; - my @packet_names = keys %packet_times; - my $total_packet_times = 0.0; - foreach my $key (@packet_names) - { - $total_packet_times += $packet_times{$key}; - } - - foreach my $value (sort {$packet_times{$b} cmp $packet_times{$a}} @packet_names) - { - my $percent = ($packet_times{$value} / $total_packet_times) * 100.0; - if ($percent < 10.0) - { - printf("%22s %1.6f %2.2f\n", $value, $packet_times{$value}, $percent); - - } - else - { - printf("%22s %1.6f %2.2f\n", $value, $packet_times{$value}, $percent); - } - } - print "---------------------- -------- ------\n"; - printf (" Total %1.6f 100.00\n", $total_packet_times); -} - - - - - - - |