1#!/usr/bin/perl 2 3use strict; 4 5#---------------------------------------------------------------------- 6# Globals 7#---------------------------------------------------------------------- 8our $unimplemented_str = "UNIMPLEMENTED"; 9our $success_str = "OK"; 10our $swap = 1; 11our $addr_size = 4; 12our $thread_suffix_supported = 0; 13our $max_bytes_per_line = 32; 14our $addr_format = sprintf("0x%%%u.%ux", $addr_size*2, $addr_size*2); 15our $pid_format = "%04.4x"; 16our $tid_format = "%04.4x"; 17our $reg8_href = { extract => \&get8, format => "0x%2.2x" }; 18our $reg16_href = { extract => \&get16, format => "0x%4.4x" }; 19our $reg32_href = { extract => \&get32, format => "0x%8.8x" }; 20our $reg64_href = { extract => \&get64, format => "0x%s" }; 21our $reg80_href = { extract => \&get80, format => "0x%s" }; 22our $reg128_href = { extract => \&get128, format => "0x%s" }; 23our $reg256_href = { extract => \&get256, format => "0x%s" }; 24our $float32_href = { extract => \&get32, format => "0x%8.8x" }; 25our $float64_href = { extract => \&get64, format => "0x%s" }; 26our $float96_href = { extract => \&get96, format => "0x%s" }; 27our $curr_cmd = undef; 28our $reg_cmd_reg; 29our %reg_map = ( 30 'i386-gdb' => [ 31 { name => 'eax', info => $reg32_href }, 32 { name => 'ecx', info => $reg32_href }, 33 { name => 'edx', info => $reg32_href }, 34 { name => 'ebx', info => $reg32_href }, 35 { name => 'esp', info => $reg32_href }, 36 { name => 'ebp', info => $reg32_href }, 37 { name => 'esi', info => $reg32_href }, 38 { name => 'edi', info => $reg32_href }, 39 { name => 'eip', info => $reg32_href }, 40 { name => 'eflags', info => $reg32_href }, 41 { name => 'cs', info => $reg32_href }, 42 { name => 'ss', info => $reg32_href }, 43 { name => 'ds', info => $reg32_href }, 44 { name => 'es', info => $reg32_href }, 45 { name => 'fs', info => $reg32_href }, 46 { name => 'gs', info => $reg32_href }, 47 { name => 'st0', info => $reg80_href }, 48 { name => 'st1', info => $reg80_href }, 49 { name => 'st2', info => $reg80_href }, 50 { name => 'st3', info => $reg80_href }, 51 { name => 'st4', info => $reg80_href }, 52 { name => 'st5', info => $reg80_href }, 53 { name => 'st6', info => $reg80_href }, 54 { name => 'st7', info => $reg80_href }, 55 { name => 'fctrl', info => $reg32_href }, 56 { name => 'fstat', info => $reg32_href }, 57 { name => 'ftag', info => $reg32_href }, 58 { name => 'fiseg', info => $reg32_href }, 59 { name => 'fioff', info => $reg32_href }, 60 { name => 'foseg', info => $reg32_href }, 61 { name => 'fooff', info => $reg32_href }, 62 { name => 'fop', info => $reg32_href }, 63 { name => 'xmm0', info => $reg128_href }, 64 { name => 'xmm1', info => $reg128_href }, 65 { name => 'xmm2', info => $reg128_href }, 66 { name => 'xmm3', info => $reg128_href }, 67 { name => 'xmm4', info => $reg128_href }, 68 { name => 'xmm5', info => $reg128_href }, 69 { name => 'xmm6', info => $reg128_href }, 70 { name => 'xmm7', info => $reg128_href }, 71 { name => 'mxcsr', info => $reg32_href }, 72 { name => 'mm0', info => $reg64_href }, 73 { name => 'mm1', info => $reg64_href }, 74 { name => 'mm2', info => $reg64_href }, 75 { name => 'mm3', info => $reg64_href }, 76 { name => 'mm4', info => $reg64_href }, 77 { name => 'mm5', info => $reg64_href }, 78 { name => 'mm6', info => $reg64_href }, 79 { name => 'mm7', info => $reg64_href }, 80 ], 81 82 'i386-lldb' => [ 83 { name => 'eax', info => $reg32_href }, 84 { name => 'ebx', info => $reg32_href }, 85 { name => 'ecx', info => $reg32_href }, 86 { name => 'edx', info => $reg32_href }, 87 { name => 'edi', info => $reg32_href }, 88 { name => 'esi', info => $reg32_href }, 89 { name => 'ebp', info => $reg32_href }, 90 { name => 'esp', info => $reg32_href }, 91 { name => 'ss', info => $reg32_href }, 92 { name => 'eflags', info => $reg32_href }, 93 { name => 'eip', info => $reg32_href }, 94 { name => 'cs', info => $reg32_href }, 95 { name => 'ds', info => $reg32_href }, 96 { name => 'es', info => $reg32_href }, 97 { name => 'fs', info => $reg32_href }, 98 { name => 'gs', info => $reg32_href }, 99 { name => 'fctrl', info => $reg16_href }, 100 { name => 'fstat', info => $reg16_href }, 101 { name => 'ftag', info => $reg8_href }, 102 { name => 'fop', info => $reg16_href }, 103 { name => 'fioff', info => $reg32_href }, 104 { name => 'fiseg', info => $reg16_href }, 105 { name => 'fooff', info => $reg32_href }, 106 { name => 'foseg', info => $reg16_href }, 107 { name => 'mxcsr', info => $reg32_href }, 108 { name => 'mxcsrmask', info => $reg32_href }, 109 { name => 'stmm0', info => $reg80_href }, 110 { name => 'stmm1', info => $reg80_href }, 111 { name => 'stmm2', info => $reg80_href }, 112 { name => 'stmm3', info => $reg80_href }, 113 { name => 'stmm4', info => $reg80_href }, 114 { name => 'stmm5', info => $reg80_href }, 115 { name => 'stmm6', info => $reg80_href }, 116 { name => 'stmm7', info => $reg80_href }, 117 { name => 'xmm0', info => $reg128_href }, 118 { name => 'xmm1', info => $reg128_href }, 119 { name => 'xmm2', info => $reg128_href }, 120 { name => 'xmm3', info => $reg128_href }, 121 { name => 'xmm4', info => $reg128_href }, 122 { name => 'xmm5', info => $reg128_href }, 123 { name => 'xmm6', info => $reg128_href }, 124 { name => 'xmm7', info => $reg128_href }, 125 { name => 'trapno', info => $reg32_href }, 126 { name => 'err', info => $reg32_href }, 127 { name => 'faultvaddr', info => $reg32_href }, 128 ], 129 130 'arm-gdb' => [ 131 { name => 'r0' , info => $reg32_href }, 132 { name => 'r1' , info => $reg32_href }, 133 { name => 'r2' , info => $reg32_href }, 134 { name => 'r3' , info => $reg32_href }, 135 { name => 'r4' , info => $reg32_href }, 136 { name => 'r5' , info => $reg32_href }, 137 { name => 'r6' , info => $reg32_href }, 138 { name => 'r7' , info => $reg32_href }, 139 { name => 'r8' , info => $reg32_href }, 140 { name => 'r9' , info => $reg32_href }, 141 { name => 'r10' , info => $reg32_href }, 142 { name => 'r11' , info => $reg32_href }, 143 { name => 'r12' , info => $reg32_href }, 144 { name => 'sp' , info => $reg32_href }, 145 { name => 'lr' , info => $reg32_href }, 146 { name => 'pc' , info => $reg32_href }, 147 { name => 'f0' , info => $float96_href }, 148 { name => 'f1' , info => $float96_href }, 149 { name => 'f2' , info => $float96_href }, 150 { name => 'f3' , info => $float96_href }, 151 { name => 'f4' , info => $float96_href }, 152 { name => 'f5' , info => $float96_href }, 153 { name => 'f6' , info => $float96_href }, 154 { name => 'f7' , info => $float96_href }, 155 { name => 'fps' , info => $reg32_href }, 156 { name => 'cpsr' , info => $reg32_href }, 157 { name => 's0' , info => $float32_href }, 158 { name => 's1' , info => $float32_href }, 159 { name => 's2' , info => $float32_href }, 160 { name => 's3' , info => $float32_href }, 161 { name => 's4' , info => $float32_href }, 162 { name => 's5' , info => $float32_href }, 163 { name => 's6' , info => $float32_href }, 164 { name => 's7' , info => $float32_href }, 165 { name => 's8' , info => $float32_href }, 166 { name => 's9' , info => $float32_href }, 167 { name => 's10' , info => $float32_href }, 168 { name => 's11' , info => $float32_href }, 169 { name => 's12' , info => $float32_href }, 170 { name => 's13' , info => $float32_href }, 171 { name => 's14' , info => $float32_href }, 172 { name => 's15' , info => $float32_href }, 173 { name => 's16' , info => $float32_href }, 174 { name => 's17' , info => $float32_href }, 175 { name => 's18' , info => $float32_href }, 176 { name => 's19' , info => $float32_href }, 177 { name => 's20' , info => $float32_href }, 178 { name => 's21' , info => $float32_href }, 179 { name => 's22' , info => $float32_href }, 180 { name => 's23' , info => $float32_href }, 181 { name => 's24' , info => $float32_href }, 182 { name => 's25' , info => $float32_href }, 183 { name => 's26' , info => $float32_href }, 184 { name => 's27' , info => $float32_href }, 185 { name => 's28' , info => $float32_href }, 186 { name => 's29' , info => $float32_href }, 187 { name => 's30' , info => $float32_href }, 188 { name => 's31' , info => $float32_href }, 189 { name => 'fpscr' , info => $reg32_href }, 190 { name => 'd16' , info => $float64_href }, 191 { name => 'd17' , info => $float64_href }, 192 { name => 'd18' , info => $float64_href }, 193 { name => 'd19' , info => $float64_href }, 194 { name => 'd20' , info => $float64_href }, 195 { name => 'd21' , info => $float64_href }, 196 { name => 'd22' , info => $float64_href }, 197 { name => 'd23' , info => $float64_href }, 198 { name => 'd24' , info => $float64_href }, 199 { name => 'd25' , info => $float64_href }, 200 { name => 'd26' , info => $float64_href }, 201 { name => 'd27' , info => $float64_href }, 202 { name => 'd28' , info => $float64_href }, 203 { name => 'd29' , info => $float64_href }, 204 { name => 'd30' , info => $float64_href }, 205 { name => 'd31' , info => $float64_href }, 206 ], 207 208 209 'arm-lldb' => [ 210 { name => 'r0' , info => $reg32_href }, 211 { name => 'r1' , info => $reg32_href }, 212 { name => 'r2' , info => $reg32_href }, 213 { name => 'r3' , info => $reg32_href }, 214 { name => 'r4' , info => $reg32_href }, 215 { name => 'r5' , info => $reg32_href }, 216 { name => 'r6' , info => $reg32_href }, 217 { name => 'r7' , info => $reg32_href }, 218 { name => 'r8' , info => $reg32_href }, 219 { name => 'r9' , info => $reg32_href }, 220 { name => 'r10' , info => $reg32_href }, 221 { name => 'r11' , info => $reg32_href }, 222 { name => 'r12' , info => $reg32_href }, 223 { name => 'sp' , info => $reg32_href }, 224 { name => 'lr' , info => $reg32_href }, 225 { name => 'pc' , info => $reg32_href }, 226 { name => 'cpsr' , info => $reg32_href }, 227 { name => 's0' , info => $float32_href }, 228 { name => 's1' , info => $float32_href }, 229 { name => 's2' , info => $float32_href }, 230 { name => 's3' , info => $float32_href }, 231 { name => 's4' , info => $float32_href }, 232 { name => 's5' , info => $float32_href }, 233 { name => 's6' , info => $float32_href }, 234 { name => 's7' , info => $float32_href }, 235 { name => 's8' , info => $float32_href }, 236 { name => 's9' , info => $float32_href }, 237 { name => 's10' , info => $float32_href }, 238 { name => 's11' , info => $float32_href }, 239 { name => 's12' , info => $float32_href }, 240 { name => 's13' , info => $float32_href }, 241 { name => 's14' , info => $float32_href }, 242 { name => 's15' , info => $float32_href }, 243 { name => 's16' , info => $float32_href }, 244 { name => 's17' , info => $float32_href }, 245 { name => 's18' , info => $float32_href }, 246 { name => 's19' , info => $float32_href }, 247 { name => 's20' , info => $float32_href }, 248 { name => 's21' , info => $float32_href }, 249 { name => 's22' , info => $float32_href }, 250 { name => 's23' , info => $float32_href }, 251 { name => 's24' , info => $float32_href }, 252 { name => 's25' , info => $float32_href }, 253 { name => 's26' , info => $float32_href }, 254 { name => 's27' , info => $float32_href }, 255 { name => 's28' , info => $float32_href }, 256 { name => 's29' , info => $float32_href }, 257 { name => 's30' , info => $float32_href }, 258 { name => 's31' , info => $float32_href }, 259 { name => 'd0' , info => $float64_href }, 260 { name => 'd1' , info => $float64_href }, 261 { name => 'd2' , info => $float64_href }, 262 { name => 'd3' , info => $float64_href }, 263 { name => 'd4' , info => $float64_href }, 264 { name => 'd5' , info => $float64_href }, 265 { name => 'd6' , info => $float64_href }, 266 { name => 'd7' , info => $float64_href }, 267 { name => 'd8' , info => $float64_href }, 268 { name => 'd9' , info => $float64_href }, 269 { name => 'd10' , info => $float64_href }, 270 { name => 'd11' , info => $float64_href }, 271 { name => 'd12' , info => $float64_href }, 272 { name => 'd13' , info => $float64_href }, 273 { name => 'd14' , info => $float64_href }, 274 { name => 'd15' , info => $float64_href }, 275 { name => 'd16' , info => $float64_href }, 276 { name => 'd17' , info => $float64_href }, 277 { name => 'd18' , info => $float64_href }, 278 { name => 'd19' , info => $float64_href }, 279 { name => 'd20' , info => $float64_href }, 280 { name => 'd21' , info => $float64_href }, 281 { name => 'd22' , info => $float64_href }, 282 { name => 'd23' , info => $float64_href }, 283 { name => 'd24' , info => $float64_href }, 284 { name => 'd25' , info => $float64_href }, 285 { name => 'd26' , info => $float64_href }, 286 { name => 'd27' , info => $float64_href }, 287 { name => 'd28' , info => $float64_href }, 288 { name => 'd29' , info => $float64_href }, 289 { name => 'd30' , info => $float64_href }, 290 { name => 'd31' , info => $float64_href }, 291 { name => 'fpscr' , info => $reg32_href }, 292 { name => 'exc' , info => $reg32_href }, 293 { name => 'fsr' , info => $reg32_href }, 294 { name => 'far' , info => $reg32_href }, 295 ], 296 297 'x86_64-gdb' => [ 298 { name => 'rax' , info => $reg64_href }, 299 { name => 'rbx' , info => $reg64_href }, 300 { name => 'rcx' , info => $reg64_href }, 301 { name => 'rdx' , info => $reg64_href }, 302 { name => 'rsi' , info => $reg64_href }, 303 { name => 'rdi' , info => $reg64_href }, 304 { name => 'rbp' , info => $reg64_href }, 305 { name => 'rsp' , info => $reg64_href }, 306 { name => 'r8' , info => $reg64_href }, 307 { name => 'r9' , info => $reg64_href }, 308 { name => 'r10' , info => $reg64_href }, 309 { name => 'r11' , info => $reg64_href }, 310 { name => 'r12' , info => $reg64_href }, 311 { name => 'r13' , info => $reg64_href }, 312 { name => 'r14' , info => $reg64_href }, 313 { name => 'r15' , info => $reg64_href }, 314 { name => 'rip' , info => $reg64_href }, 315 { name => 'eflags' , info => $reg32_href }, 316 { name => 'cs' , info => $reg32_href }, 317 { name => 'ss' , info => $reg32_href }, 318 { name => 'ds' , info => $reg32_href }, 319 { name => 'es' , info => $reg32_href }, 320 { name => 'fs' , info => $reg32_href }, 321 { name => 'gs' , info => $reg32_href }, 322 { name => 'stmm0' , info => $reg80_href }, 323 { name => 'stmm1' , info => $reg80_href }, 324 { name => 'stmm2' , info => $reg80_href }, 325 { name => 'stmm3' , info => $reg80_href }, 326 { name => 'stmm4' , info => $reg80_href }, 327 { name => 'stmm5' , info => $reg80_href }, 328 { name => 'stmm6' , info => $reg80_href }, 329 { name => 'stmm7' , info => $reg80_href }, 330 { name => 'fctrl' , info => $reg32_href }, 331 { name => 'fstat' , info => $reg32_href }, 332 { name => 'ftag' , info => $reg32_href }, 333 { name => 'fiseg' , info => $reg32_href }, 334 { name => 'fioff' , info => $reg32_href }, 335 { name => 'foseg' , info => $reg32_href }, 336 { name => 'fooff' , info => $reg32_href }, 337 { name => 'fop' , info => $reg32_href }, 338 { name => 'xmm0' , info => $reg128_href }, 339 { name => 'xmm1' , info => $reg128_href }, 340 { name => 'xmm2' , info => $reg128_href }, 341 { name => 'xmm3' , info => $reg128_href }, 342 { name => 'xmm4' , info => $reg128_href }, 343 { name => 'xmm5' , info => $reg128_href }, 344 { name => 'xmm6' , info => $reg128_href }, 345 { name => 'xmm7' , info => $reg128_href }, 346 { name => 'xmm8' , info => $reg128_href }, 347 { name => 'xmm9' , info => $reg128_href }, 348 { name => 'xmm10' , info => $reg128_href }, 349 { name => 'xmm11' , info => $reg128_href }, 350 { name => 'xmm12' , info => $reg128_href }, 351 { name => 'xmm13' , info => $reg128_href }, 352 { name => 'xmm14' , info => $reg128_href }, 353 { name => 'xmm15' , info => $reg128_href }, 354 { name => 'mxcsr' , info => $reg32_href }, 355 ], 356 357 'x86_64-lldb' => [ 358 { name => 'rax' , info => $reg64_href }, 359 { name => 'rbx' , info => $reg64_href }, 360 { name => 'rcx' , info => $reg64_href }, 361 { name => 'rdx' , info => $reg64_href }, 362 { name => 'rdi' , info => $reg64_href }, 363 { name => 'rsi' , info => $reg64_href }, 364 { name => 'rbp' , info => $reg64_href }, 365 { name => 'rsp' , info => $reg64_href }, 366 { name => 'r8 ' , info => $reg64_href }, 367 { name => 'r9 ' , info => $reg64_href }, 368 { name => 'r10' , info => $reg64_href }, 369 { name => 'r11' , info => $reg64_href }, 370 { name => 'r12' , info => $reg64_href }, 371 { name => 'r13' , info => $reg64_href }, 372 { name => 'r14' , info => $reg64_href }, 373 { name => 'r15' , info => $reg64_href }, 374 { name => 'rip' , info => $reg64_href }, 375 { name => 'rflags' , info => $reg64_href }, 376 { name => 'cs' , info => $reg64_href }, 377 { name => 'fs' , info => $reg64_href }, 378 { name => 'gs' , info => $reg64_href }, 379 { name => 'fctrl' , info => $reg16_href }, 380 { name => 'fstat' , info => $reg16_href }, 381 { name => 'ftag' , info => $reg8_href }, 382 { name => 'fop' , info => $reg16_href }, 383 { name => 'fioff' , info => $reg32_href }, 384 { name => 'fiseg' , info => $reg16_href }, 385 { name => 'fooff' , info => $reg32_href }, 386 { name => 'foseg' , info => $reg16_href }, 387 { name => 'mxcsr' , info => $reg32_href }, 388 { name => 'mxcsrmask' , info => $reg32_href }, 389 { name => 'stmm0' , info => $reg80_href }, 390 { name => 'stmm1' , info => $reg80_href }, 391 { name => 'stmm2' , info => $reg80_href }, 392 { name => 'stmm3' , info => $reg80_href }, 393 { name => 'stmm4' , info => $reg80_href }, 394 { name => 'stmm5' , info => $reg80_href }, 395 { name => 'stmm6' , info => $reg80_href }, 396 { name => 'stmm7' , info => $reg80_href }, 397 { name => 'xmm0' , info => $reg128_href }, 398 { name => 'xmm1' , info => $reg128_href }, 399 { name => 'xmm2' , info => $reg128_href }, 400 { name => 'xmm3' , info => $reg128_href }, 401 { name => 'xmm4' , info => $reg128_href }, 402 { name => 'xmm5' , info => $reg128_href }, 403 { name => 'xmm6' , info => $reg128_href }, 404 { name => 'xmm7' , info => $reg128_href }, 405 { name => 'xmm8' , info => $reg128_href }, 406 { name => 'xmm9' , info => $reg128_href }, 407 { name => 'xmm10' , info => $reg128_href }, 408 { name => 'xmm11' , info => $reg128_href }, 409 { name => 'xmm12' , info => $reg128_href }, 410 { name => 'xmm13' , info => $reg128_href }, 411 { name => 'xmm14' , info => $reg128_href }, 412 { name => 'xmm15' , info => $reg128_href }, 413 { name => 'trapno' , info => $reg32_href }, 414 { name => 'err' , info => $reg32_href }, 415 { name => 'faultvaddr' , info => $reg64_href }, 416 ] 417); 418 419our $max_register_name_len = 0; 420calculate_max_register_name_length(); 421our @point_types = ( "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ); 422our $opt_v = 0; # verbose 423our $opt_g = 0; # debug 424our $opt_q = 0; # quiet 425our $opt_r = undef; 426use Getopt::Std; 427getopts('gvqr:'); 428 429our $registers_aref = undef; 430 431if (length($opt_r)) 432{ 433 if (exists $reg_map{$opt_r}) 434 { 435 $registers_aref = $reg_map{$opt_r}; 436 } 437 else 438 { 439 die "Can't get registers group for '$opt_r'\n"; 440 } 441} 442 443sub extract_key_value_pairs 444{ 445 my $kv_href = {}; 446 my $arrayref = shift; 447 my $str = join('',@$arrayref); 448 my @kv_strs = split(/;/, $str); 449 foreach my $kv_str (@kv_strs) 450 { 451 my ($key, $value) = split(/:/, $kv_str); 452 $kv_href->{$key} = $value; 453 } 454 return $kv_href; 455} 456 457sub get_thread_from_thread_suffix 458{ 459 if ($thread_suffix_supported) 460 { 461 my $arrayref = shift; 462 # Skip leading semi-colon if needed 463 $$arrayref[0] == ';' and shift @$arrayref; 464 my $thread_href = extract_key_value_pairs ($arrayref); 465 if (exists $thread_href->{thread}) 466 { 467 return $thread_href->{thread}; 468 } 469 } 470 return undef; 471} 472 473sub calculate_max_register_name_length 474{ 475 $max_register_name_len = 7; 476 foreach my $reg_href (@$registers_aref) 477 { 478 my $name_len = length($reg_href->{name}); 479 if ($max_register_name_len < $name_len) 480 { 481 $max_register_name_len = $name_len; 482 } 483 } 484} 485#---------------------------------------------------------------------- 486# Hash that maps command characters to the appropriate functions using 487# the command character as the key and the value being a reference to 488# the dump function for dumping the command itself. 489#---------------------------------------------------------------------- 490our %cmd_callbacks = 491( 492 '?' => \&dump_last_signal_cmd, 493 'H' => \&dump_set_thread_cmd, 494 'T' => \&dump_thread_is_alive_cmd, 495 'q' => \&dump_general_query_cmd, 496 'Q' => \&dump_general_set_cmd, 497 'g' => \&dump_read_regs_cmd, 498 'G' => \&dump_write_regs_cmd, 499 'p' => \&dump_read_single_register_cmd, 500 'P' => \&dump_write_single_register_cmd, 501 'm' => \&dump_read_mem_cmd, 502 'M' => \&dump_write_mem_cmd, 503 'X' => \&dump_write_mem_binary_cmd, 504 'Z' => \&dump_bp_wp_command, 505 'z' => \&dump_bp_wp_command, 506 'k' => \&dump_kill_cmd, 507 'A' => \&dump_A_command, 508 'c' => \&dump_continue_cmd, 509 'C' => \&dump_continue_with_signal_cmd, 510 '_M' => \&dump_allocate_memory_cmd, 511 '_m' => \&dump_deallocate_memory_cmd, 512 # extended commands 513 'v' => \&dump_extended_cmd 514); 515 516#---------------------------------------------------------------------- 517# Hash that maps command characters to the appropriate functions using 518# the command character as the key and the value being a reference to 519# the dump function for the response to the command. 520#---------------------------------------------------------------------- 521our %rsp_callbacks = 522( 523 'c' => \&dump_stop_reply_packet, 524 'C' => \&dump_stop_reply_packet, 525 '?' => \&dump_stop_reply_packet, 526 'T' => \&dump_thread_is_alive_rsp, 527 'H' => \&dump_set_thread_rsp, 528 'q' => \&dump_general_query_rsp, 529 'g' => \&dump_read_regs_rsp, 530 'p' => \&dump_read_single_register_rsp, 531 'm' => \&dump_read_mem_rsp, 532 '_M' => \&dump_allocate_memory_rsp, 533 534 # extended commands 535 'v' => \&dump_extended_rsp, 536); 537 538 539sub dump_register_value 540{ 541 my $indent = shift; 542 my $arrayref = shift; 543 my $reg_num = shift; 544 545 if ($reg_num >= @$registers_aref) 546 { 547 printf("\tinvalid register index %d\n", $reg_num); 548 } 549 550 my $reg_href = $$registers_aref[$reg_num]; 551 my $reg_name = $reg_href->{name}; 552 if ($$arrayref[0] eq '#') 553 { 554 printf("\t%*s: error: EOS reached when trying to read register %d\n", $max_register_name_len, $reg_name, $reg_num); 555 } 556 557 my $reg_info = $reg_href->{info}; 558 my $reg_extract = $reg_info->{extract}; 559 my $reg_format = $reg_info->{format}; 560 my $reg_val = &$reg_extract($arrayref); 561 if ($indent) { 562 printf("\t%*s = $reg_format", $max_register_name_len, $reg_name, $reg_val); 563 } else { 564 printf("%s = $reg_format", $reg_name, $reg_val); 565 } 566} 567 568#---------------------------------------------------------------------- 569# Extract the command into an array of ASCII char strings for easy 570# processing 571#---------------------------------------------------------------------- 572sub extract_command 573{ 574 my $cmd_str = shift; 575 my @cmd_chars = split(/ */, $cmd_str); 576 if ($cmd_chars[0] ne '$') 577 { 578 # only set the current command if it isn't a reply 579 $curr_cmd = $cmd_chars[0]; 580 } 581 return @cmd_chars; 582} 583 584#---------------------------------------------------------------------- 585# Strip the 3 checksum array entries after we don't need them anymore 586#---------------------------------------------------------------------- 587sub strip_checksum 588{ 589 my $arrayref = shift; 590 splice(@$arrayref, -3); 591} 592 593#---------------------------------------------------------------------- 594# Dump all strings in array by joining them together with no space 595# between them 596#---------------------------------------------------------------------- 597sub dump_chars 598{ 599 print join('',@_); 600} 601 602#---------------------------------------------------------------------- 603# Check if the response is an error 'EXX' 604#---------------------------------------------------------------------- 605sub is_error_response 606{ 607 if ($_[0] eq 'E') 608 { 609 shift; 610 print "ERROR = " . join('',@_) . "\n"; 611 return 1; 612 } 613 return 0; 614} 615 616#---------------------------------------------------------------------- 617# 'H' command 618#---------------------------------------------------------------------- 619sub dump_set_thread_cmd 620{ 621 my $cmd = shift; 622 my $mod = shift; 623 print "set_thread ( $mod, " . join('',@_) . " )\n"; 624} 625 626#---------------------------------------------------------------------- 627# 'T' command 628#---------------------------------------------------------------------- 629our $T_cmd_tid = -1; 630sub dump_thread_is_alive_cmd 631{ 632 my $cmd = shift; 633 $T_cmd_tid = get_hex(\@_); 634 printf("thread_is_alive ( $tid_format )\n", $T_cmd_tid); 635} 636 637sub dump_thread_is_alive_rsp 638{ 639 my $rsp = join('',@_); 640 641 printf("thread_is_alive ( $tid_format ) =>", $T_cmd_tid); 642 if ($rsp eq 'OK') 643 { 644 print " alive.\n"; 645 } 646 else 647 { 648 print " dead.\n"; 649 } 650} 651 652#---------------------------------------------------------------------- 653# 'H' response 654#---------------------------------------------------------------------- 655sub dump_set_thread_rsp 656{ 657 if (!is_error_response(@_)) 658 { 659 print join('',@_) . "\n"; 660 } 661} 662 663#---------------------------------------------------------------------- 664# 'q' command 665#---------------------------------------------------------------------- 666our $gen_query_cmd; 667our $qRegisterInfo_reg_num = -1; 668sub dump_general_query_cmd 669{ 670 $gen_query_cmd = join('',@_); 671 if ($gen_query_cmd eq 'qC') 672 { 673 print 'get_current_pid ()'; 674 } 675 elsif ($gen_query_cmd eq 'qfThreadInfo') 676 { 677 print 'get_first_active_threads ()'; 678 } 679 elsif ($gen_query_cmd eq 'qsThreadInfo') 680 { 681 print 'get_subsequent_active_threads ()'; 682 } 683 elsif (index($gen_query_cmd, 'qThreadExtraInfo') == 0) 684 { 685 # qThreadExtraInfo,id 686 print 'get_thread_extra_info ()'; 687 } 688 elsif (index($gen_query_cmd, 'qThreadStopInfo') == 0) 689 { 690 # qThreadStopInfoXXXX 691 @_ = splice(@_, length('qThreadStopInfo')); 692 my $tid = get_addr(\@_); 693 printf('get_thread_stop_info ( thread = 0x%4.4x )', $tid); 694 } 695 elsif (index($gen_query_cmd, 'qSymbol:') == 0) 696 { 697 # qCRC:addr,length 698 print 'gdb_ready_to_serve_symbol_lookups ()'; 699 } 700 elsif (index($gen_query_cmd, 'qCRC:') == 0) 701 { 702 # qCRC:addr,length 703 @_ = splice(@_, length('qCRC:')); 704 my $address = get_addr(\@_); 705 shift @_; 706 my $length = join('', @_); 707 printf("compute_crc (addr = $addr_format, length = $length)", $address); 708 } 709 elsif (index($gen_query_cmd, 'qGetTLSAddr:') == 0) 710 { 711 # qGetTLSAddr:thread-id,offset,lm 712 @_ = splice(@_, length('qGetTLSAddr:')); 713 my ($tid, $offset, $lm) = split (/,/, join('', @_)); 714 print "get_thread_local_storage_addr (thread-id = $tid, offset = $offset, lm = $lm)"; 715 } 716 elsif ($gen_query_cmd eq 'qOffsets') 717 { 718 print 'get_section_offsets ()'; 719 } 720 elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) 721 { 722 @_ = splice(@_, length('qRegisterInfo')); 723 $qRegisterInfo_reg_num = get_hex(\@_); 724 725 printf "get_dynamic_register_info ($qRegisterInfo_reg_num)"; 726 } 727 else 728 { 729 print $gen_query_cmd; 730 } 731 print "\n"; 732} 733 734#---------------------------------------------------------------------- 735# 'q' response 736#---------------------------------------------------------------------- 737sub dump_general_query_rsp 738{ 739 my $gen_query_rsp = join('',@_); 740 my $gen_query_rsp_len = length ($gen_query_rsp); 741 if ($gen_query_cmd eq 'qC' and index($gen_query_rsp, 'QC') == 0) 742 { 743 shift @_; shift @_; 744 my $pid = get_hex(\@_); 745 printf("pid = $pid_format\n", $pid); 746 return; 747 } 748 elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) 749 { 750 if ($gen_query_rsp_len == 0) 751 { 752 print "$unimplemented_str\n"; 753 } 754 else 755 { 756 if (index($gen_query_rsp, 'name') == 0) 757 { 758 $qRegisterInfo_reg_num == 0 and $registers_aref = []; 759 760 my @name_and_values = split (/;/, $gen_query_rsp); 761 762 my $reg_name = undef; 763 my $byte_size = 0; 764 foreach (@name_and_values) 765 { 766 my ($name, $value) = split /:/; 767 if ($name eq "name") { $reg_name = $value; } 768 elsif ($name eq "bitsize") { $byte_size = $value / 8; last; } 769 } 770 if (defined $reg_name and $byte_size > 0) 771 { 772 if ($byte_size == 4) {push @$registers_aref, { name => $reg_name, info => $reg32_href };} 773 elsif ($byte_size == 8) {push @$registers_aref, { name => $reg_name, info => $reg64_href };} 774 elsif ($byte_size == 1) {push @$registers_aref, { name => $reg_name, info => $reg8_href };} 775 elsif ($byte_size == 2) {push @$registers_aref, { name => $reg_name, info => $reg16_href };} 776 elsif ($byte_size == 10) {push @$registers_aref, { name => $reg_name, info => $reg80_href };} 777 elsif ($byte_size == 12) {push @$registers_aref, { name => $reg_name, info => $float96_href };} 778 elsif ($byte_size == 16) {push @$registers_aref, { name => $reg_name, info => $reg128_href };} 779 elsif ($byte_size == 32) {push @$registers_aref, { name => $reg_name, info => $reg256_href };} 780 } 781 } 782 elsif ($gen_query_rsp_len == 3 and index($gen_query_rsp, 'E') == 0) 783 { 784 calculate_max_register_name_length(); 785 } 786 } 787 } 788 elsif ($gen_query_cmd =~ 'qThreadStopInfo') 789 { 790 dump_stop_reply_packet (@_); 791 } 792 if (dump_standard_response(\@_)) 793 { 794 # Do nothing... 795 } 796 else 797 { 798 print join('',@_) . "\n"; 799 } 800} 801 802#---------------------------------------------------------------------- 803# 'Q' command 804#---------------------------------------------------------------------- 805our $gen_set_cmd; 806sub dump_general_set_cmd 807{ 808 $gen_query_cmd = join('',@_); 809 if ($gen_query_cmd eq 'QStartNoAckMode') 810 { 811 print "StartNoAckMode ()" 812 } 813 elsif ($gen_query_cmd eq 'QThreadSuffixSupported') 814 { 815 $thread_suffix_supported = 1; 816 print "ThreadSuffixSupported ()" 817 } 818 elsif (index($gen_query_cmd, 'QSetMaxPayloadSize:') == 0) 819 { 820 @_ = splice(@_, length('QSetMaxPayloadSize:')); 821 my $max_payload_size = get_hex(\@_); 822 # QSetMaxPayloadSize:XXXX where XXXX is a hex length of the max 823 # packet payload size supported by gdb 824 printf("SetMaxPayloadSize ( 0x%x (%u))", $max_payload_size, $max_payload_size); 825 } 826 elsif (index ($gen_query_cmd, 'QSetSTDIN:') == 0) 827 { 828 @_ = splice(@_, length('QSetSTDIN:')); 829 printf ("SetSTDIN (path ='%s')\n", get_hex_string (\@_)); 830 } 831 elsif (index ($gen_query_cmd, 'QSetSTDOUT:') == 0) 832 { 833 @_ = splice(@_, length('QSetSTDOUT:')); 834 printf ("SetSTDOUT (path ='%s')\n", get_hex_string (\@_)); 835 } 836 elsif (index ($gen_query_cmd, 'QSetSTDERR:') == 0) 837 { 838 @_ = splice(@_, length('QSetSTDERR:')); 839 printf ("SetSTDERR (path ='%s')\n", get_hex_string (\@_)); 840 } 841 else 842 { 843 print $gen_query_cmd; 844 } 845 print "\n"; 846} 847 848#---------------------------------------------------------------------- 849# 'k' command 850#---------------------------------------------------------------------- 851sub dump_kill_cmd 852{ 853 my $cmd = shift; 854 print "kill (" . join('',@_) . ")\n"; 855} 856 857#---------------------------------------------------------------------- 858# 'g' command 859#---------------------------------------------------------------------- 860sub dump_read_regs_cmd 861{ 862 my $cmd = shift; 863 print "read_registers ()\n"; 864} 865 866#---------------------------------------------------------------------- 867# 'G' command 868#---------------------------------------------------------------------- 869sub dump_write_regs_cmd 870{ 871 print "write_registers:\n"; 872 my $cmd = shift; 873 foreach my $reg_href (@$registers_aref) 874 { 875 last if ($_[0] eq '#'); 876 my $reg_info_href = $reg_href->{info}; 877 my $reg_name = $reg_href->{name}; 878 my $reg_extract = $reg_info_href->{extract}; 879 my $reg_format = $reg_info_href->{format}; 880 my $reg_val = &$reg_extract(\@_); 881 printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); 882 } 883} 884 885sub dump_read_regs_rsp 886{ 887 print "read_registers () =>\n"; 888 if (!is_error_response(@_)) 889 { 890 # print join('',@_) . "\n"; 891 foreach my $reg_href (@$registers_aref) 892 { 893 last if ($_[0] eq '#'); 894 my $reg_info_href = $reg_href->{info}; 895 my $reg_name = $reg_href->{name}; 896 my $reg_extract = $reg_info_href->{extract}; 897 my $reg_format = $reg_info_href->{format}; 898 my $reg_val = &$reg_extract(\@_); 899 printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); 900 } 901 } 902} 903 904sub dump_read_single_register_rsp 905{ 906 dump_register_value(0, \@_, $reg_cmd_reg); 907 print "\n"; 908} 909 910#---------------------------------------------------------------------- 911# '_M' - allocate memory command (LLDB extension) 912# 913# Command: '_M' 914# Arg1: Hex byte size as big endian hex string 915# Separator: ',' 916# Arg2: permissions as string that must be a string that contains any 917# combination of 'r' (readable) 'w' (writable) or 'x' (executable) 918# 919# Returns: The address that was allocated as a big endian hex string 920# on success, else an error "EXX" where XX are hex bytes 921# that indicate an error code. 922# 923# Examples: 924# _M10,rw # allocate 16 bytes with read + write permissions 925# _M100,rx # allocate 256 bytes with read + execute permissions 926#---------------------------------------------------------------------- 927sub dump_allocate_memory_cmd 928{ 929 shift; shift; # shift off the '_' and the 'M' 930 my $byte_size = get_addr(\@_); 931 shift; # Skip ',' 932 printf("allocate_memory ( byte_size = %u (0x%x), permissions = %s)\n", $byte_size, $byte_size, join('',@_)); 933} 934 935sub dump_allocate_memory_rsp 936{ 937 if (@_ == 3 and $_[0] == 'E') 938 { 939 printf("allocated memory addr = ERROR (%s))\n", join('',@_)); 940 } 941 else 942 { 943 printf("allocated memory addr = 0x%s\n", join('',@_)); 944 } 945} 946 947#---------------------------------------------------------------------- 948# '_m' - deallocate memory command (LLDB extension) 949# 950# Command: '_m' 951# Arg1: Hex address as big endian hex string 952# 953# Returns: "OK" on success "EXX" on error 954# 955# Examples: 956# _m201000 # Free previously allocated memory at address 0x201000 957#---------------------------------------------------------------------- 958sub dump_deallocate_memory_cmd 959{ 960 shift; shift; # shift off the '_' and the 'm' 961 printf("deallocate_memory ( addr = 0x%s)\n", join('',@_)); 962} 963 964 965#---------------------------------------------------------------------- 966# 'p' command 967#---------------------------------------------------------------------- 968sub dump_read_single_register_cmd 969{ 970 my $cmd = shift; 971 $reg_cmd_reg = get_hex(\@_); 972 my $thread = get_thread_from_thread_suffix (\@_); 973 my $reg_href = $$registers_aref[$reg_cmd_reg]; 974 975 if (defined $thread) 976 { 977 print "read_register ( reg = \"$reg_href->{name}\", thread = $thread )\n"; 978 } 979 else 980 { 981 print "read_register ( reg = \"$reg_href->{name}\" )\n"; 982 } 983} 984 985 986#---------------------------------------------------------------------- 987# 'P' command 988#---------------------------------------------------------------------- 989sub dump_write_single_register_cmd 990{ 991 my $cmd = shift; 992 my $reg_num = get_hex(\@_); 993 shift (@_); # Discard the '=' 994 995 print "write_register ( "; 996 dump_register_value(0, \@_, $reg_num); 997 my $thread = get_thread_from_thread_suffix (\@_); 998 if (defined $thread) 999 { 1000 print ", thread = $thread"; 1001 } 1002 print " )\n"; 1003} 1004 1005#---------------------------------------------------------------------- 1006# 'm' command 1007#---------------------------------------------------------------------- 1008our $read_mem_address = 0; 1009sub dump_read_mem_cmd 1010{ 1011 my $cmd = shift; 1012 $read_mem_address = get_addr(\@_); 1013 shift; # Skip ',' 1014 printf("read_mem ( $addr_format, %s )\n", $read_mem_address, join('',@_)); 1015} 1016 1017#---------------------------------------------------------------------- 1018# 'm' response 1019#---------------------------------------------------------------------- 1020sub dump_read_mem_rsp 1021{ 1022 # If the memory read was 2 or 4 bytes, print it out in native format 1023 # instead of just as bytes. 1024 my $num_nibbles = @_; 1025 if ($num_nibbles == 2) 1026 { 1027 printf(" 0x%2.2x", get8(\@_)); 1028 } 1029 elsif ($num_nibbles == 4) 1030 { 1031 printf(" 0x%4.4x", get16(\@_)); 1032 } 1033 elsif ($num_nibbles == 8) 1034 { 1035 printf(" 0x%8.8x", get32(\@_)); 1036 } 1037 elsif ($num_nibbles == 16) 1038 { 1039 printf(" 0x%s", get64(\@_)); 1040 } 1041 else 1042 { 1043 my $curr_address = $read_mem_address; 1044 my $nibble; 1045 my $nibble_offset = 0; 1046 my $max_nibbles_per_line = 2 * $max_bytes_per_line; 1047 foreach $nibble (@_) 1048 { 1049 if (($nibble_offset % $max_nibbles_per_line) == 0) 1050 { 1051 ($nibble_offset > 0) and print "\n "; 1052 printf("$addr_format: ", $curr_address + $nibble_offset/2); 1053 } 1054 (($nibble_offset % 2) == 0) and print ' '; 1055 print $nibble; 1056 $nibble_offset++; 1057 } 1058 } 1059 print "\n"; 1060} 1061 1062#---------------------------------------------------------------------- 1063# 'c' command 1064#---------------------------------------------------------------------- 1065sub dump_continue_cmd 1066{ 1067 my $cmd = shift; 1068 my $address = -1; 1069 if (@_) 1070 { 1071 my $address = get_addr(\@_); 1072 printf("continue ($addr_format)\n", $address); 1073 } 1074 else 1075 { 1076 printf("continue ()\n"); 1077 } 1078} 1079 1080#---------------------------------------------------------------------- 1081# 'Css' continue (C) with signal (ss where 'ss' is two hex digits) 1082#---------------------------------------------------------------------- 1083sub dump_continue_with_signal_cmd 1084{ 1085 my $cmd = shift; 1086 my $address = -1; 1087 my $signal = get_hex(\@_); 1088 if (@_) 1089 { 1090 my $address = 0; 1091 if (@_ && $_[0] == ';') 1092 { 1093 shift; 1094 $address = get_addr(\@_); 1095 } 1096 } 1097 1098 if ($address != -1) 1099 { 1100 printf("continue_with_signal (signal = 0x%2.2x, address = $addr_format)\n", $signal, $address); 1101 } 1102 else 1103 { 1104 printf("continue_with_signal (signal = 0x%2.2x)\n", $signal); 1105 } 1106} 1107 1108#---------------------------------------------------------------------- 1109# 'A' command 1110#---------------------------------------------------------------------- 1111sub dump_A_command 1112{ 1113 my $cmd = get_exptected_char(\@_, 'A') or print "error: incorrect command letter for argument packet, exptected 'A'\n"; 1114 printf("set_program_arguments (\n"); 1115 do 1116 { 1117 my $arg_len = get_uint(\@_); 1118 get_exptected_char(\@_, ',') or die "error: missing comma after argument length...?\n"; 1119 my $arg_idx = get_uint(\@_); 1120 get_exptected_char(\@_, ',') or die "error: missing comma after argument number...?\n"; 1121 1122 my $arg = ''; 1123 my $num_hex8_bytes = $arg_len/2; 1124 for (1 .. $num_hex8_bytes) 1125 { 1126 $arg .= sprintf("%c", get8(\@_)) 1127 } 1128 printf(" <%3u> argv[%u] = '%s'\n", $arg_len, $arg_idx, $arg); 1129 if (@_ > 0) 1130 { 1131 get_exptected_char(\@_, ',') or die "error: missing comma after argument argument ASCII hex bytes...?\n"; 1132 } 1133 } while (@_ > 0); 1134 printf(" )\n"); 1135} 1136 1137 1138#---------------------------------------------------------------------- 1139# 'z' and 'Z' command 1140#---------------------------------------------------------------------- 1141sub dump_bp_wp_command 1142{ 1143 my $cmd = shift; 1144 my $type = shift; 1145 shift; # Skip ',' 1146 my $address = get_addr(\@_); 1147 shift; # Skip ',' 1148 my $length = join('',@_); 1149 if ($cmd eq 'z') 1150 { 1151 printf("remove $point_types[$type]($addr_format, %d)\n", $address, $length); 1152 } 1153 else 1154 { 1155 printf("insert $point_types[$type]($addr_format, %d)\n", $address, $length); 1156 } 1157} 1158 1159 1160#---------------------------------------------------------------------- 1161# 'X' command 1162#---------------------------------------------------------------------- 1163sub dump_write_mem_binary_cmd 1164{ 1165 my $cmd = shift; 1166 my $address = get_addr(\@_); 1167 shift; # Skip ',' 1168 1169 my ($length, $binary) = split(/:/, join('',@_)); 1170 printf("write_mem_binary ( $addr_format, %d, %s)\n", $address, $length, $binary); 1171 1172} 1173 1174#---------------------------------------------------------------------- 1175# 'M' command 1176#---------------------------------------------------------------------- 1177sub dump_write_mem_cmd 1178{ 1179 my $cmd = shift; 1180 my $address = get_addr(\@_); 1181 shift; # Skip ',' 1182 my ($length, $hex_bytes) = split(/:/, join('',@_)); 1183# printf("write_mem ( $addr_format, %d, %s)\n", $address, $length, $hex_bytes); 1184 printf("write_mem ( addr = $addr_format, len = %d (0x%x), bytes = ", $address, $length, $length); 1185 splice(@_, 0, length($length)+1); 1186 1187 my $curr_address = $address; 1188 my $nibble; 1189 my $nibble_count = 0; 1190 my $max_nibbles_per_line = 2 * $max_bytes_per_line; 1191 foreach $nibble (@_) 1192 { 1193 (($nibble_count % 2) == 0) and print ' '; 1194 print $nibble; 1195 $nibble_count++; 1196 } 1197 1198 # If the memory to write is 2 or 4 bytes, print it out in native format 1199 # instead of just as bytes. 1200 if (@_ == 4) 1201 { 1202 printf(" ( 0x%4.4x )", get16(\@_)); 1203 } 1204 elsif (@_ == 8) 1205 { 1206 printf(" ( 0x%8.8x )", get32(\@_)); 1207 } 1208 print " )\n"; 1209 1210} 1211 1212#---------------------------------------------------------------------- 1213# 'v' command 1214#---------------------------------------------------------------------- 1215our $extended_rsp_callback = 0; 1216sub dump_extended_cmd 1217{ 1218 $extended_rsp_callback = 0; 1219 if (join('', @_[0..4]) eq "vCont") 1220 { 1221 dump_extended_continue_cmd(splice(@_,5)); 1222 } 1223 elsif (join('', @_[0..11]) eq 'vAttachWait;') 1224 { 1225 dump_attach_wait_command (splice(@_,12)); 1226 } 1227} 1228 1229#---------------------------------------------------------------------- 1230# 'v' response 1231#---------------------------------------------------------------------- 1232sub dump_extended_rsp 1233{ 1234 if ($extended_rsp_callback) 1235 { 1236 &$extended_rsp_callback(@_); 1237 } 1238 $extended_rsp_callback = 0; 1239} 1240 1241#---------------------------------------------------------------------- 1242# 'vAttachWait' command 1243#---------------------------------------------------------------------- 1244sub dump_attach_wait_command 1245{ 1246 print "attach_wait ( "; 1247 while (@_) 1248 { 1249 printf("%c", get8(\@_)) 1250 } 1251 printf " )\n"; 1252 1253} 1254 1255#---------------------------------------------------------------------- 1256# 'vCont' command 1257#---------------------------------------------------------------------- 1258sub dump_extended_continue_cmd 1259{ 1260 print "extended_continue ( "; 1261 my $cmd = shift; 1262 if ($cmd eq '?') 1263 { 1264 print "list supported modes )\n"; 1265 $extended_rsp_callback = \&dump_extended_continue_rsp; 1266 } 1267 elsif ($cmd eq ';') 1268 { 1269 $extended_rsp_callback = \&dump_stop_reply_packet; 1270 my $i = 0; 1271 while ($#_ >= 0) 1272 { 1273 if ($i > 0) 1274 { 1275 print ", "; 1276 } 1277 my $continue_cmd = shift; 1278 my $tmp; 1279 if ($continue_cmd eq 'c') 1280 { 1281 print "continue"; 1282 } 1283 elsif ($continue_cmd eq 'C') 1284 { 1285 print "continue with signal "; 1286 print shift; 1287 print shift; 1288 } 1289 elsif ($continue_cmd eq 's') 1290 { 1291 print "step"; 1292 } 1293 elsif ($continue_cmd eq 'S') 1294 { 1295 print "step with signal "; 1296 print shift; 1297 print shift; 1298 } 1299 1300 if ($_[0] eq ':') 1301 { 1302 shift; # Skip ':' 1303 print " for thread "; 1304 while ($#_ >= 0) 1305 { 1306 $tmp = shift; 1307 if (length($tmp) > 0 && $tmp ne ';') { 1308 print $tmp; 1309 } else { 1310 last; 1311 } 1312 } 1313 } 1314 $i++; 1315 } 1316 1317 printf " )\n"; 1318 } 1319} 1320 1321#---------------------------------------------------------------------- 1322# 'vCont' response 1323#---------------------------------------------------------------------- 1324sub dump_extended_continue_rsp 1325{ 1326 if (scalar(@_) == 0) 1327 { 1328 print "$unimplemented_str\n"; 1329 } 1330 else 1331 { 1332 print "extended_continue supports " . join('',@_) . "\n"; 1333 } 1334} 1335 1336#---------------------------------------------------------------------- 1337# Dump the command ascii for any unknown commands 1338#---------------------------------------------------------------------- 1339sub dump_other_cmd 1340{ 1341 print "other = " . join('',@_) . "\n"; 1342} 1343 1344#---------------------------------------------------------------------- 1345# Check to see if the response was unsupported with appropriate checksum 1346#---------------------------------------------------------------------- 1347sub rsp_is_unsupported 1348{ 1349 return join('',@_) eq "#00"; 1350} 1351 1352#---------------------------------------------------------------------- 1353# Check to see if the response was "OK" with appropriate checksum 1354#---------------------------------------------------------------------- 1355sub rsp_is_OK 1356{ 1357 return join('',@_) eq "OK#9a"; 1358} 1359 1360#---------------------------------------------------------------------- 1361# Dump a response for an unknown command 1362#---------------------------------------------------------------------- 1363sub dump_other_rsp 1364{ 1365 print "other = " . join('',@_) . "\n"; 1366} 1367 1368#---------------------------------------------------------------------- 1369# Get a byte from the ascii string assuming that the 2 nibble ascii 1370# characters are in hex. 1371# 1372# The argument for this function needs to be a reference to an array 1373# that contains single character strings and the array will get 1374# updated by shifting characters off the front of it (no leading # "0x") 1375#---------------------------------------------------------------------- 1376sub get8 1377{ 1378 my $arrayref = shift; 1379 my $val = hex(shift(@$arrayref) . shift(@$arrayref)); 1380 return $val; 1381} 1382 1383#---------------------------------------------------------------------- 1384# Get a 16 bit integer and swap if $swap global is set to a non-zero 1385# value. 1386# 1387# The argument for this function needs to be a reference to an array 1388# that contains single character strings and the array will get 1389# updated by shifting characters off the front of it (no leading # "0x") 1390#---------------------------------------------------------------------- 1391sub get16 1392{ 1393 my $arrayref = shift; 1394 my $val = 0; 1395 if ($swap) 1396 { 1397 $val = get8($arrayref) | 1398 get8($arrayref) << 8; 1399 } 1400 else 1401 { 1402 $val = get8($arrayref) << 8 | 1403 get8($arrayref) ; 1404 } 1405 return $val; 1406} 1407 1408#---------------------------------------------------------------------- 1409# Get a 32 bit integer and swap if $swap global is set to a non-zero 1410# value. 1411# 1412# The argument for this function needs to be a reference to an array 1413# that contains single character strings and the array will get 1414# updated by shifting characters off the front of it (no leading # "0x") 1415#---------------------------------------------------------------------- 1416sub get32 1417{ 1418 my $arrayref = shift; 1419 my $val = 0; 1420 if ($swap) 1421 { 1422 $val = get8($arrayref) | 1423 get8($arrayref) << 8 | 1424 get8($arrayref) << 16 | 1425 get8($arrayref) << 24 ; 1426 } 1427 else 1428 { 1429 $val = get8($arrayref) << 24 | 1430 get8($arrayref) << 16 | 1431 get8($arrayref) << 8 | 1432 get8($arrayref) ; 1433 } 1434 return $val; 1435} 1436 1437#---------------------------------------------------------------------- 1438# Get a 64 bit hex value as a string 1439# 1440# The argument for this function needs to be a reference to an array 1441# that contains single character strings and the array will get 1442# updated by shifting characters off the front of it (no leading # "0x") 1443#---------------------------------------------------------------------- 1444sub get64 1445{ 1446 my $arrayref = shift; 1447 my $val = ''; 1448 my @nibbles; 1449 if ($swap) 1450 { 1451 push @nibbles, splice(@$arrayref, 14, 2); 1452 push @nibbles, splice(@$arrayref, 12, 2); 1453 push @nibbles, splice(@$arrayref, 10, 2); 1454 push @nibbles, splice(@$arrayref, 8, 2); 1455 push @nibbles, splice(@$arrayref, 6, 2); 1456 push @nibbles, splice(@$arrayref, 4, 2); 1457 push @nibbles, splice(@$arrayref, 2, 2); 1458 push @nibbles, splice(@$arrayref, 0, 2); 1459 } 1460 else 1461 { 1462 (@nibbles) = splice(@$arrayref, 0, ((64/8) * 2)); 1463 } 1464 $val = join('', @nibbles); 1465 return $val; 1466} 1467 1468#---------------------------------------------------------------------- 1469# Get a 80 bit hex value as a string 1470# 1471# The argument for this function needs to be a reference to an array 1472# that contains single character strings and the array will get 1473# updated by shifting characters off the front of it (no leading # "0x") 1474#---------------------------------------------------------------------- 1475sub get80 1476{ 1477 my $arrayref = shift; 1478 my $val = ''; 1479 my @nibbles; 1480 if ($swap) 1481 { 1482 push @nibbles, splice(@$arrayref, 18, 2); 1483 push @nibbles, splice(@$arrayref, 16, 2); 1484 push @nibbles, splice(@$arrayref, 14, 2); 1485 push @nibbles, splice(@$arrayref, 12, 2); 1486 push @nibbles, splice(@$arrayref, 10, 2); 1487 push @nibbles, splice(@$arrayref, 8, 2); 1488 push @nibbles, splice(@$arrayref, 6, 2); 1489 push @nibbles, splice(@$arrayref, 4, 2); 1490 push @nibbles, splice(@$arrayref, 2, 2); 1491 push @nibbles, splice(@$arrayref, 0, 2); 1492 } 1493 else 1494 { 1495 (@nibbles) = splice(@$arrayref, 0, ((80/8) * 2)); 1496 } 1497 $val = join('', @nibbles); 1498 return $val; 1499} 1500 1501#---------------------------------------------------------------------- 1502# Get a 96 bit hex value as a string 1503# 1504# The argument for this function needs to be a reference to an array 1505# that contains single character strings and the array will get 1506# updated by shifting characters off the front of it (no leading # "0x") 1507#---------------------------------------------------------------------- 1508sub get96 1509{ 1510 my $arrayref = shift; 1511 my $val = ''; 1512 my @nibbles; 1513 if ($swap) 1514 { 1515 push @nibbles, splice(@$arrayref, 22, 2); 1516 push @nibbles, splice(@$arrayref, 20, 2); 1517 push @nibbles, splice(@$arrayref, 18, 2); 1518 push @nibbles, splice(@$arrayref, 16, 2); 1519 push @nibbles, splice(@$arrayref, 14, 2); 1520 push @nibbles, splice(@$arrayref, 12, 2); 1521 push @nibbles, splice(@$arrayref, 10, 2); 1522 push @nibbles, splice(@$arrayref, 8, 2); 1523 push @nibbles, splice(@$arrayref, 6, 2); 1524 push @nibbles, splice(@$arrayref, 4, 2); 1525 push @nibbles, splice(@$arrayref, 2, 2); 1526 push @nibbles, splice(@$arrayref, 0, 2); 1527 } 1528 else 1529 { 1530 (@nibbles) = splice(@$arrayref, 0, ((96/8) * 2)); 1531 } 1532 $val = join('', @nibbles); 1533 return $val; 1534} 1535 1536#---------------------------------------------------------------------- 1537# Get a 128 bit hex value as a string 1538# 1539# The argument for this function needs to be a reference to an array 1540# that contains single character strings and the array will get 1541# updated by shifting characters off the front of it (no leading # "0x") 1542#---------------------------------------------------------------------- 1543sub get128 1544{ 1545 my $arrayref = shift; 1546 my $val = ''; 1547 my @nibbles; 1548 if ($swap) 1549 { 1550 push @nibbles, splice(@$arrayref, 30, 2); 1551 push @nibbles, splice(@$arrayref, 28, 2); 1552 push @nibbles, splice(@$arrayref, 26, 2); 1553 push @nibbles, splice(@$arrayref, 24, 2); 1554 push @nibbles, splice(@$arrayref, 22, 2); 1555 push @nibbles, splice(@$arrayref, 20, 2); 1556 push @nibbles, splice(@$arrayref, 18, 2); 1557 push @nibbles, splice(@$arrayref, 16, 2); 1558 push @nibbles, splice(@$arrayref, 14, 2); 1559 push @nibbles, splice(@$arrayref, 12, 2); 1560 push @nibbles, splice(@$arrayref, 10, 2); 1561 push @nibbles, splice(@$arrayref, 8, 2); 1562 push @nibbles, splice(@$arrayref, 6, 2); 1563 push @nibbles, splice(@$arrayref, 4, 2); 1564 push @nibbles, splice(@$arrayref, 2, 2); 1565 push @nibbles, splice(@$arrayref, 0, 2); 1566 } 1567 else 1568 { 1569 (@nibbles) = splice(@$arrayref, 0, ((128/8) * 2)); 1570 } 1571 $val = join('', @nibbles); 1572 return $val; 1573} 1574 1575#---------------------------------------------------------------------- 1576# Get a 256 bit hex value as a string 1577# 1578# The argument for this function needs to be a reference to an array 1579# that contains single character strings and the array will get 1580# updated by shifting characters off the front of it (no leading # "0x") 1581#---------------------------------------------------------------------- 1582sub get256 1583{ 1584 my $arrayref = shift; 1585 my $val = ''; 1586 my @nibbles; 1587 if ($swap) 1588 { 1589 push @nibbles, splice(@$arrayref, 62, 2); 1590 push @nibbles, splice(@$arrayref, 60, 2); 1591 push @nibbles, splice(@$arrayref, 58, 2); 1592 push @nibbles, splice(@$arrayref, 56, 2); 1593 push @nibbles, splice(@$arrayref, 54, 2); 1594 push @nibbles, splice(@$arrayref, 52, 2); 1595 push @nibbles, splice(@$arrayref, 50, 2); 1596 push @nibbles, splice(@$arrayref, 48, 2); 1597 push @nibbles, splice(@$arrayref, 46, 2); 1598 push @nibbles, splice(@$arrayref, 44, 2); 1599 push @nibbles, splice(@$arrayref, 42, 2); 1600 push @nibbles, splice(@$arrayref, 40, 2); 1601 push @nibbles, splice(@$arrayref, 38, 2); 1602 push @nibbles, splice(@$arrayref, 36, 2); 1603 push @nibbles, splice(@$arrayref, 34, 2); 1604 push @nibbles, splice(@$arrayref, 32, 2); 1605 push @nibbles, splice(@$arrayref, 30, 2); 1606 push @nibbles, splice(@$arrayref, 28, 2); 1607 push @nibbles, splice(@$arrayref, 26, 2); 1608 push @nibbles, splice(@$arrayref, 24, 2); 1609 push @nibbles, splice(@$arrayref, 22, 2); 1610 push @nibbles, splice(@$arrayref, 20, 2); 1611 push @nibbles, splice(@$arrayref, 18, 2); 1612 push @nibbles, splice(@$arrayref, 16, 2); 1613 push @nibbles, splice(@$arrayref, 14, 2); 1614 push @nibbles, splice(@$arrayref, 12, 2); 1615 push @nibbles, splice(@$arrayref, 10, 2); 1616 push @nibbles, splice(@$arrayref, 8, 2); 1617 push @nibbles, splice(@$arrayref, 6, 2); 1618 push @nibbles, splice(@$arrayref, 4, 2); 1619 push @nibbles, splice(@$arrayref, 2, 2); 1620 push @nibbles, splice(@$arrayref, 0, 2); 1621 } 1622 else 1623 { 1624 (@nibbles) = splice(@$arrayref, 0, ((256/8) * 2)); 1625 } 1626 $val = join('', @nibbles); 1627 return $val; 1628} 1629 1630#---------------------------------------------------------------------- 1631# Get a an unsigned integer value by grabbing items off the front of 1632# the array stopping when a non-digit char string is encountered. 1633# 1634# The argument for this function needs to be a reference to an array 1635# that contains single character strings and the array will get 1636# updated by shifting characters off the front of it 1637#---------------------------------------------------------------------- 1638sub get_uint 1639{ 1640 my $arrayref = shift; 1641 @$arrayref == 0 and return 0; 1642 my $val = 0; 1643 while ($$arrayref[0] =~ /[0-9]/) 1644 { 1645 $val = $val * 10 + int(shift(@$arrayref)); 1646 } 1647 return $val; 1648} 1649 1650#---------------------------------------------------------------------- 1651# Check the first character in the array and if it matches the expected 1652# character, return that character, else return undef; 1653# 1654# The argument for this function needs to be a reference to an array 1655# that contains single character strings and the array will get 1656# updated by shifting characters off the front of it. If the expected 1657# character doesn't match, it won't touch the array. If the first 1658# character does match, it will shift it off and return it. 1659#---------------------------------------------------------------------- 1660sub get_exptected_char 1661{ 1662 my $arrayref = shift; 1663 my $expected_char = shift; 1664 if ($expected_char eq $$arrayref[0]) 1665 { 1666 return shift(@$arrayref); 1667 } 1668 return undef; 1669} 1670#---------------------------------------------------------------------- 1671# Get a hex value by grabbing items off the front of the array and 1672# stopping when a non-hex char string is encountered. 1673# 1674# The argument for this function needs to be a reference to an array 1675# that contains single character strings and the array will get 1676# updated by shifting characters off the front of it (no leading # "0x") 1677#---------------------------------------------------------------------- 1678sub get_hex 1679{ 1680 my $arrayref = shift; 1681 my $my_swap = @_ ? shift : 0; 1682 my $shift = 0; 1683 my $val = 0; 1684 while ($$arrayref[0] =~ /[0-9a-fA-F]/) 1685 { 1686 if ($my_swap) 1687 { 1688 my $byte = hex(shift(@$arrayref)) << 4 | hex(shift(@$arrayref)); 1689 $val |= $byte << $shift; 1690 $shift += 8; 1691 } 1692 else 1693 { 1694 $val <<= 4; 1695 $val |= hex(shift(@$arrayref)); 1696 } 1697 } 1698 return $val; 1699} 1700 1701#---------------------------------------------------------------------- 1702# Get an address value by grabbing items off the front of the array. 1703# 1704# The argument for this function needs to be a reference to an array 1705# that contains single character strings and the array will get 1706# updated by shifting characters off the front of it (no leading # "0x") 1707#---------------------------------------------------------------------- 1708sub get_addr 1709{ 1710 get_hex(shift); 1711} 1712 1713sub get_hex_string 1714{ 1715 my $arrayref = shift; 1716 my $str = ''; 1717 while ($$arrayref[0] =~ /[0-9a-fA-F]/ and $$arrayref[1] =~ /[0-9a-fA-F]/) 1718 { 1719 my $hi_nibble = hex(shift(@$arrayref)); 1720 my $lo_nibble = hex(shift(@$arrayref)); 1721 my $byte = ($hi_nibble << 4) | $lo_nibble; 1722 $str .= chr($byte); 1723 } 1724 return $str; 1725} 1726 1727sub dump_stop_reply_data 1728{ 1729 while ($#_ >= 0) 1730 { 1731 last unless ($_[0] ne '#'); 1732 1733 1734 my $key = ''; 1735 my $value = ''; 1736 if ($_[0] =~ /[0-9a-fA-F]/ && $_[1] =~ /[0-9a-fA-F]/) 1737 { 1738 my $reg_num = get8(\@_); 1739 shift(@_); # Skip ':' 1740 if (defined ($registers_aref) && $reg_num < @$registers_aref) 1741 { 1742 dump_register_value(1, \@_, $reg_num); 1743 print "\n"; 1744 shift(@_); # Skip ';' 1745 next; 1746 } 1747 $key = sprintf("reg %u", $reg_num); 1748 } 1749 my $char; 1750 1751 if (length($key) == 0) 1752 { 1753 while (1) 1754 { 1755 $char = shift(@_); 1756 if (length($char) == 0 or $char eq ':' or $char eq '#') { last; } 1757 $key .= $char; 1758 } 1759 } 1760 1761 while (1) 1762 { 1763 $char = shift(@_); 1764 if (length($char) == 0 or $char eq ';' or $char eq '#') { last; } 1765 $value .= $char; 1766 } 1767 printf("\t%*s = %s\n", $max_register_name_len, $key, $value); 1768 } 1769} 1770 1771#---------------------------------------------------------------------- 1772# Dumps a Stop Reply Packet which happens in response to a step, 1773# continue, last signal, and probably a few other commands. 1774#---------------------------------------------------------------------- 1775sub dump_stop_reply_packet 1776{ 1777 my $what = shift(@_); 1778 if ($what eq 'S') 1779 { 1780 print 'signal ( 0x' . shift(@_) . shift(@_) . " )\n"; 1781 } 1782 elsif ($what eq 'T') 1783 { 1784 print 'signal ( 0x' . shift(@_) . shift(@_) . " )\n"; 1785 dump_stop_reply_data (@_); 1786 } 1787 elsif ($what eq 'W') 1788 { 1789 print 'process_exited( ' . shift(@_) . shift(@_) . " )\n"; 1790 } 1791 elsif ($what eq 'X') 1792 { 1793 print 'process_terminated( ' . shift(@_) . shift(@_) . " )\n"; 1794 } 1795 elsif ($what eq 'O') 1796 { 1797 my $console_output = ''; 1798 my $num_hex8_bytes = @_/2; 1799 for (1 .. $num_hex8_bytes) 1800 { 1801 $console_output .= sprintf("%c", get8(\@_)) 1802 } 1803 1804 print "program_console_output('$console_output')\n"; 1805 } 1806} 1807 1808#---------------------------------------------------------------------- 1809# '?' command 1810#---------------------------------------------------------------------- 1811sub dump_last_signal_cmd 1812{ 1813 my $cmd = shift; 1814 print 'last_signal (' . join('',@_) . ")\n"; 1815} 1816 1817sub dump_raw_command 1818{ 1819 my $cmd_aref = shift; 1820 my $callback_ref; 1821 $curr_cmd = $$cmd_aref[0]; 1822 $curr_cmd eq '_' and $curr_cmd .= $$cmd_aref[1]; 1823 1824 $callback_ref = $cmd_callbacks{$curr_cmd}; 1825 if ($callback_ref) 1826 { 1827 &$callback_ref(@$cmd_aref); 1828 } 1829 else 1830 { 1831 # Strip the command byte for responses since we injected that above 1832 dump_other_cmd(@$cmd_aref); 1833 } 1834} 1835 1836sub dump_standard_response 1837{ 1838 my $cmd_aref = shift; 1839 1840 my $cmd_len = scalar(@$cmd_aref); 1841 if ($cmd_len == 0) 1842 { 1843 print "$unimplemented_str\n"; 1844 return 1; 1845 } 1846 1847 my $response = join('', @$cmd_aref); 1848 if ($response eq 'OK') 1849 { 1850 print "$success_str\n"; 1851 return 1; 1852 } 1853 1854 if ($cmd_len == 3 and index($response, 'E') == 0) 1855 { 1856 print "ERROR: " . substr($response, 1) . "\n"; 1857 return 1; 1858 } 1859 1860 return 0; 1861} 1862sub dump_raw_response 1863{ 1864 my $cmd_aref = shift; 1865 my $callback_ref; 1866 1867 $callback_ref = $rsp_callbacks{$curr_cmd}; 1868 1869 if ($callback_ref) 1870 { 1871 &$callback_ref(@$cmd_aref); 1872 } 1873 else 1874 { 1875 dump_standard_response($cmd_aref) or dump_other_rsp(@$cmd_aref); 1876 } 1877 1878} 1879#---------------------------------------------------------------------- 1880# Dumps any command and handles simple error checking on the responses 1881# for commands that are unsupported or OK. 1882#---------------------------------------------------------------------- 1883sub dump_command 1884{ 1885 my $cmd_str = shift; 1886 1887 # Dump the original command string if verbose is on 1888 if ($opt_v) 1889 { 1890 print "dump_command($cmd_str)\n "; 1891 } 1892 1893 my @cmd_chars = extract_command($cmd_str); 1894 my $is_cmd = 1; 1895 1896 my $cmd = $cmd_chars[0]; 1897 if ($cmd eq '$') 1898 { 1899 $is_cmd = 0; # Note that this is a reply 1900 $cmd = $curr_cmd; # set the command byte appropriately 1901 shift @cmd_chars; # remove the '$' from the cmd bytes 1902 } 1903 1904 # Check for common responses across all commands and handle them 1905 # if we can 1906 if ( $is_cmd == 0 ) 1907 { 1908 if (rsp_is_unsupported(@cmd_chars)) 1909 { 1910 print "$unimplemented_str\n"; 1911 return; 1912 } 1913 elsif (rsp_is_OK(@cmd_chars)) 1914 { 1915 print "$success_str\n"; 1916 return; 1917 } 1918 # Strip the checksum information for responses 1919 strip_checksum(\@cmd_chars); 1920 } 1921 1922 my $callback_ref; 1923 if ($is_cmd) { 1924 $callback_ref = $cmd_callbacks{$cmd}; 1925 } else { 1926 $callback_ref = $rsp_callbacks{$cmd}; 1927 } 1928 1929 if ($callback_ref) 1930 { 1931 &$callback_ref(@cmd_chars); 1932 } 1933 else 1934 { 1935 # Strip the command byte for responses since we injected that above 1936 if ($is_cmd) { 1937 dump_other_cmd(@cmd_chars); 1938 } else { 1939 dump_other_rsp(@cmd_chars); 1940 } 1941 1942 } 1943} 1944 1945 1946#---------------------------------------------------------------------- 1947# Process a gdbserver log line by looking for getpkt and putkpt and 1948# tossing any other lines. 1949#---------------------------------------------------------------------- 1950sub process_log_line 1951{ 1952 my $line = shift; 1953 #($opt_v and $opt_g) and print "# $line"; 1954 my $extract_cmd = 0; 1955 if ($line =~ /getpkt /) 1956 { 1957 $extract_cmd = 1; 1958 print "\n--> "; 1959 } 1960 elsif ($line =~ /putpkt /) 1961 { 1962 $extract_cmd = 1; 1963 print "<-- "; 1964 } 1965 elsif ($line =~ /.*Sent: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) 1966 { 1967 $opt_g and print "maintenance dump-packets command: $1\n"; 1968 my @raw_cmd_bytes = split(/ */, $1); 1969 print "\n--> "; 1970 dump_raw_command(\@raw_cmd_bytes); 1971 process_log_line($2); 1972 } 1973 elsif ($line =~ /.*Recvd: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) 1974 { 1975 $opt_g and print "maintenance dump-packets reply: $1\n"; 1976 my @raw_rsp_bytes = split(/ */, $1); 1977 print "<-- "; 1978 dump_raw_response(\@raw_rsp_bytes); 1979 print "\n"; 1980 } 1981 elsif ($line =~ /getpkt: (.*)/) 1982 { 1983 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) 1984 { 1985 $opt_g and print "command: $1\n"; 1986 my @raw_cmd_bytes = split(/ */, $1); 1987 print "--> "; 1988 dump_raw_command(\@raw_cmd_bytes); 1989 } 1990 elsif ($1 =~ /\+/) 1991 { 1992 #print "--> ACK\n"; 1993 } 1994 elsif ($1 =~ /-/) 1995 { 1996 #print "--> NACK\n"; 1997 } 1998 } 1999 elsif ($line =~ /putpkt: (.*)/) 2000 { 2001 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) 2002 { 2003 $opt_g and print "response: $1\n"; 2004 my @raw_rsp_bytes = split(/ */, $1); 2005 print "<-- "; 2006 dump_raw_response(\@raw_rsp_bytes); 2007 print "\n"; 2008 } 2009 elsif ($1 =~ /\+/) 2010 { 2011 #print "<-- ACK\n"; 2012 } 2013 elsif ($1 =~ /-/) 2014 { 2015 #print "<-- NACK\n"; 2016 } 2017 } 2018 elsif ($line =~ /send packet: (.*)/) 2019 { 2020 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) 2021 { 2022 $opt_g and print "command: $1\n"; 2023 my @raw_cmd_bytes = split(/ */, $1); 2024 print "--> "; 2025 dump_raw_command(\@raw_cmd_bytes); 2026 } 2027 elsif ($1 =~ /\+/) 2028 { 2029 #print "--> ACK\n"; 2030 } 2031 elsif ($1 =~ /-/) 2032 { 2033 #print "--> NACK\n"; 2034 } 2035 } 2036 elsif ($line =~ /read packet: (.*)/) 2037 { 2038 if ($1 =~ /\$([^#]*)#[0-9a-fA-F]{2}/) 2039 { 2040 $opt_g and print "response: $1\n"; 2041 my @raw_rsp_bytes = split(/ */, $1); 2042 print "<-- "; 2043 dump_raw_response(\@raw_rsp_bytes); 2044 print "\n"; 2045 } 2046 elsif ($1 =~ /\+/) 2047 { 2048 #print "<-- ACK\n"; 2049 } 2050 elsif ($1 =~ /-/) 2051 { 2052 #print "<-- NACK\n"; 2053 } 2054 } 2055 elsif ($line =~ /Sending packet: \$([^#]+)#[0-9a-fA-F]{2}\.\.\.(.*)/) 2056 { 2057 $opt_g and print "command: $1\n"; 2058 my @raw_cmd_bytes = split(/ */, $1); 2059 print "\n--> "; 2060 dump_raw_command(\@raw_cmd_bytes); 2061 process_log_line($2); 2062 } 2063 elsif ($line =~ /Packet received: (.*)/) 2064 { 2065 $opt_g and print "response: $1\n"; 2066 my @raw_rsp_bytes = split(/ */, $1); 2067 print "<-- "; 2068 dump_raw_response(\@raw_rsp_bytes); 2069 print "\n"; 2070 } 2071 2072 if ($extract_cmd) 2073 { 2074 my $beg = index($line, '("') + 2; 2075 my $end = rindex($line, '");'); 2076 dump_command(substr($line, $beg, $end - $beg)); 2077 } 2078} 2079 2080 2081our $line_num = 0; 2082while(<>) 2083{ 2084 $line_num++; 2085 $opt_q or printf("# %5d: $_", $line_num); 2086 process_log_line($_); 2087} 2088 2089 2090 2091 2092 2093 2094