diff --git a/.gdb/breakpoints.gdb b/.gdb/breakpoints.gdb new file mode 100644 index 0000000..bd1b832 --- /dev/null +++ b/.gdb/breakpoints.gdb @@ -0,0 +1,121 @@ +define bpl + info breakpoints +end +document bpl +List all breakpoints. +end + + +define bp + if $argc != 1 + help bp + else + break $arg0 + end +end +document bp +Set breakpoint. +Usage: bp LOCATION +LOCATION may be a line number, function name, or "*" and an address. +To break on a symbol you must enclose symbol name inside "". +Example: +bp "[NSControl stringValue]" +Or else you can use directly the break command (break [NSControl stringValue]) +end + + +define bpc + if $argc != 1 + help bpc + else + clear $arg0 + end +end +document bpc +Clear breakpoint. +Usage: bpc LOCATION +LOCATION may be a line number, function name, or "*" and an address. +end + + +define bpe + if $argc != 1 + help bpe + else + enable $arg0 + end +end +document bpe +Enable breakpoint with number NUM. +Usage: bpe NUM +end + + +define bpd + if $argc != 1 + help bpd + else + disable $arg0 + end +end +document bpd +Disable breakpoint with number NUM. +Usage: bpd NUM +end + + +define bpt + if $argc != 1 + help bpt + else + tbreak $arg0 + end +end +document bpt +Set a temporary breakpoint. +This breakpoint will be automatically deleted when hit!. +Usage: bpt LOCATION +LOCATION may be a line number, function name, or "*" and an address. +end + + +define bpm + if $argc != 1 + help bpm + else + awatch $arg0 + end +end +document bpm +Set a read/write breakpoint on EXPRESSION, e.g. *address. +Usage: bpm EXPRESSION +end + + +define bhb + if $argc != 1 + help bhb + else + hb $arg0 + end +end +document bhb +Set hardware assisted breakpoint. +Usage: bhb LOCATION +LOCATION may be a line number, function name, or "*" and an address. +end + + +define bht + if $argc != 1 + help bht + else + thbreak $arg0 + end +end +document bht +Set a temporary hardware breakpoint. +This breakpoint will be automatically deleted when hit! +Usage: bht LOCATION +LOCATION may be a line number, function name, or "*" and an address. +end diff --git a/.gdb/c++.gdb b/.gdb/c++.gdb new file mode 100644 index 0000000..729b3ef --- /dev/null +++ b/.gdb/c++.gdb @@ -0,0 +1,7 @@ +python +import sys +from os.path import expanduser +sys.path.insert(0, expanduser('~/.gdb')) +from libstdcxx.v6.printers import register_libstdcxx_printers +register_libstdcxx_printers (None) +end diff --git a/.gdb/carbon.gdb b/.gdb/carbon.gdb new file mode 100644 index 0000000..e828bbe --- /dev/null +++ b/.gdb/carbon.gdb @@ -0,0 +1,49 @@ +define print-char + if ($arg0 > 0xff) + print "not a character" + "" + else + if ($arg0 == '\n') + printf "\\n" + else + if ($arg0 == '\t') + printf "\\t" + else + if ($arg0 == '\r') + printf "\\r" + else + if ($arg0 == '\'') + printf "\\'" + else + if (($arg0 < 0x20) || ($arg0 >= 0x7f)) + printf "\\%03o", $arg0 + else + printf "%c", $arg0 + end + end + end + end + end + end +end +document print-char +Print a single character in a readable fashion. +end + +define print-ostype + set $tmp0 = ($arg0) + printf "'" + set $tmp1 = (($tmp0 & 0xff000000) >> 24) + print-char $tmp1 + set $tmp1 = (($tmp0 & 0x00ff0000) >> 16) + print-char $tmp1 + set $tmp1 = (($tmp0 & 0x0000ff00) >> 8) + print-char $tmp1 + set $tmp1 = (($tmp0 & 0x000000ff) >> 0) + print-char $tmp1 + printf "'" + printf "\n" +end +document print-ostype +Print a value as an OSType (four-byte character string). +end diff --git a/.gdb/cpu-arm.gdb b/.gdb/cpu-arm.gdb new file mode 100644 index 0000000..33b663a --- /dev/null +++ b/.gdb/cpu-arm.gdb @@ -0,0 +1,549 @@ +# Initialize these variables else comparisons will fail for colouring +set $oldr0 = 0 +set $oldr1 = 0 +set $oldr2 = 0 +set $oldr3 = 0 +set $oldr4 = 0 +set $oldr5 = 0 +set $oldr6 = 0 +set $oldr7 = 0 +set $oldr8 = 0 +set $oldr9 = 0 +set $oldr10 = 0 +set $oldr11 = 0 +set $oldr12 = 0 +set $oldr13 = 0 +set $oldr14 = 0 +set $oldr15 = 0 +set $oldsp = 0 +set $oldlr = 0 + +define flagsarm + # conditional flags are + # negative/less than (N), bit 31 of CPSR + # zero (Z), bit 30 + # Carry/Borrow/Extend (C), bit 29 + # Overflow (V), bit 28 + # negative/less than (N), bit 31 of CPSR + if ($cpsr->n & 1) + printf "N " + set $_n_flag = 1 + else + printf "n " + set $_n_flag = 0 + end + # zero (Z), bit 30 + if ($cpsr->z & 1) + printf "Z " + set $_z_flag = 1 + else + printf "z " + set $_z_flag = 0 + end + # Carry/Borrow/Extend (C), bit 29 + if ($cpsr->c & 1) + printf "C " + set $_c_flag = 1 + else + printf "c " + set $_c_flag = 0 + end + # Overflow (V), bit 28 + if ($cpsr->v & 1) + printf "V " + set $_v_flag = 1 + else + printf "v " + set $_v_flag = 0 + end + # Sticky overflow (Q), bit 27 + if ($cpsr->q & 1) + printf "Q " + set $_q_flag = 1 + else + printf "q " + set $_q_flag = 0 + end + # Java state bit (J), bit 24 + # When T=1: + # J = 0 The processor is in Thumb state. + # J = 1 The processor is in ThumbEE state. + if ($cpsr->j & 1) + printf "J " + set $_j_flag = 1 + else + printf "j " + set $_j_flag = 0 + end + # Data endianness bit (E), bit 9 + if ($cpsr->e & 1) + printf "E " + set $_e_flag = 1 + else + printf "e " + set $_e_flag = 0 + end + # Imprecise abort disable bit (A), bit 8 + # The A bit is set to 1 automatically. It is used to disable imprecise data aborts. + # It might not be writable in the Nonsecure state if the AW bit in the SCR register is reset. + if ($cpsr->a & 1) + printf "A " + set $_a_flag = 1 + else + printf "a " + set $_a_flag = 0 + end + # IRQ disable bit (I), bit 7 + # When the I bit is set to 1, IRQ interrupts are disabled. + if ($cpsr->i & 1) + printf "I " + set $_i_flag = 1 + else + printf "i " + set $_i_flag = 0 + end + # FIQ disable bit (F), bit 6 + # When the F bit is set to 1, FIQ interrupts are disabled. + # FIQ can be nonmaskable in the Nonsecure state if the FW bit in SCR register is reset. + if ($cpsr->f & 1) + printf "F " + set $_f_flag = 1 + else + printf "f " + set $_f_flag = 0 + end + # Thumb state bit (F), bit 5 + # if 1 then the processor is executing in Thumb state or ThumbEE state depending on the J bit + if ($cpsr->t & 1) + printf "T " + set $_t_flag = 1 + else + printf "t " + set $_t_flag = 0 + end + # TODO: GE bit ? +end +document flagsarm +Auxiliary function to set ARM cpu flags. +end + + +define eflagsarm + printf " N <%d> Z <%d> C <%d> V <%d>", \ + ($cpsr->n & 1), ($cpsr->z & 1), \ + ($cpsr->c & 1), ($cpsr->v & 1) + printf " Q <%d> J <%d> GE <%d> E <%d> A <%d>", \ + ($cpsr->q & 1), ($cpsr->j & 1), \ + ($cpsr->ge), ($cpsr->e & 1), ($cpsr->a & 1) + printf " I <%d> F <%d> T <%d> \n", \ + ($cpsr->i & 1), ($cpsr->f & 1), \ + ($cpsr->t & 1) +end +document eflagsarm +Auxillary function to print ARM eflags register. +end + +define cpsr + eflagsarm +end +document cpsr +Print cpsr register. +end + + +define regarm + printf " " + echo \033[32m + printf "R0:" + if $r0 + if ($r0 != $oldr0 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r0 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R1:" + if $r1 + if ($r1 != $oldr1 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r1 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R2:" + if $r2 + if ($r2 != $oldr2 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r2 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R3:" + if $r3 + if ($r3 != $oldr3 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X", $r3 + else + printf " 0x%08X", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "R4:" + if $r4 + if ($r4 != $oldr4 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r4 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R5:" + if $r5 + if ($r5 != $oldr5 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r5 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R6:" + if $r6 + if ($r6 != $oldr6 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r6 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R7:" + if $r7 + if ($r7 != $oldr7 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r7 + else + printf " 0x%08X ", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "R8:" + if $r8 + if ($r8 != $oldr8 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r8 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R9:" + if $r9 + if ($r9 != $oldr9 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r9 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R10:" + if $r10 + if ($r10 != $oldr10 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r10 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "R11:" + if $r11 + if ($r11 != $oldr11 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r11 + else + printf " 0x%08X ", 0 + end + + dumpjump + printf "\n " + + echo \033[32m + printf "R12:" + if $r12 + if ($r12 != $oldr12 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $r12 + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "SP:" + if $sp + if ($sp != $oldsp && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $sp + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "LR:" + if $lr + if ($lr != $oldlr && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $lr + else + printf " 0x%08X ", 0 + end + + echo \033[32m + printf "PC:" + echo \033[0m + if $pc + printf " 0x%08X ", $pc + else + printf " 0x%08X ", 0 + end + + echo \033[1m\033[4m\033[31m + flags + echo \033[0m + printf "\n" + + if ($SHOWREGCHANGES == 1) + if $r0 + set $oldr0 = $r0 + end + if $r1 + set $oldr1 = $r1 + end + if $r2 + set $oldr2 = $r2 + end + if $r3 + set $oldr3 = $r3 + end + if $r4 + set $oldr4 = $r4 + end + if $r5 + set $oldr5 = $r5 + end + if $r6 + set $oldr6 = $r6 + end + if $r7 + set $oldr7 = $r7 + end + if $r8 + set $oldr8 = $r8 + end + if $r9 + set $oldr9 = $r9 + end + if $r10 + set $oldr10 = $r10 + end + if $r11 + set $oldr11 = $r11 + end + if $r12 + set $oldr12 = $r12 + end + if $sp + set $oldsp = $sp + end + if $lr + set $oldlr = $lr + end + end +end +document regarm +Auxiliary function to display ARM registers. +end + + +define stepoframeworkarm + # bl and bx opcodes + # bx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 0 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 0 + # blx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 1 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 1 + # bl # => ARM bits 27-24: 1 0 1 1 ; Thumb bits: 15-11: 1 1 1 1 0 + # blx # => ARM bits 31-25: 1 1 1 1 1 0 1 ; Thumb bits: 15-11: 1 1 1 1 0 + set $_nextaddress = 0 + + # ARM Mode + if ($_t_flag == 0) + set $_branchesint = *(unsigned int*) $pc + set $_bit31 = ($_branchesint >> 0x1F) & 1 + set $_bit30 = ($_branchesint >> 0x1E) & 1 + set $_bit29 = ($_branchesint >> 0x1D) & 1 + set $_bit28 = ($_branchesint >> 0x1C) & 1 + set $_bit27 = ($_branchesint >> 0x1B) & 1 + set $_bit26 = ($_branchesint >> 0x1A) & 1 + set $_bit25 = ($_branchesint >> 0x19) & 1 + set $_bit24 = ($_branchesint >> 0x18) & 1 + set $_bit23 = ($_branchesint >> 0x17) & 1 + set $_bit22 = ($_branchesint >> 0x16) & 1 + set $_bit21 = ($_branchesint >> 0x15) & 1 + set $_bit20 = ($_branchesint >> 0x14) & 1 + set $_bit7 = ($_branchesint >> 0x7) & 1 + set $_bit6 = ($_branchesint >> 0x6) & 1 + set $_bit5 = ($_branchesint >> 0x5) & 1 + set $_bit4 = ($_branchesint >> 0x4) & 1 + + # set $_lastbyte = *(unsigned char *)($pc+3) + # set $_bits2724 = $_lastbyte & 0x1 + # set $_bits3128 = $_lastbyte >> 4 + # if ($_bits3128 == 0xF) + # set $_bits2724 = $_lastbyte & 0xA + # set $_bits2724 = $_bits2724 >> 1 + # end + # set $_previousbyte = *(unsigned char *)($pc+2) + # set $_bits2320 = $_previousbyte >> 4 + # printf "bits2724: %x bits2320: %x\n", $_bits2724, $_bits2320 + + if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 0 && $_bit4 == 1) + printf "Found a bx Rn\n" + set $_nextaddress = $pc + 0x4 + end + if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 1 && $_bit4 == 1) + printf "Found a blx Rn\n" + set $_nextaddress = $pc + 0x4 + end + if ($_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1 && $_bit24 == 1) + printf "Found a bl #\n" + set $_nextaddress = $pc + 0x4 + end + if ($_bit31 == 1 && $_bit30 == 1 && $_bit29 == 1 && $_bit28 == 1 && $_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1) + printf "Found a blx #\n" + set $_nextaddress = $pc + 0x4 + end + # Thumb Mode + else + # 32 bits instructions in Thumb are divided into two half words + set $_hw1 = *(unsigned short*) ($pc) + set $_hw2 = *(unsigned short*) ($pc + 2) + + # bl/blx (immediate) + # hw1: bits 15-11: 1 1 1 1 0 + # hw2: bits 15-14: 1 1 ; BL bit 12: 1 ; BLX bit 12: 0 + if (($_hw1 >> 0xC) == 0xF && (($_hw1 >> 0xB) & 1) == 0) + if (((($_hw2 >> 0xF) & 1) == 1) && ((($_hw2 >> 0xE) & 1) == 1)) + set $_nextaddress = $pc + 0x4 + end + end + end + # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue + if ($_nextaddress != 0) + tbreak *$_nextaddress + continue + printf "[StepO] Next address will be %x\n", $_nextaddress + # else we just single step + else + nexti + end +end +document stepoframeworkarm +Auxiliary function to stepo command. +end + + +define cfnarm + set $tempflag = $cpsr->n + if ($tempflag & 1) + set $cpsr->n = $tempflag & ~0x1 + else + set $cpsr->n = $tempflag | 0x1 + end +end +document cfnarm +Auxiliary function to change ARM Negative/Less Than Flag. +end + + +define cfcarm + # Carry/Borrow/Extend (C), bit 29 + set $tempflag = $cpsr->c + if ($tempflag & 1) + set $cpsr->c = $tempflag & ~0x1 + else + set $cpsr->c = $tempflag | 0x1 + end +end +document cfc +Auxiliary function to change ARM Carry Flag. +end + + +define cfzarm + # zero (Z), bit 30 + set $tempflag = $cpsr->z + if ($tempflag & 1) + set $cpsr->z = $tempflag & ~0x1 + else + set $cpsr->z = $tempflag | 0x1 + end +end +document cfzarm +Auxiliary function to change ARM Zero Flag. +end + + +# Overflow (V), bit 28 +define cfvarm + set $tempflag = $cpsr->v + if ($tempflag & 1) + set $cpsr->v = $tempflag & ~0x1 + else + set $cpsr->v = $tempflag | 0x1 + end +end +document cfvarm +Auxiliary function to change ARM Overflow Flag. +end + + +define hookstoparm + # Display instructions formats + if $ARMOPCODES == 1 + set arm show-opcode-bytes 1 + else + set arm show-opcode-bytes 1 + end +end +document hookstoparm +!!! FOR INTERNAL USE ONLY - DO NOT CALL !!! +end diff --git a/.gdb/cpu-mips.gdb b/.gdb/cpu-mips.gdb new file mode 100644 index 0000000..9607c29 --- /dev/null +++ b/.gdb/cpu-mips.gdb @@ -0,0 +1,495 @@ +# Initialize these variables else comparisons will fail for colouring +set $oldv0 = 0 +set $oldv1 = 0 + +set $olda0 = 0 +set $olda1 = 0 +set $olda2 = 0 +set $olda3 = 0 + +set $oldt0 = 0 +set $oldt1 = 0 +set $oldt2 = 0 +set $oldt3 = 0 +set $oldt4 = 0 +set $oldt5 = 0 +set $oldt6 = 0 +set $oldt8 = 0 +set $oldt9 = 0 + +set $olds0 = 0 +set $olds1 = 0 +set $olds2 = 0 +set $olds3 = 0 +set $olds4 = 0 +set $olds5 = 0 +set $olds6 = 0 +set $olds7 = 0 +set $olds8 = 0 + +set $oldkt0 = 0 +set $oldkt1 = 0 + +set $oldgp = 0 +set $oldsp = 0 +set $oldra = 0 +set $oldat = 0 + + +define regmips + # 64bits stuff + printf " " + + echo \033[32m + printf "V0: " + echo \033[0m + if $v0 + if ($v0 != $oldv0 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $v0 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "V1: " + echo \033[0m + if $v1 + if ($v1 != $oldv1 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $v1 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "A0: " + echo \033[0m + if $a0 + if ($a0 != $olda0 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $a0 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "A1: " + echo \033[0m + if $a1 + if ($a1 != $olda1 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $a1 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "A2: " + echo \033[0m + if $a2 + if ($a2 != $oldt5 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $a2 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "A3: " + echo \033[0m + if $a3 + if ($a3 != $olda3 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $a3 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T0: " + echo \033[0m + if $t0 + if ($t0 != $oldt0 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t0 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T1: " + echo \033[0m + if $t1 + if ($t1 != $oldt1 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t1 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T2: " + echo \033[0m + if $t2 + if ($t2 != $oldt2 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t2 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T3: " + echo \033[0m + if $t3 + if ($t3 != $oldt3 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $t3 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "T4: " + echo \033[0m + if $t4 + if ($t4 != $oldt4 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t4 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T5: " + echo \033[0m + if $t5 + if ($t5 != $oldt5 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t5 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T6: " + echo \033[0m + if $t6 + if ($t6 != $oldt6 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t6 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T7: " + echo \033[0m + if $t7 + if ($t7 != $oldt7 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t7 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "T8: " + echo \033[0m + if $t8 + if ($t8 != $oldt8 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $t8 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "T9: " + echo \033[0m + if $t9 + if ($t9 != $oldt9 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $t9 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S0: " + echo \033[0m + if $s0 + if ($s0 != $olds0 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s0 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S1: " + echo \033[0m + if $s1 + if ($s1 != $olds1 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s1 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S2: " + echo \033[0m + if $s2 + if ($s2 != $olds2 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s2 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S3: " + echo \033[0m + if $s3 + if ($s3 != $olds3 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $s3 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "S4: " + echo \033[0m + if $s4 + if ($s4 != $olds4 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s4 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S5: " + echo \033[0m + if $s5 + if ($s5 != $olds5 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s5 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S6: " + echo \033[0m + if $s6 + if ($s6 != $olds6 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s6 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S7: " + echo \033[0m + if $s7 + if ($s7 != $olds7 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $s7 + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "S8: " + echo \033[0m + if $s8 + if ($s8 != $olds8 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $s8 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n\n " + + echo \033[32m + printf "0: " + echo \033[0m + printf " 0x%016lX ", $zero + echo \033[32m + printf "AT: " + echo \033[0m + printf " 0x%016lX ", $at + echo \033[32m + printf "GP: " + echo \033[0m + printf " 0x%016lX ", $gp + echo \033[32m + printf "SP: " + echo \033[0m + printf " 0x%016lX", $sp + + + # Newline + printf "\n " + + echo \033[32m + printf "KT0:" + echo \033[0m + printf " 0x%016lX ", $kt0 + echo \033[32m + printf "KT1:" + echo \033[0m + printf " 0x%016lX ", $kt1 + echo \033[0m + + + # End of registers + printf "\n" + + if ($SHOWREGCHANGES == 1) + if $v0 + set $oldv0 = $v0 + end + if $v1 + set $oldv1 = $v1 + end + + if $a0 + set $olda0 = $a0 + end + if $a1 + set $olda1 = $a1 + end + if $a2 + set $olda2 = $a2 + end + if $a3 + set $olda3 = $a3 + end + + if $t0 + set $oldt0 = $t0 + end + if $t1 + set $oldt1 = $t1 + end + if $t2 + set $oldt2 = $t2 + end + if $t3 + set $oldt3 = $t3 + end + if $t4 + set $oldt4 = $t4 + end + if $t5 + set $oldt5 = $t5 + end + if $t6 + set $oldt6 = $t6 + end + if $t7 + set $oldt8 = $t8 + end + if $t9 + set $oldt9 = $t9 + end + + if $s0 + set $olds0 = $s0 + end + if $s1 + set $olds1 = $s1 + end + if $s2 + set $olds2 = $s2 + end + if $s3 + set $olds3 = $s3 + end + if $s4 + set $olds4 = $s4 + end + if $s5 + set $olds5 = $s5 + end + if $s6 + set $olds6 = $s6 + end + if $s7 + set $olds8 = $s8 + end + + if $kt0 + set $oldkt0 = $kt0 + end + if $kt1 + set $oldkt1 = $kt1 + end + + if $gp + set $oldgp = $gp + end + if $sp + set $oldsp = $sp + end + if $ra + set $oldra = $ra + end + if $at + set $oldat = $at + end + end +end +document regmips +Auxiliary function to display MIPS registers. +end diff --git a/.gdb/cpu-x86.gdb b/.gdb/cpu-x86.gdb new file mode 100644 index 0000000..1a89cb9 --- /dev/null +++ b/.gdb/cpu-x86.gdb @@ -0,0 +1,832 @@ +# Initialize these variables else comparisons will fail for colouring +set $oldrax = 0 +set $oldrbx = 0 +set $oldrcx = 0 +set $oldrdx = 0 +set $oldrsi = 0 +set $oldrdi = 0 +set $oldrbp = 0 +set $oldrsp = 0 +set $oldr8 = 0 +set $oldr9 = 0 +set $oldr10 = 0 +set $oldr11 = 0 +set $oldr12 = 0 +set $oldr13 = 0 +set $oldr14 = 0 +set $oldr15 = 0 + +set $oldeax = 0 +set $oldebx = 0 +set $oldecx = 0 +set $oldedx = 0 +set $oldesi = 0 +set $oldedi = 0 +set $oldebp = 0 +set $oldesp = 0 + + +define flagsx86 + # OF (overflow) flag + if (($eflags >> 0xB) & 1) + printf "O " + set $_of_flag = 1 + else + printf "o " + set $_of_flag = 0 + end + # DF (direction) flag + if (($eflags >> 0xA) & 1) + printf "D " + else + printf "d " + end + # IF (interrupt enable) flag + if (($eflags >> 9) & 1) + printf "I " + else + printf "i " + end + # TF (trap) flag + if (($eflags >> 8) & 1) + printf "T " + else + printf "t " + end + # SF (sign) flag + if (($eflags >> 7) & 1) + printf "S " + set $_sf_flag = 1 + else + printf "s " + set $_sf_flag = 0 + end + # ZF (zero) flag + if (($eflags >> 6) & 1) + printf "Z " + set $_zf_flag = 1 + else + printf "z " + set $_zf_flag = 0 + end + # AF (adjust) flag + if (($eflags >> 4) & 1) + printf "A " + else + printf "a " + end + # PF (parity) flag + if (($eflags >> 2) & 1) + printf "P " + set $_pf_flag = 1 + else + printf "p " + set $_pf_flag = 0 + end + # CF (carry) flag + if ($eflags & 1) + printf "C " + set $_cf_flag = 1 + else + printf "c " + set $_cf_flag = 0 + end + printf "\n" +end +document flagsx86 +Auxiliary function to set X86/X64 cpu flags. +end + + +define eflagsx86 + printf " OF <%d> DF <%d> IF <%d> TF <%d>", \ + (($eflags >> 0xB) & 1), (($eflags >> 0xA) & 1), \ + (($eflags >> 9) & 1), (($eflags >> 8) & 1) + printf " SF <%d> ZF <%d> AF <%d> PF <%d> CF <%d>\n", \ + (($eflags >> 7) & 1), (($eflags >> 6) & 1), \ + (($eflags >> 4) & 1), (($eflags >> 2) & 1), ($eflags & 1) + printf " ID <%d> VIP <%d> VIF <%d> AC <%d>", \ + (($eflags >> 0x15) & 1), (($eflags >> 0x14) & 1), \ + (($eflags >> 0x13) & 1), (($eflags >> 0x12) & 1) + printf " VM <%d> RF <%d> NT <%d> IOPL <%d>\n", \ + (($eflags >> 0x11) & 1), (($eflags >> 0x10) & 1), \ + (($eflags >> 0xE) & 1), (($eflags >> 0xC) & 3) +end +document eflagsx86 +Auxillary function to print X86/X64 eflags register. +end + + +define regx86_64 + # 64bits stuff + printf " " + + # RAX + echo \033[32m + printf "RAX:" + echo \033[0m + if $rax + if ($rax != $oldrax && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rax + else + printf " 0x%016lX ", 0 + end + + # RBX + echo \033[32m + printf "RBX:" + echo \033[0m + if $rbx + if ($rbx != $oldrbx && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rbx + else + printf " 0x%016lX ", 0 + end + + # RCX + echo \033[32m + printf "RCX:" + echo \033[0m + if $rcx + if ($rcx != $oldrcx && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rcx + else + printf " 0x%016lX ", 0 + end + + # RDX + echo \033[32m + printf "RDX:" + echo \033[0m + if $rdx + if ($rdx != $oldrdx && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rdx + else + printf " 0x%016lX ", 0 + end + + echo \033[1m\033[4m\033[31m + flags + echo \033[0m + printf " " + + # RSI + echo \033[32m + printf "RSI:" + echo \033[0m + if $rsi + if ($rsi != $oldrsi && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rsi + else + printf " 0x%016lX ", 0 + end + + # RDI + echo \033[32m + printf "RDI:" + echo \033[0m + if $rdi + if ($rdi != $oldrdi && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rdi + else + printf " 0x%016lX ", 0 + end + + # RBP + echo \033[32m + printf "RBP:" + echo \033[0m + if $rbp + if ($rbp != $oldrbp && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rbp + else + printf " 0x%016lX ", 0 + end + + # RSP + echo \033[32m + printf "RSP:" + echo \033[0m + if $rsp + if ($rsp != $oldrsp && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $rsp + else + printf " 0x%016lX ", 0 + end + + echo \033[32m + printf "RIP:" + echo \033[0m + if $rip + printf " 0x%016lX", $rip + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + # R8 + echo \033[32m + printf "R8 :" + echo \033[0m + if $r8 + if ($r8 != $oldr8 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r8 + else + printf " 0x%016lX ", 0 + end + + # R9 + echo \033[32m + printf "R9 :" + echo \033[0m + if $r9 + if ($r9 != $oldr9 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r9 + else + printf " 0x%016lX ", 0 + end + + # R10 + echo \033[32m + printf "R10:" + echo \033[0m + if $r10 + if ($r10 != $oldr10 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r10 + else + printf " 0x%016lX ", 0 + end + + # R11 + echo \033[32m + printf "R11:" + echo \033[0m + if $r11 + if ($r11 != $oldr11 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r11 + else + printf " 0x%016lX ", 0 + end + + # R12 + echo \033[32m + printf "R12:" + echo \033[0m + if $r12 + if ($r12 != $oldr12 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX", $r12 + else + printf " 0x%016lX", 0 + end + + + # Newline + printf "\n " + + # R13 + echo \033[32m + printf "R13:" + echo \033[0m + if $r13 + if ($r13 != $oldr13 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r13 + else + printf " 0x%016lX ", 0 + end + + # R14 + echo \033[32m + printf "R14:" + echo \033[0m + if $r14 + if ($r14 != $oldr14 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r14 + else + printf " 0x%016lX ", 0 + end + + # R15 + echo \033[32m + printf "R15:" + echo \033[0m + if $r15 + if ($r15 != $oldr15 && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%016lX ", $r15 + else + printf " 0x%016lX ", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "CS:" + echo \033[0m + if $cs + printf " %04X ", $cs + else + printf " %04X ", 0 + end + echo \033[32m + printf "DS:" + echo \033[0m + if $ds + printf " %04X ", $ds + else + printf " %04X ", 0 + end + echo \033[32m + printf "ES:" + echo \033[0m + if $es + printf " %04X ", $es + else + printf " %04X ", 0 + end + echo \033[32m + printf "FS:" + echo \033[0m + if $fs + printf " %04X ", $fs + else + printf " %04X ", 0 + end + echo \033[32m + printf "GS:" + echo \033[0m + if $gs + printf " %04X ", $gs + else + printf " %04X ", 0 + end + echo \033[32m + printf "SS:" + echo \033[0m + if $ss + printf " %04X", $ss + else + printf " %04X ", 0 + end + echo \033[0m + + if ($SHOWREGCHANGES == 1) + if $rax + set $oldrax = $rax + end + if $rbx + set $oldrbx = $rbx + end + if $rcx + set $oldrcx = $rcx + end + if $rdx + set $oldrdx = $rdx + end + if $rsi + set $oldrsi = $rsi + end + if $rdi + set $oldrdi = $rdi + end + if $rbp + set $oldrbp = $rbp + end + if $rsp + set $oldrsp = $rsp + end + if $r8 + set $oldr8 = $r8 + end + if $r9 + set $oldr9 = $r9 + end + if $r10 + set $oldr10 = $r10 + end + if $r11 + set $oldr11 = $r11 + end + if $r12 + set $oldr12 = $r12 + end + if $r13 + set $oldr13 = $r13 + end + if $r14 + set $oldr14 = $r14 + end + if $r15 + set $oldr15 = $r15 + end + end +end +document regx86_64 +Auxiliary function to display X86_64 registers. +end + + +define regx86 + printf " " + # EAX + echo \033[32m + printf "EAX:" + echo \033[0m + if $eax + if ($eax != $oldeax && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $eax + else + printf " 0x%08X ", 0 + end + + # EBX + echo \033[32m + printf "EBX:" + echo \033[0m + if $ebx + if ($ebx != $oldebx && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $ebx + else + printf " 0x%08X ", 0 + end + + # ECX + echo \033[32m + printf "ECX:" + echo \033[0m + if $ecx + if ($ecx != $oldecx && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $ecx + else + printf " 0x%08X ", 0 + end + + # EDX + if $edx + if ($edx != $oldedx && $SHOWREGCHANGES == 1) + echo \033[32m + printf "EDX:" + echo \033[31m + printf " 0x%08X ", $edx + else + echo \033[32m + printf "EDX:" + echo \033[0m + printf " 0x%08X ", $edx + end + else + printf "EDX:" + echo \033[0m + printf " 0x%08X ", 0 + end + + echo \033[1m\033[4m\033[31m + flags + echo \033[0m + + + # Newline + printf "\n " + + # ESI + echo \033[32m + printf "ESI:" + echo \033[0m + if $esi + if ($esi != $oldesi && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $esi + else + printf " 0x%08X ", 0 + end + + # EDI + echo \033[32m + printf "EDI:" + echo \033[0m + if $edi + if ($edi != $oldedi && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $edi + else + printf " 0x%08X ", 0 + end + + # EBP + echo \033[32m + printf "EBP:" + echo \033[0m + if $ebp + if ($ebp != $oldebp && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $ebp + else + printf " 0x%08X ", 0 + end + + # ESP + echo \033[32m + printf "ESP:" + echo \033[0m + if $esp + if ($esp != $oldesp && $SHOWREGCHANGES == 1) + echo \033[31m + end + printf " 0x%08X ", $esp + else + printf " 0x%08X ", 0 + end + + # EIP + echo \033[32m + printf "EIP:" + echo \033[0m + if $eip + printf " 0x%08X", $eip + else + printf " 0x%08X", 0 + end + + + # Newline + printf "\n " + + echo \033[32m + printf "CS:" + echo \033[0m + if $cs + printf " %04X ", $cs + else + printf " %04X ", 0 + end + echo \033[32m + printf "DS:" + echo \033[0m + if $ds + printf " %04X ", $ds + else + printf " %04X ", 0 + end + echo \033[32m + printf "ES:" + echo \033[0m + if $es + printf " %04X ", $es + else + printf " %04X ", 0 + end + echo \033[32m + printf "FS:" + echo \033[0m + if $fs + printf " %04X ", $fs + else + printf " %04X ", 0 + end + echo \033[32m + printf "GS:" + echo \033[0m + if $gs + printf " %04X ", $gs + else + printf " %04X ", 0 + end + echo \033[32m + printf "SS:" + echo \033[0m + if $ss + printf " %04X ", $ss + else + printf " %04X ", 0 + end + echo \033[0m + + if ($SHOWREGCHANGES == 1) + if $eax + set $oldeax = $eax + end + if $ebx + set $oldebx = $ebx + end + if $ecx + set $oldecx = $ecx + end + if $edx + set $oldedx = $edx + end + if $esi + set $oldesi = $esi + end + if $edi + set $oldedi = $edi + end + if $ebp + set $oldebp = $ebp + end + if $esp + set $oldesp = $esp + end + end +end +document regx86 +Auxiliary function to display X86 registers. +end + + +define smallregisters + if ($X86_64 == 1) + #64bits stuff + # from rax + set $eax = $rax & 0xffffffff + set $ax = $rax & 0xffff + set $al = $ax & 0xff + set $ah = $ax >> 8 + # from rbx + set $ebx = $rbx & 0xffffffff + set $bx = $rbx & 0xffff + set $bl = $bx & 0xff + set $bh = $bx >> 8 + # from rcx + set $ecx = $rcx & 0xffffffff + set $cx = $rcx & 0xffff + set $cl = $cx & 0xff + set $ch = $cx >> 8 + # from rdx + set $edx = $rdx & 0xffffffff + set $dx = $rdx & 0xffff + set $dl = $dx & 0xff + set $dh = $dx >> 8 + # from rsi + set $esi = $rsi & 0xffffffff + set $si = $rsi & 0xffff + # from rdi + set $edi = $rdi & 0xffffffff + set $di = $rdi & 0xffff + #32 bits stuff + end + + if ($X86 == 1) + # from eax + set $ax = $eax & 0xffff + set $al = $ax & 0xff + set $ah = $ax >> 8 + # from ebx + set $bx = $ebx & 0xffff + set $bl = $bx & 0xff + set $bh = $bx >> 8 + # from ecx + set $cx = $ecx & 0xffff + set $cl = $cx & 0xff + set $ch = $cx >> 8 + # from edx + set $dx = $edx & 0xffff + set $dl = $dx & 0xff + set $dh = $dx >> 8 + # from esi + set $si = $esi & 0xffff + # from edi + set $di = $edi & 0xffff + end +end +document smallregisters +Create the 16 and 8 bit cpu registers (gdb doesn't have them by default). +And 32bits if we are dealing with 64bits binaries. +end + + +define stepoframeworkx86 + ## we know that an opcode starting by 0xE8 has a fixed length + ## for the 0xFF opcodes, we can enumerate what is possible to have + # first we grab the first 3 bytes from the current program counter + set $_byte1 = *(unsigned char *) $pc + set $_byte2 = *(unsigned char *) ($pc+1) + set $_byte3 = *(unsigned char *) ($pc+2) + # and start the fun + # if it's a 0xE8 opcode, the total instruction size will be 5 bytes + # so we can simply calculate the next address and use a temporary breakpoint ! Voila :) + set $_nextaddress = 0 + # this one is the must useful for us !!! + if ($_byte1 == 0xE8) + set $_nextaddress = $pc + 0x5 + else + # just other cases we might be interested in... maybe this should be removed since the 0xE8 opcode is the one we will use more + # this is a big fucking mess and can be improved for sure :) I don't like the way it is ehehehe + if ($_byte1 == 0xFF) + # call *%eax (0xFFD0) || call *%edx (0xFFD2) || call *(%ecx) (0xFFD1) || call (%eax) (0xFF10) || call *%esi (0xFFD6) || call *%ebx (0xFFD3) || call DWORD PTR [edx] (0xFF12) + if ($_byte2 == 0xD0 || $_byte2 == 0xD1 || $_byte2 == 0xD2 || $_byte2 == 0xD3 || $_byte2 == 0xD6 || $_byte2 == 0x10 || $_byte2 == 0x11 || $_byte2 == 0xD7 || $_byte2 == 0x12) + set $_nextaddress = $pc + 0x2 + end + # call *0x??(%ebp) (0xFF55??) || call *0x??(%esi) (0xFF56??) || call *0x??(%edi) (0xFF5F??) || call *0x??(%ebx) + # call *0x??(%edx) (0xFF52??) || call *0x??(%ecx) (0xFF51??) || call *0x??(%edi) (0xFF57??) || call *0x??(%eax) (0xFF50??) + if ($_byte2 == 0x55 || $_byte2 == 0x56 || $_byte2 == 0x5F || $_byte2 == 0x53 || $_byte2 == 0x52 || $_byte2 == 0x51 || $_byte2 == 0x57 || $_byte2 == 0x50) + set $_nextaddress = $pc + 0x3 + end + # call *0x????????(%ebx) (0xFF93????????) || + if ($_byte2 == 0x93 || $_byte2 == 0x94 || $_byte2 == 0x90 || $_byte2 == 0x92 || $_byte2 == 0x95) + set $_nextaddress = $pc + 6 + end + # call *0x????????(%ebx,%eax,4) (0xFF94??????????) + if ($_byte2 == 0x94) + set $_nextaddress = $pc + 7 + end + end + end + # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue + if ($_nextaddress != 0) + if ($arg0 == 1) + thbreak *$_nextaddress + else + tbreak *$_nextaddress + end + continue + # else we just single step + else + nexti + end +end +document stepoframeworkx86 +Auxiliary function to stepo command. +end + + +define cfcx86 + # Carry/Borrow/Extend (C), bit 29 + if ($eflags & 1) + set $eflags = $eflags & ~0x1 + else + set $eflags = $eflags | 0x1 + end +end +document cfcx86 +Auxiliary function to change x86 Carry Flag. +end + + +define cfzx86 + # zero (Z), bit 30 + if (($eflags >> 6) & 1) + set $eflags = $eflags & ~0x40 + else + set $eflags = $eflags | 0x40 + end +end +document cfzx86 +Auxiliary function to change x86 Zero Flag. +end + + +define hookstopx86 + # Display instructions formats + if $X86FLAVOR == 0 + set disassembly-flavor intel + else + set disassembly-flavor att + end +end +document hookstopx86 +!!! FOR INTERNAL USE ONLY - DO NOT CALL !!! +end diff --git a/.gdb/cpu.gdb b/.gdb/cpu.gdb new file mode 100644 index 0000000..ef8ff8d --- /dev/null +++ b/.gdb/cpu.gdb @@ -0,0 +1,503 @@ +source ~/.gdb/cpu-arm.gdb +source ~/.gdb/cpu-x86.gdb +source ~/.gdb/cpu-mips.gdb + +define flags + # call the auxiliary functions based on target cpu + if ($ARM == 1) + flagsarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + flagsx86 + end +end +document flags +Print flags register. +end + +define eflags + # call the auxiliary functions based on target cpu + if $ARM == 1 + eflagsarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + eflagsx86 + end +end +document eflags +Print eflags register. +end + + +define reg + if $ARM == 1 + regarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + if ($X86_64 == 1) + regx86_64 + else + regx86 + end + # call smallregisters + smallregisters + # display conditional jump routine + if ($X86_64 == 1) + printf "\t\t\t\t" + end + dumpjump + printf "\n" + end + + if ($MIPS == 1) + regmips + end +end +document reg +Print CPU registers. +end + + +# _______________eflags commands______________ +# conditional flags are +# negative/less than (N), bit 31 of CPSR +# zero (Z), bit 30 +# Carry/Borrow/Extend (C), bit 29 +# Overflow (V), bit 28 + +# negative/less than (N), bit 31 of CPSR +define cfn + if $ARM == 1 + cfnarm + end +end +document cfn +Change Negative/Less Than Flag. +end + + +define cfc + # Carry/Borrow/Extend (C), bit 29 + if $ARM == 1 + cfcarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + cfcx86 + end +end +document cfc +Change Carry Flag. +end + + +define cfp + if (($eflags >> 2) & 1) + set $eflags = $eflags & ~0x4 + else + set $eflags = $eflags | 0x4 + end +end +document cfp +Change Parity Flag. +end + + +define cfa + if (($eflags >> 4) & 1) + set $eflags = $eflags & ~0x10 + else + set $eflags = $eflags | 0x10 + end +end +document cfa +Change Auxiliary Carry Flag. +end + + +define cfz + # zero (Z), bit 30 + if $ARM == 1 + cfzarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + cfzx86 + end +end +document cfz +Change Zero Flag. +end + + +define cfs + if (($eflags >> 7) & 1) + set $eflags = $eflags & ~0x80 + else + set $eflags = $eflags | 0x80 + end +end +document cfs +Change Sign Flag. +end + + +define cft + if (($eflags >> 8) & 1) + set $eflags = $eflags & ~0x100 + else + set $eflags = $eflags | 0x100 + end +end +document cft +Change Trap Flag. +end + + +define cfi + if (($eflags >> 9) & 1) + set $eflags = $eflags & ~0x200 + else + set $eflags = $eflags | 0x200 + end +end +document cfi +Change Interrupt Flag. +Only privileged applications (usually the OS kernel) may modify IF. +This only applies to protected mode (real mode code may always modify IF). +end + + +define cfd + if (($eflags >> 0xA) & 1) + set $eflags = $eflags & ~0x400 + else + set $eflags = $eflags | 0x400 + end +end +document cfd +Change Direction Flag. +end + + +define cfo + if (($eflags >> 0xB) & 1) + set $eflags = $eflags & ~0x800 + else + set $eflags = $eflags | 0x800 + end +end +document cfo +Change Overflow Flag. +end + + +# Overflow (V), bit 28 +define cfv + if $ARM == 1 + cfvarm + end +end +document cfv +Change Overflow Flag. +end + + +# ____________________cflow___________________ +define print_insn_type + if $argc != 1 + help print_insn_type + else + if ($arg0 < 0 || $arg0 > 5) + printf "UNDEFINED/WRONG VALUE" + end + if ($arg0 == 0) + printf "UNKNOWN" + end + if ($arg0 == 1) + printf "JMP" + end + if ($arg0 == 2) + printf "JCC" + end + if ($arg0 == 3) + printf "CALL" + end + if ($arg0 == 4) + printf "RET" + end + if ($arg0 == 5) + printf "INT" + end + end +end +document print_insn_type +Print human-readable mnemonic for the instruction type (usually $INSN_TYPE). +Usage: print_insn_type INSN_TYPE_NUMBER +end + + +define get_insn_type + if $argc != 1 + help get_insn_type + else + set $INSN_TYPE = 0 + set $_byte1 = *(unsigned char *) $arg0 + if ($_byte1 == 0x9A || $_byte1 == 0xE8) + # "call" + set $INSN_TYPE = 3 + end + if ($_byte1 >= 0xE9 && $_byte1 <= 0xEB) + # "jmp" + set $INSN_TYPE = 1 + end + if ($_byte1 >= 0x70 && $_byte1 <= 0x7F) + # "jcc" + set $INSN_TYPE = 2 + end + if ($_byte1 >= 0xE0 && $_byte1 <= 0xE3) + # "jcc" + set $INSN_TYPE = 2 + end + if ($_byte1 == 0xC2 || $_byte1 == 0xC3 || $_byte1 == 0xCA || \ + $_byte1 == 0xCB || $_byte1 == 0xCF) + # "ret" + set $INSN_TYPE = 4 + end + if ($_byte1 >= 0xCC && $_byte1 <= 0xCE) + # "int" + set $INSN_TYPE = 5 + end + if ($_byte1 == 0x0F) + # two-byte opcode + set $_byte2 = *(unsigned char *) ($arg0 + 1) + if ($_byte2 >= 0x80 && $_byte2 <= 0x8F) + # "jcc" + set $INSN_TYPE = 2 + end + end + if ($_byte1 == 0xFF) + # opcode extension + set $_byte2 = *(unsigned char *) ($arg0 + 1) + set $_opext = ($_byte2 & 0x38) + if ($_opext == 0x10 || $_opext == 0x18) + # "call" + set $INSN_TYPE = 3 + end + if ($_opext == 0x20 || $_opext == 0x28) + # "jmp" + set $INSN_TYPE = 1 + end + end + end +end +document get_insn_type +Recognize instruction type at address ADDR. +Take address ADDR and set the global $INSN_TYPE variable to +0, 1, 2, 3, 4, 5 if the instruction at that address is +unknown, a jump, a conditional jump, a call, a return, or an interrupt. +Usage: get_insn_type ADDR +end + + +define hookstopcpu + if $ARM == 1 + hookstoparm + end + + if (($X86 == 1) || ($X86_64 == 1)) + hookstopx86 + end +end +document hookstopcpu +!!! FOR INTERNAL USE ONLY - DO NOT CALL !!! +end + + +define context + echo \033[34m + if $SHOWCPUREGISTERS == 1 + printf "----------------------------------------" + printf "----------------------------------" + if ($64BITS == 1) + printf "---------------------------------------------" + end + echo \033[34m\033[1m + printf "[regs]\n" + echo \033[0m + reg + echo \033[36m + end + + if $SHOWSTACK == 1 + echo \033[34m + if ($ARM == 1) + printf "[0x%08X]---------", $sp + end + if ($MIPS == 1) + printf "[0x%016lX]-------", $sp + end + if ($X86_64 == 1) + printf "[0x%04X:0x%016lX]", $ss, $rsp + end + if ($X86 == 1) + printf "[0x%04X:0x%08X]--", $ss, $esp + end + echo \033[34m + printf "-------------------------" + printf "-----------------------------" + if ($64BITS == 1) + printf "-------------------------------------" + end + echo \033[34m\033[1m + printf "[stack]\n" + echo \033[0m + set $context_i = $CONTEXTSIZE_STACK + while ($context_i > 0) + set $context_t = $sp + 0x10 * ($context_i - 1) + hexdump $context_t + set $context_i-- + end + end + + # show the objective C message being passed to msgSend + if $SHOWOBJECTIVEC == 1 + #FIXME: X64 and ARM + # What a piece of crap that's going on here :) + # detect if it's the correct opcode we are searching for + if (($X86 == 1) || ($X86_64 == 1)) + set $__byte1 = *(unsigned char *) $pc + set $__byte = *(int *) $pc + if ($__byte == 0x4244489) + set $objectivec = $eax + set $displayobjectivec = 1 + end + + if ($__byte == 0x4245489) + set $objectivec = $edx + set $displayobjectivec = 1 + end + + if ($__byte == 0x4244c89) + set $objectivec = $ecx + set $displayobjectivec = 1 + end + end + + if ($ARM == 1) + set $__byte1 = 0 + end + # and now display it or not (we have no interest in having the info displayed after the call) + if $__byte1 == 0xE8 + if $displayobjectivec == 1 + echo \033[34m + printf "--------------------------------------------------------------------" + if ($64BITS == 1) + printf "---------------------------------------------" + end + echo \033[34m\033[1m + printf "[ObjectiveC]\n" + echo \033[0m\033[30m + x/s $objectivec + end + set $displayobjectivec = 0 + end + if $displayobjectivec == 1 + echo \033[34m + printf "--------------------------------------------------------------------" + if ($64BITS == 1) + printf "---------------------------------------------" + end + echo \033[34m\033[1m + printf "[ObjectiveC]\n" + echo \033[0m\033[30m + x/s $objectivec + end + end + echo \033[0m + # and this is the end of this little crap + + if $SHOWDATAWIN == 1 + datawin + end + + set $context_i = $CONTEXTSIZE_CODE + if ($context_i > 0) + echo \033[34m + printf "--------------------------------------------------------------------------" + if ($64BITS == 1) + printf "---------------------------------------------" + end + echo \033[34m\033[1m + printf "[code]\n" + echo \033[0m + if ($SETCOLOUR1STLINE == 1) + echo \033[32m + x /i $pc + echo \033[0m + else + x /i $pc + end + set $context_i-- + while ($context_i > 0) + x /i + set $context_i-- + end + echo \033[34m + printf "----------------------------------------" + printf "----------------------------------------" + if ($64BITS == 1) + printf "---------------------------------------------\n" + else + printf "\n" + end + echo \033[0m + end +end +document context +Print context window, i.e. regs, stack, ds:esi and disassemble cs:eip. +end + + +define context-on + set $SHOW_CONTEXT = 1 + printf "Displaying of context is now ON\n" +end +document context-on +Enable display of context on every program break. +end + + +define context-off + set $SHOW_CONTEXT = 0 + printf "Displaying of context is now OFF\n" +end +document context-off +Disable display of context on every program break. +end + + +define dis + if $argc == 0 + disassemble + end + if $argc == 1 + disassemble $arg0 + end + if $argc == 2 + disassemble $arg0 $arg1 + end + if $argc > 2 + help dis + end +end +document dis +Disassemble a specified section of memory. +Default is to disassemble the function surrounding the PC (program counter) of selected frame. +With one argument, ADDR1, the function surrounding this address is dumped. +Two arguments are taken as a range of memory to dump. +Usage: dis +end diff --git a/.gdb/data.gdb b/.gdb/data.gdb new file mode 100644 index 0000000..9f250d1 --- /dev/null +++ b/.gdb/data.gdb @@ -0,0 +1,113 @@ +# __________hex/ascii dump an address_________ +define ascii_char + if $argc != 1 + help ascii_char + else + # thanks elaine :) + set $_c = *(unsigned char *) ($arg0) + if ($_c < 0x20 || $_c > 0x7E) + printf "." + else + printf "%c", $_c + end + end +end +document ascii_char +Print ASCII value of byte at address ADDR. +Print "." if the value is unprintable. +Usage: ascii_char ADDR +end + + +define hex_quad + if $argc != 1 + help hex_quad + else + printf "%02X %02X %02X %02X %02X %02X %02X %02X", \ + *(unsigned char*) ($arg0), *(unsigned char*) ($arg0 + 1), \ + *(unsigned char*) ($arg0 + 2), *(unsigned char*) ($arg0 + 3), \ + *(unsigned char*) ($arg0 + 4), *(unsigned char*) ($arg0 + 5), \ + *(unsigned char*) ($arg0 + 6), *(unsigned char*) ($arg0 + 7) + end +end +document hex_quad +Print eight hexadecimal bytes starting at address ADDR. +Usage: hex_quad ADDR +end + + +define hexdump + if $argc == 1 + hexdump_aux $arg0 + else + if $argc == 2 + set $_count = 0 + while ($_count < $arg1) + set $_i = ($_count * 0x10) + set $_addr = $data_addr + $_i + hexdump_aux $_addr + set $_count++ + end + else + help hexdump + end + end +end +document hexdump +Display a 16-byte hex/ASCII dump of memory starting at address ADDR. +Optional parameter is the number of lines to display if you want more than one. +Usage: hexdump ADDR [nr lines] +end + + +define hexdump_aux + if $argc != 1 + help hexdump_aux + else + echo \033[1m + if ($64BITS == 1) + printf "0x%016lX : ", $arg0 + else + printf "0x%08X : ", $arg0 + end + echo \033[0m + hex_quad $arg0 + echo \033[1m + printf " - " + echo \033[0m + set $_addr = $arg0 + 8 + hex_quad $_addr + printf " " + echo \033[1m + set $_count = 0 + while ($_count < 0xf) + set $_addr = $arg0 + $_count + ascii_char $_addr + set $_count++ + end + echo \033[0m + printf "\n" + end +end +document hexdump_aux +Display a 16-byte hex/ASCII dump of memory at address ADDR. +Usage: hexdump_aux ADDR +end + + +define search + set $start = (char *) $arg0 + set $end = (char *) $arg1 + set $pattern = (short) $arg2 + set $p = $start + while $p < $end + if (*(short *) $p) == $pattern + printf "pattern 0x%hx found at 0x%x\n", $pattern, $p + end + set $p++ + end +end +document search +Search for the given pattern beetween $start and $end address. +Usage: search +end diff --git a/.gdb/datawin.gdb b/.gdb/datawin.gdb new file mode 100644 index 0000000..ae6af97 --- /dev/null +++ b/.gdb/datawin.gdb @@ -0,0 +1,134 @@ +# _______________data window__________________ +define ddump + if $argc != 1 + help ddump + else + echo \033[34m + if ($ARM == 1) + printf "[0x%08X]---------", $data_addr + end + if ($MIPS == 1) + printf "[0x%016lX]-------", $data_addr + end + if ($X86 == 1) + printf "[0x%04X:0x%08X]--", $ds, $data_addr + end + if ($X86_64 == 1) + printf "[0x%04X:0x%016lX]", $ds, $data_addr + end + echo \033[34m + printf "------------------------" + printf "-------------------------------" + if ($64BITS == 1) + printf "-------------------------------------" + end + echo \033[1;34m + printf "[data]\n" + echo \033[0m + set $_count = 0 + while ($_count < $arg0) + set $_i = ($_count * 0x10) + set $_addr = $data_addr + $_i + hexdump $_addr + set $_count++ + end + end +end +document ddump +Display NUM lines of hexdump for address in $data_addr global variable. +Usage: ddump NUM +end + + +define dd + if $argc != 1 + help dd + else + set $data_addr = $arg0 + ddump 0x10 + end +end +document dd +Display 16 lines of a hex dump of address starting at ADDR. +Usage: dd ADDR +end + + +define datawin + if $ARM == 1 + if ((($r0 >> 0x18) == 0x40) || (($r0 >> 0x18) == 0x08) || (($r0 >> 0x18) == 0xBF)) + set $data_addr = $r0 + else + if ((($r1 >> 0x18) == 0x40) || (($r1 >> 0x18) == 0x08) || (($r1 >> 0x18) == 0xBF)) + set $data_addr = $r1 + else + if ((($r2 >> 0x18) == 0x40) || (($r2 >> 0x18) == 0x08) || (($r2 >> 0x18) == 0xBF)) + set $data_addr = $r2 + else + if ((($r3 >> 0x18) == 0x40) || (($r3 >> 0x18) == 0x08) || (($r3 >> 0x18) == 0xBF)) + set $data_addr = $r3 + else + set $data_addr = $sp + end + end + end + end + end + + if $MIPS == 1 + if ((($a0 >> 0x18) == 0x40) || (($a0 >> 0x18) == 0x08) || (($a0 >> 0x18) == 0xBF)) + set $data_addr = $a0 + else + if ((($a1 >> 0x18) == 0x40) || (($a1 >> 0x18) == 0x08) || (($a1 >> 0x18) == 0xBF)) + set $data_addr = $a1 + else + if ((($a2 >> 0x18) == 0x40) || (($a2 >> 0x18) == 0x08) || (($a2 >> 0x18) == 0xBF)) + set $data_addr = $a2 + else + if ((($a3 >> 0x18) == 0x40) || (($a3 >> 0x18) == 0x08) || (($a3 >> 0x18) == 0xBF)) + set $data_addr = $a3 + else + set $data_addr = $sp + end + end + end + end + end + + if ($X86_64 == 1) + if ((($rsi >> 0x18) == 0x40) || (($rsi >> 0x18) == 0x08) || (($rsi >> 0x18) == 0xBF)) + set $data_addr = $rsi + else + if ((($rdi >> 0x18) == 0x40) || (($rdi >> 0x18) == 0x08) || (($rdi >> 0x18) == 0xBF)) + set $data_addr = $rdi + else + if ((($rax >> 0x18) == 0x40) || (($rax >> 0x18) == 0x08) || (($rax >> 0x18) == 0xBF)) + set $data_addr = $rax + else + set $data_addr = $rsp + end + end + end + end + + if ($X86 == 1) + if ((($esi >> 0x18) == 0x40) || (($esi >> 0x18) == 0x08) || (($esi >> 0x18) == 0xBF)) + set $data_addr = $esi + else + if ((($edi >> 0x18) == 0x40) || (($edi >> 0x18) == 0x08) || (($edi >> 0x18) == 0xBF)) + set $data_addr = $edi + else + if ((($eax >> 0x18) == 0x40) || (($eax >> 0x18) == 0x08) || (($eax >> 0x18) == 0xBF)) + set $data_addr = $eax + else + set $data_addr = $esp + end + end + end + end + ddump $CONTEXTSIZE_DATA +end +document datawin +Display valid address from one register in data window. +Registers to choose are: esi, edi, eax, or esp. +end diff --git a/.gdb/detect-target.sh b/.gdb/detect-target.sh new file mode 100755 index 0000000..75cfbda --- /dev/null +++ b/.gdb/detect-target.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +TARGET_DOUBLET=$(grep 'file type' /tmp/gdb_info_target | + sed 's/\.$//g' | + cut -d ' ' -f 4 | + uniq | + tr -d '\n') +OSABI=$(grep 'currently ' /tmp/gdb_info_target | + sed 's/.*currently "\([^"]*\)".*/\1/' | + tr -d '\n') +GDB_FILE="/tmp/gdb_target_arch.gdb" +rm -f "$GDB_FILE" + +case "$TARGET_DOUBLET" in + *-i386) + echo "set \$X86 = 1" >> $GDB_FILE; + ;; + *-x86-64) + echo "set \$X86_64 = 1" >> $GDB_FILE; + echo "set \$64BITS = 1" >> $GDB_FILE; + ;; + *-arm*) + echo "set \$ARM = 1" >> $GDB_FILE; + ;; + *-*mips*) + echo "set \$MIPS = 1" >> $GDB_FILE; + echo "set \$64BITS = 1" >> $GDB_FILE; + ;; + mach-o-*) + if test "$OSABI" == "Darwin64"; then + echo "set \$X86_64 = 1" >> $GDB_FILE; + echo "set \$64BITS = 1" >> $GDB_FILE; + elif test "$OSABI" == "Darwin"; then + echo "set \$X86 = 1" >> $GDB_FILE; + fi + ;; +esac diff --git a/.gdb/dumpjump.gdb b/.gdb/dumpjump.gdb new file mode 100644 index 0000000..34a2eab --- /dev/null +++ b/.gdb/dumpjump.gdb @@ -0,0 +1,413 @@ +################################ +##### ALERT ALERT ALERT ######## +################################ +# Huge mess going here :) HAHA # +################################ +define dumpjump + if $ARM == 1 + ## Most ARM and Thumb instructions are conditional! + # each instruction is 32 bits long + # 4 bits are for condition codes (16 in total) (bits 31:28 in ARM contain the condition or 1111 if instruction is unconditional) + # 2x4 bits for destination and first operand registers + # one for the set-status flag + # an assorted number for other stuff + # 12 bits for any immediate value + # $_t_flag == 0 => ARM mode + # $_t_flag == 1 => Thumb or ThumbEE + if ($cpsr->t & 1) + set $_t_flag = 1 + else + set $_t_flag = 0 + end + + if $_t_flag == 0 + set $_lastbyte = *(unsigned char *)($pc+3) + #set $_bit31 = ($_lastbyte >> 7) & 1 + #set $_bit30 = ($_lastbyte >> 6) & 1 + #set $_bit29 = ($_lastbyte >> 5) & 1 + #set $_bit28 = ($_lastbyte >> 4) & 1 + set $_conditional = $_lastbyte >> 4 + dumpjumphelper + else + # if bits 15-12 (opcode in Thumb instructions) are equal to 1 1 0 1 (0xD) then we have a conditional branch + # bits 11-8 for the conditional execution code (check ARMv7 manual A8.3) + if ((*(unsigned char *) ($pc + 1) >> 4) == 0xD) + set $_conditional = *(unsigned char *) ($pc+1) ^ 0xD0 + dumpjumphelper + end + end + end + + if (($X86 == 1) || ($X86_64 == 1)) + ## grab the first two bytes from the instruction so we can determine the jump instruction + set $_byte1 = *(unsigned char *) $pc + set $_byte2 = *(unsigned char *) ($pc+1) + ## and now check what kind of jump we have (in case it's a jump instruction) + ## I changed the flags routine to save the flag into a variable, so we don't need to repeat the process :) (search for "define flags") + + ## opcode 0x77: JA, JNBE (jump if CF=0 and ZF=0) + ## opcode 0x0F87: JNBE, JA + if (($_byte1 == 0x77) || ($_byte1 == 0x0F && $_byte2 == 0x87)) + # cf=0 and zf=0 + if ($_cf_flag == 0 && $_zf_flag == 0) + echo \033[31m + printf " Jump is taken (c=0 and z=0)" + else + # cf != 0 or zf != 0 + echo \033[31m + printf " Jump is NOT taken (c!=0 or z!=0)" + end + end + ## opcode 0x73: JAE, JNB, JNC (jump if CF=0) + ## opcode 0x0F83: JNC, JNB, JAE (jump if CF=0) + if (($_byte1 == 0x73) || ($_byte1 == 0x0F && $_byte2 == 0x83)) + # cf=0 + if ($_cf_flag == 0) + echo \033[31m + printf " Jump is taken (c=0)" + else + # cf != 0 + echo \033[31m + printf " Jump is NOT taken (c!=0)" + end + end + ## opcode 0x72: JB, JC, JNAE (jump if CF=1) + ## opcode 0x0F82: JNAE, JB, JC + if (($_byte1 == 0x72) || ($_byte1 == 0x0F && $_byte2 == 0x82)) + # cf=1 + if ($_cf_flag == 1) + echo \033[31m + printf " Jump is taken (c=1)" + else + # cf != 1 + echo \033[31m + printf " Jump is NOT taken (c!=1)" + end + end + ## opcode 0x76: JBE, JNA (jump if CF=1 or ZF=1) + ## opcode 0x0F86: JBE, JNA + if (($_byte1 == 0x76) || ($_byte1 == 0x0F && $_byte2 == 0x86)) + # cf=1 or zf=1 + if (($_cf_flag == 1) || ($_zf_flag == 1)) + echo \033[31m + printf " Jump is taken (c=1 or z=1)" + else + # cf != 1 or zf != 1 + echo \033[31m + printf " Jump is NOT taken (c!=1 or z!=1)" + end + end + ## opcode 0xE3: JCXZ, JECXZ, JRCXZ (jump if CX=0 or ECX=0 or RCX=0) + if ($_byte1 == 0xE3) + # cx=0 or ecx=0 + if (($ecx == 0) || ($cx == 0)) + echo \033[31m + printf " Jump is taken (cx=0 or ecx=0)" + else + echo \033[31m + printf " Jump is NOT taken (cx!=0 or ecx!=0)" + end + end + ## opcode 0x74: JE, JZ (jump if ZF=1) + ## opcode 0x0F84: JZ, JE, JZ (jump if ZF=1) + if (($_byte1 == 0x74) || ($_byte1 == 0x0F && $_byte2 == 0x84)) + # ZF = 1 + if ($_zf_flag == 1) + echo \033[31m + printf " Jump is taken (z=1)" + else + # ZF = 0 + echo \033[31m + printf " Jump is NOT taken (z!=1)" + end + end + ## opcode 0x7F: JG, JNLE (jump if ZF=0 and SF=OF) + ## opcode 0x0F8F: JNLE, JG (jump if ZF=0 and SF=OF) + if (($_byte1 == 0x7F) || ($_byte1 == 0x0F && $_byte2 == 0x8F)) + # zf = 0 and sf = of + if (($_zf_flag == 0) && ($_sf_flag == $_of_flag)) + echo \033[31m + printf " Jump is taken (z=0 and s=o)" + else + echo \033[31m + printf " Jump is NOT taken (z!=0 or s!=o)" + end + end + ## opcode 0x7D: JGE, JNL (jump if SF=OF) + ## opcode 0x0F8D: JNL, JGE (jump if SF=OF) + if (($_byte1 == 0x7D) || ($_byte1 == 0x0F && $_byte2 == 0x8D)) + # sf = of + if ($_sf_flag == $_of_flag) + echo \033[31m + printf " Jump is taken (s=o)" + else + echo \033[31m + printf " Jump is NOT taken (s!=o)" + end + end + ## opcode: 0x7C: JL, JNGE (jump if SF != OF) + ## opcode: 0x0F8C: JNGE, JL (jump if SF != OF) + if (($_byte1 == 0x7C) || ($_byte1 == 0x0F && $_byte2 == 0x8C)) + # sf != of + if ($_sf_flag != $_of_flag) + echo \033[31m + printf " Jump is taken (s!=o)" + else + echo \033[31m + printf " Jump is NOT taken (s=o)" + end + end + ## opcode 0x7E: JLE, JNG (jump if ZF = 1 or SF != OF) + ## opcode 0x0F8E: JNG, JLE (jump if ZF = 1 or SF != OF) + if (($_byte1 == 0x7E) || ($_byte1 == 0x0F && $_byte2 == 0x8E)) + # zf = 1 or sf != of + if (($_zf_flag == 1) || ($_sf_flag != $_of_flag)) + echo \033[31m + printf " Jump is taken (zf=1 or sf!=of)" + else + echo \033[31m + printf " Jump is NOT taken (zf!=1 or sf=of)" + end + end + ## opcode 0x75: JNE, JNZ (jump if ZF = 0) + ## opcode 0x0F85: JNE, JNZ (jump if ZF = 0) + if (($_byte1 == 0x75) || ($_byte1 == 0x0F && $_byte2 == 0x85)) + # ZF = 0 + if ($_zf_flag == 0) + echo \033[31m + printf " Jump is taken (z=0)" + else + # ZF = 1 + echo \033[31m + printf " Jump is NOT taken (z!=0)" + end + end + ## opcode 0x71: JNO (OF = 0) + ## opcode 0x0F81: JNO (OF = 0) + if (($_byte1 == 0x71) || ($_byte1 == 0x0F && $_byte2 == 0x81)) + # OF = 0 + if ($_of_flag == 0) + echo \033[31m + printf " Jump is taken (o=0)" + else + # OF != 0 + echo \033[31m + printf " Jump is NOT taken (o!=0)" + end + end + ## opcode 0x7B: JNP, JPO (jump if PF = 0) + ## opcode 0x0F8B: JPO (jump if PF = 0) + if (($_byte1 == 0x7B) || ($_byte1 == 0x0F && $_byte2 == 0x8B)) + # PF = 0 + if ($_pf_flag == 0) + echo \033[31m + printf " Jump is NOT taken (p=0)" + else + # PF != 0 + echo \033[31m + printf " Jump is taken (p!=0)" + end + end + ## opcode 0x79: JNS (jump if SF = 0) + ## opcode 0x0F89: JNS (jump if SF = 0) + if (($_byte1 == 0x79) || ($_byte1 == 0x0F && $_byte2 == 0x89)) + # SF = 0 + if ($_sf_flag == 0) + echo \033[31m + printf " Jump is taken (s=0)" + else + # SF != 0 + echo \033[31m + printf " Jump is NOT taken (s!=0)" + end + end + ## opcode 0x70: JO (jump if OF=1) + ## opcode 0x0F80: JO (jump if OF=1) + if (($_byte1 == 0x70) || ($_byte1 == 0x0F && $_byte2 == 0x80)) + # OF = 1 + if ($_of_flag == 1) + echo \033[31m + printf " Jump is taken (o=1)" + else + # OF != 1 + echo \033[31m + printf " Jump is NOT taken (o!=1)" + end + end + ## opcode 0x7A: JP, JPE (jump if PF=1) + ## opcode 0x0F8A: JP, JPE (jump if PF=1) + if (($_byte1 == 0x7A) || ($_byte1 == 0x0F && $_byte2 == 0x8A)) + # PF = 1 + if ($_pf_flag == 1) + echo \033[31m + printf " Jump is taken (p=1)" + else + # PF = 0 + echo \033[31m + printf " Jump is NOT taken (p!=1)" + end + end + ## opcode 0x78: JS (jump if SF=1) + ## opcode 0x0F88: JS (jump if SF=1) + if (($_byte1 == 0x78) || ($_byte1 == 0x0F && $_byte2 == 0x88)) + # SF = 1 + if ($_sf_flag == 1) + echo \033[31m + printf " Jump is taken (s=1)" + else + # SF != 1 + echo \033[31m + printf " Jump is NOT taken (s!=1)" + end + end + end +end +document dumpjump +Display if conditional jump will be taken or not. +end + +define dumpjumphelper + # 0000 - EQ: Z == 1 + if ($_conditional == 0x0) + if ($_z_flag == 1) + echo \033[31m + printf " Jump is taken (z==1)" + else + echo \033[31m + printf " Jump is NOT taken (z!=1)" + end + end + # 0001 - NE: Z == 0 + if ($_conditional == 0x1) + if ($_z_flag == 0) + echo \033[31m + printf " Jump is taken (z==0)" + else + echo \033[31m + printf " Jump is NOT taken (z!=0)" + end + end + # 0010 - CS: C == 1 + if ($_conditional == 0x2) + if ($_c_flag == 1) + echo \033[31m + printf " Jump is taken (c==1)" + else + echo \033[31m + printf " Jump is NOT taken (c!=1)" + end + end + # 0011 - CC: C == 0 + if ($_conditional == 0x3) + if ($_c_flag == 0) + echo \033[31m + printf " Jump is taken (c==0)" + else + echo \033[31m + printf " Jump is NOT taken (c!=0)" + end + end + # 0100 - MI: N == 1 + if ($_conditional == 0x4) + if ($_n_flag == 1) + echo \033[31m + printf " Jump is taken (n==1)" + else + echo \033[31m + printf " Jump is NOT taken (n!=1)" + end + end + # 0101 - PL: N == 0 + if ($_conditional == 0x5) + if ($_n_flag == 0) + echo \033[31m + printf " Jump is taken (n==0)" + else + echo \033[31m + printf " Jump is NOT taken (n!=0)" + end + end + # 0110 - VS: V == 1 + if ($_conditional == 0x6) + if ($_v_flag == 1) + echo \033[31m + printf " Jump is taken (v==1)" + else + echo \033[31m + printf " Jump is NOT taken (v!=1)" + end + end + # 0111 - VC: V == 0 + if ($_conditional == 0x7) + if ($_v_flag == 0) + echo \033[31m + printf " Jump is taken (v==0)" + else + echo \033[31m + printf " Jump is NOT taken (v!=0)" + end + end + # 1000 - HI: C == 1 and Z == 0 + if ($_conditional == 0x8) + if ($_c_flag == 1 && $_z_flag == 0) + echo \033[31m + printf " Jump is taken (c==1 and z==0)" + else + echo \033[31m + printf " Jump is NOT taken (c!=1 or z!=0)" + end + end + # 1001 - LS: C == 0 or Z == 1 + if ($_conditional == 0x9) + if ($_c_flag == 0 || $_z_flag == 1) + echo \033[31m + printf " Jump is taken (c==0 or z==1)" + else + echo \033[31m + printf " Jump is NOT taken (c!=0 or z!=1)" + end + end + # 1010 - GE: N == V + if ($_conditional == 0xA) + if ($_n_flag == $_v_flag) + echo \033[31m + printf " Jump is taken (n==v)" + else + echo \033[31m + printf " Jump is NOT taken (n!=v)" + end + end + # 1011 - LT: N != V + if ($_conditional == 0xB) + if ($_n_flag != $_v_flag) + echo \033[31m + printf " Jump is taken (n!=v)" + else + echo \033[31m + printf " Jump is NOT taken (n==v)" + end + end + # 1100 - GT: Z == 0 and N == V + if ($_conditional == 0xC) + if ($_z_flag == 0 && $_n_flag == $_v_flag) + echo \033[31m + printf " Jump is taken (z==0 and n==v)" + else + echo \033[31m + printf " Jump is NOT taken (z!=0 or n!=v)" + end + end + # 1101 - LE: Z == 1 or N != V + if ($_conditional == 0xD) + if ($_z_flag == 1 || $_n_flag != $_v_flag) + echo \033[31m + printf " Jump is taken (z==1 or n!=v)" + else + echo \033[31m + printf " Jump is NOT taken (z!=1 or n==v)" + end + end +end +document dumpjumphelper +Helper function to decide if conditional jump will be taken or not, for ARM and Thumb. +end diff --git a/.gdb/eigen.gdb b/.gdb/eigen.gdb new file mode 100644 index 0000000..609617c --- /dev/null +++ b/.gdb/eigen.gdb @@ -0,0 +1,7 @@ +python +import sys +from os.path import expanduser +sys.path.insert(0, expanduser('~/.gdb')) +from eigen.printers import * +register_eigen_printers (None) +end diff --git a/.gdb/eigen/__init__.py b/.gdb/eigen/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/.gdb/eigen/printers/__init__.py b/.gdb/eigen/printers/__init__.py new file mode 100644 index 0000000..7d5fb2f --- /dev/null +++ b/.gdb/eigen/printers/__init__.py @@ -0,0 +1 @@ +from .eigen import * diff --git a/.gdb/eigen/printers/eigen.py b/.gdb/eigen/printers/eigen.py new file mode 100644 index 0000000..600e140 --- /dev/null +++ b/.gdb/eigen/printers/eigen.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# This file is part of Eigen, a lightweight C++ template library +# for linear algebra. +# +# Copyright (C) 2009 Benjamin Schindler +# +# Eigen is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Alternatively, you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License and a copy of the GNU General Public License along with +# Eigen. If not, see . + +# Pretty printers for Eigen::Matrix +# This is still pretty basic as the python extension to gdb is still pretty basic. +# It cannot handle complex eigen types and it doesn't support any of the other eigen types +# Such as quaternion or some other type. +# This code supports fixed size as well as dynamic size matrices + +# To use it: +# +# * create a directory and put the file as well as an empty __init__.py in that directory +# * Create a ~/.gdbinit file, that contains the following: + + +import gdb +import re +import itertools + + +class EigenMatrixPrinter: + "Print Eigen Matrix of some kind" + + def __init__(self, val): + "Extract all the necessary information" + # The gdb extension does not support value template arguments - need to extract them by hand + type = val.type + if type.code == gdb.TYPE_CODE_REF: + type = type.target() + self.type = type.unqualified().strip_typedefs() + tag = self.type.tag + regex = re.compile('\<.*\>') + m = regex.findall(tag)[0][1:-1] + template_params = m.split(',') + template_params = map(lambda x:x.replace(" ", ""), template_params) + + self.rows = int(template_params[1]) + self.cols = int(template_params[2]) + self.options = 0 # default value + if len(template_params) > 3: + self.options = template_params[3]; + + self.rowMajor = (int(self.options) & 0x1) + + if self.rows == 10000: + self.rows = val['m_storage']['m_rows'] + + if self.cols == 10000: + self.cols = val['m_storage']['m_cols'] + + self.innerType = self.type.template_argument(0) + + self.val = val + + # Fixed size matrices have a struct as their storage, so we need to walk through this + self.data = self.val['m_storage']['m_data'] + if self.data.type.code == gdb.TYPE_CODE_STRUCT: + self.data = self.data['array'] + self.data = self.data.cast(self.innerType.pointer()) + + class _iterator: + def __init__ (self, rows, cols, dataPtr, rowMajor): + self.rows = rows + self.cols = cols + self.dataPtr = dataPtr + self.currentRow = 0 + self.currentCol = 0 + self.rowMajor = rowMajor + + def __iter__ (self): + return self + + def next(self): + + row = self.currentRow + col = self.currentCol + if self.rowMajor == 0: + if self.currentCol >= self.cols: + raise StopIteration + + self.currentRow = self.currentRow + 1 + if self.currentRow >= self.rows: + self.currentRow = 0 + self.currentCol = self.currentCol + 1 + else: + if self.currentRow >= self.rows: + raise StopIteration + + self.currentCol = self.currentCol + 1 + if self.currentCol >= self.cols: + self.currentCol = 0 + self.currentRow = self.currentRow + 1 + + + item = self.dataPtr.dereference() + self.dataPtr = self.dataPtr + 1 + if (self.cols == 1): #if it's a column vector + return ('[%d]' % (row,), item) + elif (self.rows == 1): #if it's a row vector + return ('[%d]' % (col,), item) + return ('[%d,%d]' % (row, col), item) + + def children(self): + + return self._iterator(self.rows, self.cols, self.data, self.rowMajor) + + def to_string(self): + return "Eigen::Matrix<%s,%d,%d,%s> (data ptr: %s)" % (self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else "ColMajor", self.data) + +class EigenQuaternionPrinter: + "Print an Eigen Quaternion" + + def __init__(self, val): + "Extract all the necessary information" + # The gdb extension does not support value template arguments - need to extract them by hand + type = val.type + if type.code == gdb.TYPE_CODE_REF: + type = type.target() + self.type = type.unqualified().strip_typedefs() + self.innerType = self.type.template_argument(0) + self.val = val + + # Quaternions have a struct as their storage, so we need to walk through this + self.data = self.val['m_coeffs']['m_storage']['m_data']['array'] + self.data = self.data.cast(self.innerType.pointer()) + + class _iterator: + def __init__ (self, dataPtr): + self.dataPtr = dataPtr + self.currentElement = 0 + self.elementNames = ['x', 'y', 'z', 'w'] + + def __iter__ (self): + return self + + def next(self): + element = self.currentElement + + if self.currentElement >= 4: #there are 4 elements in a quanternion + raise StopIteration + + self.currentElement = self.currentElement + 1 + + item = self.dataPtr.dereference() + self.dataPtr = self.dataPtr + 1 + return ('[%s]' % (self.elementNames[element],), item) + + def children(self): + + return self._iterator(self.data) + + def to_string(self): + return "Eigen::Quaternion<%s> (data ptr: %s)" % (self.innerType, self.data) + +def build_eigen_dictionary (): + pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val) + pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter(val) + +def register_eigen_printers(obj): + "Register eigen pretty-printers with objfile Obj" + + if obj == None: + obj = gdb + obj.pretty_printers.append(lookup_function) + +def lookup_function(val): + "Look-up and return a pretty-printer that can print va." + + type = val.type + + if type.code == gdb.TYPE_CODE_REF: + type = type.target() + + type = type.unqualified().strip_typedefs() + + typename = type.tag + if typename == None: + return None + + for function in pretty_printers_dict: + if function.search(typename): + return pretty_printers_dict[function](val) + + return None + +pretty_printers_dict = {} + +build_eigen_dictionary () diff --git a/.gdb/info.gdb b/.gdb/info.gdb new file mode 100644 index 0000000..d8a693f --- /dev/null +++ b/.gdb/info.gdb @@ -0,0 +1,93 @@ +define stack + if $argc == 0 + info stack + end + if $argc == 1 + info stack $arg0 + end + if $argc > 1 + help stack + end +end +document stack +Print backtrace of the call stack, or innermost COUNT frames. +Usage: stack +end + + +define frame + info frame + info args + info locals +end +document frame +Print stack frame. +end + + +define func + if $argc == 0 + info functions + end + if $argc == 1 + info functions $arg0 + end + if $argc > 1 + help func + end +end +document func +Print all function names in target, or those matching REGEXP. +Usage: func +end + + +define var + if $argc == 0 + info variables + end + if $argc == 1 + info variables $arg0 + end + if $argc > 1 + help var + end +end +document var +Print all global and static variable names (symbols), or those matching REGEXP. +Usage: var +end + + +define lib + info sharedlibrary +end +document lib +Print shared libraries linked to target. +end + + +define sig + if $argc == 0 + info signals + end + if $argc == 1 + info signals $arg0 + end + if $argc > 1 + help sig + end +end +document sig +Print what debugger does when program gets various signals. +Specify a SIGNAL as argument to print info on that signal only. +Usage: sig +end + + +define threads + info threads +end +document threads +Print threads in target. +end diff --git a/.gdb/kgmacros.gdb b/.gdb/kgmacros.gdb new file mode 100644 index 0000000..2889a50 --- /dev/null +++ b/.gdb/kgmacros.gdb @@ -0,0 +1,13673 @@ + +# Kernel gdb macros +# +# These gdb macros should be useful during kernel development in +# determining what's going on in the kernel. +# +# All the convenience variables used by these macros begin with $kgm_ + +set print asm-demangle on +set cp-abi gnu-v2 + +# This option tells gdb to relax its stack tracing heuristics +# Useful for debugging across stack switches +# (to the interrupt stack, for instance). Requires gdb-675 or greater. +set backtrace sanity-checks off + +echo Loading Kernel GDB Macros package. Type "help kgm" for more info.\n + +define kgm +printf "" +echo These are the gdb macros for kernel debugging. Type "help kgm" for more info.\n +end + +document kgm +| These are the kernel gdb macros. These gdb macros are intended to be +| used when debugging a remote kernel via the kdp protocol. Typically, you +| would connect to your remote target like so: +| (gdb) target remote-kdp +| (gdb) attach +| +| The following macros are available in this package: +| showversion Displays a string describing the remote kernel version +| +| showalltasks Display a summary listing of all tasks +| showallthreads Display info about all threads in the system +| showallstacks Display the stack for each thread in the system +| showcurrentthreads Display info about the thread running on each cpu +| showcurrentstacks Display the stack for the thread running on each cpu +| showallvm Display a summary listing of all the vm maps +| showallvme Display a summary listing of all the vm map entries +| showallipc Display a summary listing of all the ipc spaces +| showipcsummary Display a summary listing of the ipc spaces of all tasks +| showallrights Display a summary listing of all the ipc rights +| showallkexts Display a summary listing of all loaded kexts (alias: showallkmods) +| showallknownkexts Display a summary listing of all kexts, loaded or not +| showallbusyports Display a listing of all ports with unread messages +| showallprocessors Display a listing of all psets and processors +| +| showallclasses Display info about all OSObject subclasses in the system +| showobject Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes. +| showregistry Show info about all registry entries in the current plane +| showregistryprops Show info about all registry entries in the current plane, and their properties +| showregistryentry Show info about a registry entry; its properties and descendants in the current plane +| setregistryplane Set the plane to be used for the iokit registry macros (pass zero for list) +| +| setfindregistrystr Set the encoded string for matching with +| findregistryentry or findregistryprop (created from +| strcmp_arg_pack64) +| findregistryentry Find a registry entry that matches the encoded string +| findregistryentries Find all the registry entries that match the encoded string +| findregistryprop Search the registry entry for a property that matches +| the encoded string +| +| showtask Display info about the specified task +| showtaskthreads Display info about the threads in the task +| showtaskstacks Display the stack for each thread in the task +| showtaskvm Display info about the specified task's vm_map +| showtaskvme Display info about the task's vm_map entries +| showtaskipc Display info about the specified task's ipc space +| showtaskrights Display info about the task's ipc space entries +| showtaskrightsbt Display info about the task's ipc space entries with back traces +| showtaskbusyports Display all of the task's ports with unread messages +| +| showact Display info about a thread specified by activation +| showactstack Display the stack for a thread specified by activation +| +| showmap Display info about the specified vm_map +| showmapvme Display a summary list of the specified vm_map's entries +| +| showipc Display info about the specified ipc space +| showrights Display a summary list of all the rights in an ipc space +| +| showpid Display info about the process identified by pid +| showproc Display info about the process identified by proc struct +| showprocinfo Display detailed info about the process identified by proc struct +| showprocfiles Given a proc_t pointer, display the list of open file descriptors +| showproclocks Given a proc_t pointer, display the list of advisory file locks +| zombproc Print out all procs in the zombie list +| showproctree Show all the processes in a hierarchical tree form +| allproc Print out all process in the system not in the zombie list +| zombstacks Print out all stacks of tasks that are exiting +| +| showinitchild Print out all processes in the system which are children of init process +| +| showkext Display info about a kext (alias: showkmod) +| showkextaddr Given an address, display the kext and offset (alias: showkmodaddr) +| +| dumpcallqueue Dump out all the entries given a queue head +| +| showallmtx Display info about mutexes usage +| showallrwlck Display info about reader/writer locks usage +| +| zprint Display info about the memory zones +| showioalloc Display info about iokit allocations +| paniclog Display the panic log info +| +| switchtoact Switch to different context specified by activation +| switchtoctx Switch to different context +| showuserstack Display numeric backtrace of the user stack for an +| activation +| showtaskuserstacks Display user stacks for a specified task +| showuserregisters Display user registers for the specified thread +| showtaskuserregisters Display user registers for the specified task +| +| switchtouserthread Switch to the user context of the specified thread +| resetstacks Return to the original kernel context +| +| resetctx Reset context +| resume_on Resume when detaching from gdb +| resume_off Don't resume when detaching from gdb +| +| sendcore Configure kernel to send a coredump to the specified IP +| sendsyslog Configure kernel to send a system log to the specified IP +| sendpaniclog Configure kernel to send a panic log to the specified IP +| disablecore Configure the kernel to disable coredump transmission +| getdumpinfo Retrieve the current remote dump parameters +| setdumpinfo Configure the remote dump parameters +| +| switchtocorethread Corefile version of "switchtoact" +| resetcorectx Corefile version of "resetctx" +| +| readphys8 Reads the specified untranslated address (8-bit read) +| readphys16 Reads the specified untranslated address (16-bit read) +| readphys32 Reads the specified untranslated address (32-bit read) +| readphys64 Reads the specified untranslated address (64-bit read) +| writephys8 Writes to the specified untranslated address (8-bit write) +| writephys16 Writes to the specified untranslated address (16-bit write) +| writephys32 Writes to the specified untranslated address (32-bit write) +| writephys64 Writes to the specified untranslated address (64-bit write) +| +| readioport8 Read 8-bits from the specified I/O Port +| readioport16 Read 16-bits from the specified I/O Port +| readioport32 Read 32-bits from the specified I/O Port +| writeioport8 Write 8-bits into the specified I/O Port +| writeioport16 Write 16-bits into the specified I/O Port +| writeioport32 Write 32-bits into the specified I/O Port +| +| readmsr64 Read 64-bits from the specified MSR +| writemsr64 Write 64-bits into the specified MSR +| +| rtentry_showdbg Print the debug information of a route entry +| rtentry_trash Walk the list of trash route entries +| +| inifa_showdbg Print the debug information of an IPv4 interface address +| in6ifa_showdbg Print the debug information of an IPv6 interface address +| inm_showdbg Print the debug information of an IPv4 multicast address +| ifma_showdbg Print the debug information of a link multicast address +| ifpref_showdbg Print the debug information of an interface ref count +| +| ndpr_showdbg Print the debug information of a nd_prefix structure +| nddr_showdbg Print the debug information of a nd_defrouter structure +| +| imo_showdbg Print the debug information of a ip_moptions structure +| im6o_showdbg Print the debug information of a ip6_moptions structure +| +| inifa_trash Walk the list of trash in_ifaddr entries +| in6ifa_trash Walk the list of trash in6_ifaddr entries +| inm_trash Walk the list of trash in_multi entries +| in6m_trash Walk the list of trash in6_multi entries +| ifma_trash Walk the list of trash ifmultiaddr entries +| +| mbuf_walkpkt Walk the mbuf packet chain (m_nextpkt) +| mbuf_walk Walk the mbuf chain (m_next) +| mbuf_buf2slab Find the slab structure of the corresponding buffer +| mbuf_buf2mca Find the mcache audit structure of the corresponding mbuf +| mbuf_showmca Print the contents of an mbuf mcache audit structure +| mbuf_showactive Print all active/in-use mbuf objects +| mbuf_showinactive Print all freed/in-cache mbuf objects +| mbuf_showall Print all mbuf objects +| mbuf_slabs Print all slabs in the group +| mbuf_slabstbl Print slabs table +| mbuf_stat Print extended mbuf allocator statistics +| mbuf_countchain Count the length of an mbuf chain +| mbuf_topleak Print the top suspected mbuf leakers +| mbuf_traceleak Print the leak information for a given leak address +| +| mcache_walkobj Walk the mcache object chain (obj_next) +| mcache_stat Print all mcaches in the system +| mcache_showcache Display the number of objects in the cache +| +| showbootargs Display boot arguments passed to the target kernel +| showbootermemorymap Dump phys memory map from EFI +| +| systemlog Display the kernel's printf ring buffer +| +| hexdump Show the contents of memory as a hex/ASCII dump +| +| showvnodepath Print the path for a vnode +| showvnodelocks Display list of advisory locks held/blocked on a vnode +| showvnodedev Display information about a device vnode +| showtty Display information about a struct tty +| showallvols Display a summary of mounted volumes +| showvnode Display info about one vnode +| showvolvnodes Display info about all vnodes of a given volume +| showvolbusyvnodes Display info about busy (iocount!=0) vnodes of a given volume +| showallbusyvnodes Display info about all busy (iocount!=0) vnodes +| showallvnodes Display info about all vnodes +| print_vnode Print out the fields of a vnode struct +| showprocvnodes Print out all the open fds which are vnodes in a process +| showallprocvnodes Print out all the open fds which are vnodes in any process +| showmountvnodes Print the vnode list +| showmountallvnodes Print the vnode inactive list +| showworkqvnodes Print the vnode worker list +| shownewvnodes Print the new vnode list +| +| ifconfig display ifconfig-like output +| showifnets show the list of attached and detached interfaces +| showifaddrs show the list of addresses for the given ifp +| showifmultiaddrs show the list of multicast addresses for the given ifp +| showinmultiaddrs show the list of IPv4 multicast addresses records +| showin6multiaddrs show the list of IPv6 multicast addresses records +| +| showsocket Display information about a socket +| showprocsockets Given a proc_t pointer, display information about its sockets +| showallprocsockets Display information about the sockets of all the processes +| +| show_tcp_pcbinfo Display the list of the TCP protocol control blocks +| show_tcp_timewaitslots Display the list of the TCP protocol control blocks in TIMEWAIT +| show_udp_pcbinfo Display the list of UDP protocol control blocks +| +| show_rt_inet Display the IPv4 routing table +| show_rt_inet6 Display the IPv6 routing table +| +| showpmworkqueue Display the IOPMWorkQueue object +| showregistrypmstate Display power management state for all IOPower registry entries +| showioservicepm Display the IOServicePM object +| showstacksaftertask showallstacks starting after a given task +| showstacksafterthread showallstacks starting after a given thread +| +| showMCAstate Print machine-check register state after MC exception. +| +| showallgdbstacks Cause GDB to trace all thread stacks +| showallgdbcorestacks Corefile equivalent of "showallgdbstacks" +| kdp-reenter Schedule reentry into the debugger and continue. +| kdp-reboot Restart remote target +| kdp-version Get KDP version number +| +| zstack Print zalloc caller stack (zone leak debugging) +| findoldest Find oldest zone leak debugging record +| countpcs Print how often a pc occurs in the zone leak log +| +| showtopztrace Print the ztrace with the most outstanding allocated memory +| showztrace Print a backtrace record given its index +| showzalloc Print an allocation record + stacktrace at index +| showztraceaddr Print a backtrace record given its address +| showztracesabove Print all the backtrace records with a size bigger than X +| showzstacktrace Symbolicate and print a stored OSBacktrace +| +| showztraces Finds all in-use traces in the ztraces table +| showzallocs Finds all in-use allocations in the zallocs table +| showzstats Shows the statistics gathered about the hash tables +| +| showzallocsfortrace Print all the allocations that refer to a trace +| showztracehistogram Prints a histogram of the ztraces table +| showzallochistogram Prints a histogram of the zallocs table +| +| pmap_walk Perform a page-table walk +| pmap_vtop Translate a virtual address to physical address +| +| showuserdyldinfo Show dyld information and error messages +| in the target task +| showuserlibraries Show binary images known by dyld in the +| target task +| showallvmstats Prints a summary of vm statistics in a table format +| memstats Displays memory statistics in a table format +| +| showthreadfortid Displays the address of the thread structure +| for a given thread_id value. +| +| strcmp_nomalloc A version of strcmp that avoids the use of malloc +| through the use of encoded strings created via +| strcmp_arg_pack64. +| strcmp_arg_pack64 Pack a string into a 64-bit quantity for use by +| strcmp_nomalloc +| +| pci_cfg_read8 Read 8-bits from a PCI config space register +| pci_cfg_read16 Read 16-bits from a PCI config space register +| pci_cfg_read32 Read 32-bits from a PCI config space register +| pci_cfg_write8 Write 8-bits into a PCI config space register +| pci_cfg_write16 Write 16-bits into a PCI config space register +| pci_cfg_write32 Write 32-bits into a PCI config space register +| pci_cfg_dump Dump entire config space for a PCI device +| pci_cfg_scan Perform a scan for PCI devices +| pci_cfg_dump_all Dump config spaces for all detected PCI devices +| +| lapic_read32 Read APIC entry +| lapic_write32 Write APIC entry +| lapic_dump Dump APIC entries +| +| ioapic_read32 Read IOAPIC entry +| ioapic_write32 Write IOAPIC entry +| ioapic_dump Dump IOAPIC entries +| +| showallproviders Display summary listing of all dtrace_providers +| showallmodctls Display summary listing of all dtrace modctls +| showmodctl Display info about a dtrace modctl +| showfbtprobe Display info about an fbt probe given an id (traverses fbt_probetab) +| processortimers Display all processor timers, noting any inconsistencies +| +| maplocalcache Enable local caching in GDB for improved debug speeds +| flushlocalcahe Disable local caching in GDB (deletes all memory regions) +| +| Type "help " for more specific help on a particular macro. +| Type "show user " to see what the macro is really doing. +end + +# This macro should appear before any symbol references, to facilitate +# a gdb "source" without a loaded symbol file. +define showversion + kdp-kernelversion +end + +document showversion +Syntax: showversion +| Read the kernel version string from a fixed address in low +| memory. Useful if you don't know which kernel is on the other end, +| and need to find the appropriate symbols. Beware that if you've +| loaded a symbol file, but aren't connected to a remote target, +| the version string from the symbol file will be displayed instead. +| This macro expects to be connected to the remote kernel to function +| correctly. +end + +set $kgm_mtype_ppc = 0x00000012 +set $kgm_mtype_arm = 0x0000000C + +set $kgm_mtype_i386 = 0x00000007 +set $kgm_mtype_x86_64 = 0x01000007 +set $kgm_mtype_x86_any = $kgm_mtype_i386 +set $kgm_mtype_x86_mask = 0xFEFFFFFF + +set $kgm_mtype = ((unsigned int *)&_mh_execute_header)[1] +set $kgm_lp64 = $kgm_mtype & 0x01000000 + +set $kgm_manual_pkt_ppc = 0x549C +set $kgm_manual_pkt_i386 = 0x249C +set $kgm_manual_pkt_x86_64 = 0xFFFFFF8000002930 +set $kgm_manual_pkt_arm = 0xFFFF04A0 + +set $kgm_kdp_pkt_data_len = 128 + +# part of data packet +set $kgm_kdp_pkt_hdr_req_off = 0 +set $kgm_kdp_pkt_hdr_seq_off = 1 +set $kgm_kdp_pkt_hdr_len_off = 2 +set $kgm_kdp_pkt_hdr_key_off = 4 + +# after data packet +set $kgm_kdp_pkt_len_off = $kgm_kdp_pkt_data_len +set $kgm_kdp_pkt_input_off = $kgm_kdp_pkt_data_len + 4 + +set $kgm_kdp_pkt_hostreboot = 0x13 +set $kgm_kdp_pkt_hdr_size = 8 + + +set $kgm_readphys_force_kdp = 0 +set $kgm_readphys_force_physmap = 0 + +set $kgm_lcpu_self = 0xFFFE + +set $kgm_reg_depth = 0 +set $kgm_reg_depth_max = 0xFFFF +set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane +set $kgm_namekey = (OSSymbol *) 0 +set $kgm_childkey = (OSSymbol *) 0 + +set $kgm_show_object_addrs = 0 +set $kgm_show_object_retain = 0 +set $kgm_show_props = 0 +set $kgm_show_data_alwaysbytes = 0 + +set $kgm_show_kmod_syms = 0 + +# send a manual packet header that doesn't require knowing the location +# of everything. +define manualhdrint + set $req = $arg0 + + set $hdrp = (uint32_t *) $kgm_manual_pkt_i386 + if ($kgm_mtype == $kgm_mtype_ppc) + set $hdrp = (uint32_t *) $kgm_manual_pkt_ppc + set $req = $req << 1 # shift to deal with endiannness + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $hdrp = (uint64_t *) $kgm_manual_pkt_x86_64 + end + if ($kgm_mtype == $kgm_mtype_arm) + set $hdrp = (uint32_t *) $kgm_manual_pkt_arm + end + + set $pkt_hdr = *$hdrp + set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 0 + set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_len_off)) = $kgm_kdp_pkt_hdr_size + + set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_req_off)) = $req + set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_seq_off)) = 0 + set *((uint16_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_len_off)) = $kgm_kdp_pkt_hdr_size + set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_key_off)) = 0 + set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 1 + + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header +end + +# Print a pointer +define showptr + if $kgm_lp64 + printf "0x%016llx", $arg0 + else + printf "0x%08x", $arg0 + end +end + +# for headers, leave 8 chars for LP64 pointers +define showptrhdrpad + if $kgm_lp64 + printf " " + end +end + +# Print a userspace pointer, using $kgm_tasp +define showuserptr + set $kgm_userptr_task_64 = ( $kgm_taskp->taskFeatures[0] & 0x80000000) + if $kgm_userptr_task_64 + printf "0x%016llx", $arg0 + else + printf "0x%08x", $arg0 + end +end + +define showkmodheader + printf "kmod_info " + showptrhdrpad + printf " address " + showptrhdrpad + printf " size " + showptrhdrpad + printf " id refs version name\n" +end + +define showkmodint + set $kgm_kmodp = (struct kmod_info *)$arg0 + showptr $kgm_kmodp + printf " " + showptr $kgm_kmodp->address + printf " " + showptr $kgm_kmodp->size + printf " " + printf "%3d ", $kgm_kmodp->id + printf "%5d ", $kgm_kmodp->reference_count + printf "%10s ", $kgm_kmodp->version + printf "%s\n", $kgm_kmodp->name +end + +# cached info of the last kext found, to speed up subsequent lookups +set $kgm_pkmod = 0 +set $kgm_pkmodst = 0 +set $kgm_pkmoden = 0 + +define showkmodaddrint + showptr $arg0 + if ((unsigned long)$arg0 >= (unsigned long)$kgm_pkmodst) && ((unsigned long)$arg0 < (unsigned long)$kgm_pkmoden) + set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_pkmodst) + printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off + else + set $kgm_kmodp = (struct kmod_info *)kmod + if ($kgm_mtype == $kgm_mtype_x86_64) && ($arg0 >= (unsigned long)&_mh_execute_header) + # kexts are loaded below the kernel for x86_64 + set $kgm_kmodp = 0 + end + while $kgm_kmodp + set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_kmodp->address) + if ($kgm_kmodp->address <= $arg0) && ($kgm_off < $kgm_kmodp->size) + printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off + set $kgm_pkmod = $kgm_kmodp + set $kgm_pkmodst = $kgm_kmodp->address + set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmodp->size + set $kgm_kmodp = 0 + else + set $kgm_kmodp = $kgm_kmodp->next + end + end + end +end + +define showkmodaddr + showkmodaddrint $arg0 +end +document showkmodaddr +Syntax: (gdb) showkmodaddr +| Given an address, print the offset and name for the kmod containing it +end + +define showkmod + showkmodheader + showkmodint $arg0 +end +document showkmod +Syntax: (gdb) showkmod +| Routine to print info about a kext +end + +define showkext + showkmod $arg0 +end +document showkext +Syntax: (gdb) showkext +| Routine to print info about a kext +end + +define showallkmods + showkmodheader + set $kgm_kmodp = (struct kmod_info *)kmod + while $kgm_kmodp + showkmodint $kgm_kmodp + set $kgm_kmodp = $kgm_kmodp->next + end +end +document showallkmods +Syntax: (gdb) showallkmods +| Routine to print a summary listing of all loaded kexts +end + +define showallkexts + showallkmods +end +document showallkexts +Syntax: (gdb) showallkexts +| Routine to print a summary listing of all loaded kexts +end + +# See OSKextVersion.c for the C code this is based on +# +set $KGM_OSKEXT_VERS_MAJ_MULT = 100000000 +set $KGM_OSKEXT_VERS_MIN_MULT = 1000000 +set $KGM_OSKEXT_VERS_REV_MULT = 10000 +set $KGM_OSKEXT_VERS_STAGE_MULT = 1000 + +define printoskextversion + set $vers_scratch = $arg0 + + if ($vers_scratch == -1) + printf "(invalid)" + else + + set $vers_major = $vers_scratch / $KGM_OSKEXT_VERS_MAJ_MULT + + set $vers_scratch = $vers_scratch - ($vers_major * $KGM_OSKEXT_VERS_MAJ_MULT) + set $vers_minor = $vers_scratch / $KGM_OSKEXT_VERS_MIN_MULT + + set $vers_scratch = $vers_scratch - ( $vers_minor * $KGM_OSKEXT_VERS_MIN_MULT) + set $vers_revision = $vers_scratch / $KGM_OSKEXT_VERS_REV_MULT + + set $vers_scratch = $vers_scratch - ( $vers_revision * $KGM_OSKEXT_VERS_REV_MULT) + set $vers_stage = $vers_scratch / $KGM_OSKEXT_VERS_STAGE_MULT + + set $vers_scratch = $vers_scratch - ( $vers_stage * $KGM_OSKEXT_VERS_STAGE_MULT) + set $vers_stagelevel = $vers_scratch + + printf "%d.%d", $vers_major, $vers_minor + if ($vers_revision > 0) + printf ".%d", $vers_revision + end + + if ($vers_stage == 1) + printf "d" + end + if ($vers_stage == 3) + printf "a" + end + if ($vers_stage == 5) + printf "b" + end + if ($vers_stage == 7) + printf "fc" + end + if ($vers_stage == 1 || $vers_stage == 3 || $vers_stage == 5 || $vers_stage == 7) + printf "%d", $vers_stagelevel + end + end +end + +define showallknownkexts + set $kext_count = sKextsByID->count + set $kext_index = 0 + printf "%d kexts in sKextsByID:\n", $kext_count + + printf "OSKext * " + showptrhdrpad + printf "load_addr " + showptrhdrpad + + printf " id name (version)\n" + + while $kext_index < $kext_count + set $kext_id = sKextsByID->dictionary[$kext_index].key->string + set $oskext = (OSKext *)sKextsByID->dictionary[$kext_index].value + + showptr $oskext + printf " " + + if ($oskext->flags.loaded) + showptr $oskext->kmod_info + printf " " + printf "%3d", $oskext->loadTag + else + showptrhdrpad + printf " -------- " + printf " " + printf " --" + end + printf " " + + printf "%.64s (", $kext_id + printoskextversion (uint64_t)$oskext->version + printf ")\n" + set $kext_index = $kext_index + 1 + end +end +document showallknownkexts +Syntax: (gdb) showallknownkexts +| Routine to print a summary listing of all kexts, loaded or not +end + +define showactheader + printf " " + showptrhdrpad + printf " thread " + showptrhdrpad + printf " thread_id " + showptrhdrpad + printf " processor " + showptrhdrpad + printf " pri io_policy state wait_queue" + showptrhdrpad + printf " wait_event\n" +end + + +define showactint + printf " " + showptrhdrpad + set $kgm_thread = *(struct thread *)$arg0 + showptr $arg0 + if ($kgm_thread.static_param) + printf "[WQ]" + else + printf " " + end + printf " 0x%llx ", $kgm_thread.thread_id + showptr $kgm_thread.last_processor + printf " %3d ", $kgm_thread.sched_pri + if ($kgm_thread.uthread != 0) + set $kgm_printed = 0 + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_flag & 0x400) + printf "RAGE " + else + printf " " + end + set $diskpolicy = 0 + if ($kgm_thread->ext_appliedstate.hw_disk != 0) + set $diskpolicy = $kgm_thread->ext_appliedstate.hw_disk + else + if ($kgm_thread->appliedstate.hw_disk != 0) + set $diskpolicy = $kgm_thread->appliedstate.hw_disk + end + end + if ($kgm_thread->ext_appliedstate.hw_bg != 0) + set $diskpolicy = 5 + end + if ($kgm_thread->appliedstate.hw_bg != 0) + set $diskpolicy = 4 + end + if ($diskpolicy == 2) + printf "PASS " + set $kgm_printed = 1 + end + if ($diskpolicy == 3) + printf "THROT " + set $kgm_printed = 1 + end + if ($diskpolicy == 4) + printf "BG_THRT " + set $kgm_printed = 1 + end + if ($diskpolicy == 5) + printf "EBG_THRT" + set $kgm_printed = 1 + end + if ($kgm_printed == 0) + printf " " + end + end + set $kgm_state = $kgm_thread.state + if $kgm_state & 0x80 + printf "I" + end + if $kgm_state & 0x40 + printf "P" + end + if $kgm_state & 0x20 + printf "A" + end + if $kgm_state & 0x10 + printf "H" + end + if $kgm_state & 0x08 + printf "U" + end + if $kgm_state & 0x04 + printf "R" + end + if $kgm_state & 0x02 + printf "S" + end + if $kgm_state & 0x01 + printf "W" + printf "\t " + showptr $kgm_thread.wait_queue + printf " " + if (((unsigned long)$kgm_thread.wait_event > (unsigned long)&last_kernel_symbol) \ + && ($arg1 != 2) && ($kgm_show_kmod_syms == 0)) + showkmodaddr $kgm_thread.wait_event + else + output /a $kgm_thread.wait_event + end + if ($kgm_thread.uthread != 0) + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_wmesg != 0) + printf "\t \"%s\"", $kgm_uthread->uu_wmesg + end + end + end + if ($kgm_thread.uthread != 0) + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->pth_name && $kgm_uthread->pth_name[0]) + printf "\n\t\tThread Name: %s", $kgm_uthread->pth_name + end + end + if $arg1 != 0 + if ($kgm_thread.kernel_stack != 0) + if ($kgm_thread.uthread != 0) + printf "\n " + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_kwe.kwe_kwqqueue != 0) + set $kwq = (ksyn_wait_queue_t)$kgm_uthread->uu_kwe.kwe_kwqqueue + printf " kwq_lockcount:0x%x; kwq_retval:0x%x", $kgm_uthread->uu_kwe.kwe_lockseq, $kgm_uthread->uu_kwe.kwe_psynchretval + printf "\n " + show_kwq $kwq + printf " " + end + end + if ($kgm_thread.reserved_stack != 0) + printf "\n " + showptrhdrpad + printf " reserved_stack=" + showptr $kgm_thread.reserved_stack + end + printf "\n " + showptrhdrpad + printf " kernel_stack=" + showptr $kgm_thread.kernel_stack + if ($kgm_mtype == $kgm_mtype_ppc) + set $mysp = $kgm_thread.machine.pcb->save_r1 + end + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $kgm_statep = (struct x86_kernel_state *) \ + ($kgm_thread->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + if ($kgm_mtype == $kgm_mtype_i386) + set $mysp = $kgm_statep->k_ebp + else + set $mysp = $kgm_statep->k_rbp + end + end + if ($kgm_mtype == $kgm_mtype_arm) + if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) + set $mysp = $r7 + else + set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr + set $mysp = $kgm_statep->r[7] + end + end + set $prevsp = $mysp - 16 + printf "\n " + showptrhdrpad + printf " stacktop=" + showptr $mysp + if ($kgm_mtype == $kgm_mtype_ppc) + set $stkmask = 0xf + else + set $stkmask = 0x3 + end + set $kgm_return = 0 + set $kgm_actint_framecount = 0 + while ($mysp != 0) && (($mysp & $stkmask) == 0) \ + && ($mysp != $prevsp) \ + && ((((unsigned long) $mysp ^ (unsigned long) $prevsp) < 0x2000) \ + || (((unsigned long)$mysp < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$mysp > (unsigned long) ($kgm_thread->kernel_stack)))) \ + && ($kgm_actint_framecount < 128) + printf "\n " + set $kgm_actint_framecount = $kgm_actint_framecount + 1 + showptrhdrpad + printf " " + showptr $mysp + printf " " + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_return = *($mysp + 8) + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_return = *($mysp + 4) + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_return = *(unsigned long *)($mysp + 8) + end + if ($kgm_mtype == $kgm_mtype_arm) + set $kgm_return = *($mysp + 4) + end + if (((unsigned long) $kgm_return < (unsigned long) &_mh_execute_header || \ + (unsigned long) $kgm_return >= (unsigned long) &last_kernel_symbol ) \ + && ($kgm_show_kmod_syms == 0)) + showkmodaddr $kgm_return + else + output /a $kgm_return + end + set $prevsp = $mysp + set $mysp = *(unsigned long *)$mysp + end + set $kgm_return = 0 + printf "\n " + showptrhdrpad + printf " stackbottom=" + showptr $prevsp + else + printf "\n " + showptrhdrpad + printf " continuation=" + output /a $kgm_thread.continuation + end + printf "\n" + else + printf "\n" + end +end + +define showact + showactheader + showactint $arg0 0 +end +document showact +Syntax: (gdb) showact +| Routine to print out the state of a specific thread. +end + + +define showactstack + showactheader + showactint $arg0 1 +end +document showactstack +Syntax: (gdb) showactstack +| Routine to print out the stack of a specific thread. +end + + +define showallthreads + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + showactheader + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactint $kgm_actp 0 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showallthreads +Syntax: (gdb) showallthreads +| Routine to print out info about all threads in the system. +end + +define showprocessorint + set $kgm_processor_int = (struct processor *)$arg0 + printf "Processor " + showptr $kgm_processor_int + printf " State %d (cpu_id 0x%x)\n", ($kgm_processor_int)->state, ($kgm_processor_int)->cpu_id +end + +define showcurrentthreads + set $kgm_prp = (struct processor *)processor_list + while $kgm_prp != 0 + showprocessorint $kgm_prp + if ($kgm_prp)->active_thread != 0 + set $kgm_actp = ($kgm_prp)->active_thread + showtaskheader + showtaskint ($kgm_actp)->task + showactheader + showactint $kgm_actp 0 + printf "\n" + end + set $kgm_prp = ($kgm_prp)->processor_list + end +end +document showcurrentthreads +Syntax: (gdb) showcurrentthreads +| Routine to print out info about the thread running on each cpu. +end + + +define _showrunqint + set $kgm_runq = (struct run_queue *)$arg0 + + printf " Priority Run Queue Info: Count %d\n", $kgm_runq->count + set $kgm_runq_queue_i = 0 + set $kgm_runq_queue_count = sizeof($kgm_runq->queues)/sizeof($kgm_runq->queues[0]) + while $kgm_runq->count && $kgm_runq_queue_i < $kgm_runq_queue_count + set $kgm_runq_queue_head = &$kgm_runq->queues[$kgm_runq_queue_i] + set $kgm_runq_queue_p = $kgm_runq_queue_head->next + if $kgm_runq_queue_p != $kgm_runq_queue_head + set $kgm_runq_queue_this_count = 0 + while $kgm_runq_queue_p != $kgm_runq_queue_head + set $kgm_runq_queue_this_count = $kgm_runq_queue_this_count + 1 + showtask ((thread_t)$kgm_runq_queue_p)->task + showactstack $kgm_runq_queue_p + set $kgm_runq_queue_p = $kgm_runq_queue_p->next + end + printf " Queue Priority %3d [", $kgm_runq_queue_i + showptr $kgm_runq_queue_head + printf "] Count %d\n", $kgm_runq_queue_this_count + end + set $kgm_runq_queue_i = $kgm_runq_queue_i + 1 + end + +end + +define _showgrrrint + set $kgm_grrr_runq = $arg0 + + printf " GRRR Info: Count %d Weight %d Current Group ", $kgm_grrr_runq->count, $kgm_grrr_runq->weight + showptr $kgm_grrr_runq->current_group + printf "\n" + set $kgm_grrr_group_i = 0 + set $kgm_grrr_group_count = sizeof($kgm_grrr_runq->groups)/sizeof($kgm_grrr_runq->groups[0]) + while $kgm_grrr_runq->count && $kgm_grrr_group_i < $kgm_grrr_group_count + set $kgm_grrr_group = &$kgm_grrr_runq->groups[$kgm_grrr_group_i] + if $kgm_grrr_group->count > 0 + printf " Group %3d [", $kgm_grrr_group->index + showptr $kgm_grrr_group + printf "] Count %d Weight %d\n", $kgm_grrr_group->count, $kgm_grrr_group->weight + set $kgm_grrr_group_client_head = &$kgm_grrr_group->clients + set $kgm_grrr_group_client = $kgm_grrr_group_client_head->next + while $kgm_grrr_group_client != $kgm_grrr_group_client_head + # showtask ((thread_t)$kgm_grrr_group_client)->task + # showactstack $kgm_grrr_group_client + set $kgm_grrr_group_client = $kgm_grrr_group_client->next + end + end + set $kgm_grrr_group_i = $kgm_grrr_group_i + 1 + end +end + +define showallprocessors + set $kgm_pset = &pset0 + + set $kgm_show_grrr = 0 + set $kgm_show_priority_runq = 0 + set $kgm_show_priority_pset_runq = 0 + set $kgm_show_fairshare_grrr = 0 + set $kgm_show_fairshare_list = 0 + + if _sched_enum == 1 + set $kgm_show_priority_runq = 1 + set $kgm_show_fairshare_list = 1 + end + if _sched_enum == 2 + set $kgm_show_priority_pset_runq = 1 + set $kgm_show_fairshare_list = 1 + end + if _sched_enum == 4 + set $kgm_show_grrr = 1 + set $kgm_show_fairshare_grrr = 1 + end + if _sched_enum == 5 + set $kgm_show_priority_runq = 1 + set $kgm_show_fairshare_list = 1 + end + if _sched_enum == 6 + set $kgm_show_priority_pset_runq = 1 + set $kgm_show_fairshare_list = 1 + end + + while $kgm_pset != 0 + printf "Processor Set " + showptr $kgm_pset + printf " Count %d (cpu_id 0x%x-0x%x)\n", ($kgm_pset)->cpu_set_count, ($kgm_pset)->cpu_set_low, ($kgm_pset)->cpu_set_hi + printf " Active Processors:\n" + set $kgm_active_queue_head = &($kgm_pset)->active_queue + set $kgm_active_elt = $kgm_active_queue_head->next + while $kgm_active_elt != $kgm_active_queue_head + set $kgm_processor = (processor_t)$kgm_active_elt + printf " " + showprocessorint $kgm_processor + + if $kgm_show_priority_runq + set $kgm_runq = &$kgm_processor->runq + _showrunqint $kgm_runq + end + if $kgm_show_grrr + set $kgm_grrr_runq = &$kgm_processor->grrr_runq + _showgrrrint $kgm_grrr_runq + end + + if $kgm_processor->processor_meta != 0 && $kgm_processor->processor_meta->primary == $kgm_processor + set $kgm_processor_meta_idle_head = &$kgm_processor->processor_meta->idle_queue + set $kgm_processor_meta_idle = $kgm_processor_meta_idle_head->next + while $kgm_processor_meta_idle != $kgm_processor_meta_idle_head + printf " Idle Meta Processor: " + showprocessorint $kgm_processor_meta_idle + set $kgm_processor_meta_idle = $kgm_processor_meta_idle->next + end + end + + set $kgm_active_elt = $kgm_active_elt->next + end + printf " Idle Processors:\n" + set $kgm_idle_queue_head = &($kgm_pset)->idle_queue + set $kgm_idle_elt = $kgm_idle_queue_head->next + while $kgm_idle_elt != $kgm_idle_queue_head + set $kgm_processor = (processor_t)$kgm_idle_elt + printf " " + showprocessorint $kgm_processor + + if $kgm_processor->processor_meta != 0 && $kgm_processor->processor_meta->primary == $kgm_processor + set $kgm_processor_meta_idle_head = &$kgm_processor->processor_meta->idle_queue + set $kgm_processor_meta_idle = $kgm_processor_meta_idle_head->next + while $kgm_processor_meta_idle != $kgm_processor_meta_idle_head + printf " Idle Meta Processor: " + showprocessorint $kgm_processor_meta_idle + set $kgm_processor_meta_idle = $kgm_processor_meta_idle->next + end + end + + set $kgm_idle_elt = $kgm_idle_elt->next + end + + if $kgm_show_priority_pset_runq + set $kgm_runq = &$kgm_pset->pset_runq + printf "\n" + _showrunqint $kgm_runq + end + set $kgm_pset = ($kgm_pset)->pset_list + end + + printf "\n" + printf "Realtime Queue Count %d\n", rt_runq.count + set $kgm_rt_runq_head = &rt_runq.queue + set $kgm_rt_runq = $kgm_rt_runq_head->next + while $kgm_rt_runq != $kgm_rt_runq_head + showtask ((thread_t)$kgm_rt_runq)->task + showact $kgm_rt_runq + set $kgm_rt_runq = $kgm_rt_runq->next + end + + printf "\n" + if $kgm_show_fairshare_list + printf "Fair Share Queue Count %d\n", fs_runq.count + set $kgm_fs_runq_head = &fs_runq.queue + set $kgm_fs_runq = $kgm_fs_runq_head->next + while $kgm_fs_runq != $kgm_fs_runq_head + showtask ((thread_t)$kgm_fs_runq)->task + showact $kgm_fs_runq + set $kgm_fs_runq = $kgm_fs_runq->next + end + end + if $kgm_show_fairshare_grrr + printf "Fair Share Queue Count %d\n", fs_grrr_runq.count + set $kgm_fs_grrr = &fs_grrr_runq + _showgrrrint $kgm_fs_grrr + end +end +document showallprocessors +Syntax: (gdb) showallprocessors +| Routine to print out info about all psets and processors +end + +set $decode_wait_events = 0 +define showallstacks + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactheader + if ($decode_wait_events > 0) + showactint $kgm_actp 1 + else + showactint $kgm_actp 2 + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + + printf "\nZombie Processes:\n" + zombstacks +end + +document showallstacks +Syntax: (gdb) showallstacks +| Routine to print out the stack for each thread in the system. +| If the variable $decode_wait_events is non-zero, the routine attempts to +| interpret thread wait_events as kernel module offsets, which can add to +| processing time. +end + +define showcurrentstacks + set $kgm_prp = processor_list + while $kgm_prp != 0 + showprocessorint $kgm_prp + if ($kgm_prp)->active_thread != 0 + set $kgm_actp = ($kgm_prp)->active_thread + showtaskheader + showtaskint ($kgm_actp)->task + showactheader + showactint $kgm_actp 1 + printf "\n" + end + set $kgm_prp = ($kgm_prp)->processor_list + end +end + +document showcurrentstacks +Syntax: (gdb) showcurrentstacks +| Routine to print out the thread running on each cpu (incl. its stack) +end + +define showwaiterheader + printf "waiters thread " + printf "processor pri state wait_queue wait_event\n" +end + +define showwaitqwaiters + set $kgm_w_waitqp = (WaitQueue*)$arg0 + set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue) + set $kgm_w_wqe = (WaitQueueElement *)$kgm_w_linksp->next + set $kgm_w_found = 0 + while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp) + if ($kgm_w_wqe->wqe_type != &_wait_queue_link) + if !$kgm_w_found + set $kgm_w_found = 1 + showwaiterheader + end + set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe + showactint $kgm_w_shuttle 0 + end + set $kgm_w_wqe = (WaitQueueElement *)$kgm_w_wqe->wqe_links.next + end +end + +define showwaitqwaitercount + set $kgm_wc_waitqp = (WaitQueue*)$arg0 + set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue) + set $kgm_wc_wqe = (WaitQueueElement *)$kgm_wc_linksp->next + set $kgm_wc_count = 0 + while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp) + if ($kgm_wc_wqe->wqe_type != &_wait_queue_link) + set $kgm_wc_count = $kgm_wc_count + 1 + end + set $kgm_wc_wqe = (WaitQueueElement *)$kgm_wc_wqe->wqe_links.next + end + printf "0x%08x ", $kgm_wc_count +end + +define showwaitqmembercount + set $kgm_mc_waitqsetp = (WaitQueueSet*)$arg0 + set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks) + set $kgm_mc_wql = (WaitQueueLink *)$kgm_mc_setlinksp->next + set $kgm_mc_count = 0 + while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp) + set $kgm_mc_count = $kgm_mc_count + 1 + set $kgm_mc_wql = (WaitQueueLink *)$kgm_mc_wql->wql_setlinks.next + end + printf "0x%08x ", $kgm_mc_count +end + + +define showwaitqmemberheader + printf "set-members wait_queue interlock " + printf "pol type member_cnt waiter_cnt\n" +end + +define showwaitqmemberint + set $kgm_m_waitqp = (WaitQueue*)$arg0 + printf " 0x%08x ", $kgm_m_waitqp + printf "0x%08x ", $kgm_m_waitqp->wq_interlock.lock_data + if ($kgm_m_waitqp->wq_fifo) + printf "Fifo " + else + printf "Prio " + end + if ($kgm_m_waitqp->wq_type == 0xf1d1) + printf "Set " + showwaitqmembercount $kgm_m_waitqp + else + printf "Que 0x00000000 " + end + showwaitqwaitercount $kgm_m_waitqp + printf "\n" +end + + +define showwaitqmemberofheader + printf "member-of wait_queue interlock " + printf "pol type member_cnt waiter_cnt\n" +end + +define showwaitqmemberof + set $kgm_mo_waitqp = (WaitQueue*)$arg0 + set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue) + set $kgm_mo_wqe = (WaitQueueElement *)$kgm_mo_linksp->next + set $kgm_mo_found = 0 + while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp) + if ($kgm_mo_wqe->wqe_type == &_wait_queue_link) + if !$kgm_mo_found + set $kgm_mo_found = 1 + showwaitqmemberofheader + end + set $kgm_mo_wqlp = (WaitQueueLink *)$kgm_mo_wqe + set $kgm_mo_wqsetp = (WaitQueue*)($kgm_mo_wqlp->wql_setqueue) + showwaitqmemberint $kgm_mo_wqsetp + end + set $kgm_mo_wqe = (WaitQueueElement *)$kgm_mo_wqe->wqe_links.next + end +end + +define showwaitqmembers + set $kgm_ms_waitqsetp = (WaitQueueSet*)$arg0 + set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks) + set $kgm_ms_wql = (WaitQueueLink *)$kgm_ms_setlinksp->next + set $kgm_ms_found = 0 + while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp) + set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue + if !$kgm_ms_found + showwaitqmemberheader + set $kgm_ms_found = 1 + end + showwaitqmemberint $kgm_ms_waitqp + set $kgm_ms_wql = (WaitQueueLink *)$kgm_ms_wql->wql_setlinks.next + end +end + +define showwaitqheader + printf "wait_queue ref_count interlock " + printf "pol type member_cnt waiter_cnt\n" +end + +define showwaitqint + set $kgm_waitqp = (WaitQueue*)$arg0 + printf "0x%08x ", $kgm_waitqp + if ($kgm_waitqp->wq_type == 0xf1d1) + printf "0x%08x ", ((WaitQueueSet*)$kgm_waitqp)->wqs_refcount + else + printf "0x00000000 " + end + printf "0x%08x ", $kgm_waitqp->wq_interlock.lock_data + if ($kgm_waitqp->wq_fifo) + printf "Fifo " + else + printf "Prio " + end + if ($kgm_waitqp->wq_type == 0xf1d1) + printf "Set " + showwaitqmembercount $kgm_waitqp + else + printf "Que 0x00000000 " + end + showwaitqwaitercount $kgm_waitqp + printf "\n" +end + +define showwaitq + set $kgm_waitq1p = (WaitQueue*)$arg0 + showwaitqheader + showwaitqint $kgm_waitq1p + if ($kgm_waitq1p->wq_type == 0xf1d1) + showwaitqmembers $kgm_waitq1p + else + showwaitqmemberof $kgm_waitq1p + end + showwaitqwaiters $kgm_waitq1p +end + +define showmapheader + printf "vm_map " + showptrhdrpad + printf " pmap " + showptrhdrpad + printf " vm_size " + showptrhdrpad + printf " #ents rpage hint " + showptrhdrpad + printf " first_free\n" +end + +define showvmeheader + printf " entry " + showptrhdrpad + printf " start prot #page object " + showptrhdrpad + printf " offset\n" +end + +define showvmint + set $kgm_mapp = (vm_map_t)$arg0 + set $kgm_map = *$kgm_mapp + showptr $arg0 + printf " " + showptr $kgm_map.pmap + printf " " + showptr $kgm_map.size + printf " %3d ", $kgm_map.hdr.nentries + if $kgm_map.pmap + printf "%5d ", $kgm_map.pmap->stats.resident_count + else + printf " " + end + showptr $kgm_map.hint + printf " " + showptr $kgm_map.first_free + printf "\n" + if $arg1 != 0 + showvmeheader + set $kgm_head_vmep = &($kgm_mapp->hdr.links) + set $kgm_vmep = $kgm_map.hdr.links.next + while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) + set $kgm_vme = *$kgm_vmep + printf " " + showptr $kgm_vmep + printf " 0x%016llx ", $kgm_vme.links.start + printf "%1x", $kgm_vme.protection + printf "%1x", $kgm_vme.max_protection + if $kgm_vme.inheritance == 0x0 + printf "S" + end + if $kgm_vme.inheritance == 0x1 + printf "C" + end + if $kgm_vme.inheritance == 0x2 + printf "-" + end + if $kgm_vme.inheritance == 0x3 + printf "D" + end + if $kgm_vme.is_sub_map + printf "s " + else + if $kgm_vme.needs_copy + printf "n " + else + printf " " + end + end + printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 + showptr $kgm_vme.object.vm_object + printf " 0x%016llx\n", $kgm_vme.offset + set $kgm_vmep = $kgm_vme.links.next + end + end + printf "\n" +end + + +define showmapwiredp + set $kgm_mapp = (vm_map_t)$arg0 + set $kgm_map = *$kgm_mapp + set $kgm_head_vmep = &($kgm_mapp->hdr.links) + set $kgm_vmep = $kgm_map.hdr.links.next + set $kgm_objp_prev = (struct vm_object *)0 + if $arg1 == 0 + set $kgm_saw_kernel_obj = 0 + set $kgm_wired_count = 0 + set $kgm_objp_print_space = 1 + else + set $kgm_objp_print_space = 0 + end + while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) + set $kgm_vme = *$kgm_vmep + set $kgm_objp = $kgm_vme.object.vm_object + if $kgm_vme.is_sub_map + if $arg1 == 0 + set $kgm_mapp_orig = $kgm_mapp + set $kgm_vmep_orig = $kgm_vmep + set $kgm_vme_orig = $kgm_vme + set $kgm_head_vmep_orig = $kgm_head_vmep + printf "\n****" + showptr $kgm_objp + showmapwiredp $kgm_objp 1 + set $kgm_vme = $kgm_vme_orig + set $kgm_vmep = $kgm_vmep_orig + set $kgm_mapp = $kgm_mapp_orig + set $kgm_head_vmep = $kgm_head_vmep_orig + set $kgm_objp = (struct vm_object *)0 + else + printf "\n????" + showptr $kgm_mapp + printf " " + showptr $kgm_vmep + set $kgm_objp = (struct vm_object *)0 + printf "\n" + end + end + if ($kgm_objp == $kgm_objp_prev) + set $kgm_objp = (struct vm_object *)0 + end + if $kgm_objp == kernel_object + if $kgm_saw_kernel_obj + set $kgm_objp = (struct vm_object *)0 + end + set $kgm_saw_kernel_obj = 1 + end + if $kgm_objp && $kgm_objp->wired_page_count + if $kgm_objp_print_space == 1 + printf " " + showptr $kgm_mapp + end + set $kgm_objp_print_space = 1 + printf " " + showptr $kgm_vmep + printf " 0x%016llx ", $kgm_vme.links.start + printf "%5d", $kgm_vme.alias + printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 + showptr $kgm_objp + printf "[%3d]", $kgm_objp->ref_count + printf "%7d\n", $kgm_objp->wired_page_count + set $kgm_wired_count = $kgm_wired_count + $kgm_objp->wired_page_count + set $kgm_objp_prev = $kgm_objp + end + set $kgm_vmep = $kgm_vme.links.next + end + if $arg1 == 0 + printf "total wired count = %d\n", $kgm_wired_count + end +end + +define showmapwired + printf " map " + showptrhdrpad + printf " entry " + showptrhdrpad + printf " start alias #page object " + showptrhdrpad + printf " wired\n" + showmapwiredp $arg0 0 +end +document showmapwired +Syntax: (gdb) showmapwired +| Routine to print out a summary listing of all the entries with wired pages in a vm_map +end + +define showmapvme + showmapheader + showvmint $arg0 1 +end +document showmapvme +Syntax: (gdb) showmapvme +| Routine to print out a summary listing of all the entries in a vm_map +end + + +define showmap + showmapheader + showvmint $arg0 0 +end +document showmap +Syntax: (gdb) showmap +| Routine to print out info about the specified vm_map +end + +define showallvm + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showmapheader + showtaskint $kgm_taskp + showvmint $kgm_taskp->map 0 + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showallvm +Syntax: (gdb) showallvm +| Routine to print a summary listing of all the vm maps +end + + +define showallvme + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showmapheader + showtaskint $kgm_taskp + showvmint $kgm_taskp->map 1 + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showallvme +Syntax: (gdb) showallvme +| Routine to print a summary listing of all the vm map entries +end + + +define showipcheader + printf "ipc_space " + showptrhdrpad + printf " is_task " + showptrhdrpad + printf " is_table " + showptrhdrpad + printf " flags ports table_next " + showptrhdrpad + printf " low_mod high_mod\n" +end + +define showipceheader + printf " " + showptrhdrpad + printf "object " + showptrhdrpad + showptrhdrpad + printf "name rite urefs destname " + showptrhdrpad + printf "destination\n" +end + +define showipceint + set $kgm_ie = *(ipc_entry_t)$arg0 + printf " " + showptrhdrpad + showptr $kgm_ie.ie_object + showptrhdrpad + printf " 0x%08x ", $arg1 + if $kgm_ie.ie_bits & 0x00100000 + printf "Dead " + printf "%5d\n", $kgm_ie.ie_bits & 0xffff + else + if $kgm_ie.ie_bits & 0x00080000 + printf "SET " + printf "%5d\n", $kgm_ie.ie_bits & 0xffff + else + if $kgm_ie.ie_bits & 0x00010000 + if $kgm_ie.ie_bits & 0x00020000 + printf " SR" + else + printf " S" + end + else + if $kgm_ie.ie_bits & 0x00020000 + printf " R" + end + end + if $kgm_ie.ie_bits & 0x00040000 + printf " O" + end + if $kgm_ie.index.request + set $kgm_port = (ipc_port_t)$kgm_ie.ie_object + set $kgm_requests = $kgm_port->ip_requests + set $kgm_req_soright = $kgm_requests[$kgm_ie.index.request].notify.port + if $kgm_req_soright +# Armed send-possible notification? + if (uintptr_t)$kgm_req_soright & 0x1 + printf "s" + else +# Delayed send-possible notification? + if (uintptr_t)$kgm_req_soright & 0x2 + printf "d" + else +# Dead-name notification + printf "n" + end + end + else + printf " " + end + else + printf " " + end +# Collision (with tree)? + if $kgm_ie.ie_bits & 0x00800000 + printf "c" + else + printf " " + end + printf "%5d ", $kgm_ie.ie_bits & 0xffff + showportdest $kgm_ie.ie_object + end + end +end + +define showipcint + set $kgm_isp = (ipc_space_t)$arg0 + set $kgm_is = *$kgm_isp + showptr $arg0 + printf " " + showptr $kgm_is.is_task + printf " " + showptr $kgm_is.is_table + printf " " + if ($kgm_is.is_bits & 0x40000000) == 0 + printf "A" + else + printf " " + end + if ($kgm_is.is_bits & 0x20000000) != 0 + printf "G " + else + printf " " + end + printf "%5d ", $kgm_is.is_table_size + showptr $kgm_is.is_table_next + printf " " + printf "%10d ", $kgm_is.is_low_mod + printf "%10d", $kgm_is.is_high_mod + printf "\n" + if $arg1 != 0 + showipceheader + set $kgm_iindex = 0 + set $kgm_iep = $kgm_is.is_table + set $kgm_destspacep = (ipc_space_t)0 + while ( $kgm_iindex < $kgm_is.is_table_size ) + set $kgm_ie = *$kgm_iep + if $kgm_ie.ie_bits & 0x001f0000 + set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24)) + showipceint $kgm_iep $kgm_name + if $arg2 != 0 + if $kgm_ie.ie_object != 0 && ($kgm_ie.ie_bits & 0x00070000) && ((ipc_port_t) $kgm_ie.ie_object)->ip_callstack[0] != 0 + printf " user bt: " + showportbt $kgm_ie.ie_object $kgm_is.is_task + end + end + end + set $kgm_iindex = $kgm_iindex + 1 + set $kgm_iep = &($kgm_is.is_table[$kgm_iindex]) + end + end + printf "\n" +end + + +define showipc + set $kgm_isp = (ipc_space_t)$arg0 + showipcheader + showipcint $kgm_isp 0 0 +end +document showipc +Syntax: (gdb) showipc +| Routine to print the status of the specified ipc space +end + +define showrights + set $kgm_isp = (ipc_space_t)$arg0 + showipcheader + showipcint $kgm_isp 1 0 +end +document showrights +Syntax: (gdb) showrights +| Routine to print a summary list of all the rights in a specified ipc space +end + + +define showtaskipc + set $kgm_taskp = (task_t)$arg0 + showtaskheader + showtaskint $kgm_taskp + showipcheader + showipcint $kgm_taskp->itk_space 0 0 +end +document showtaskipc +Syntax: (gdb) showtaskipc +| Routine to print info about the ipc space for a task +end + + +define showtaskrights + set $kgm_taskp = (task_t)$arg0 + showtaskheader + showtaskint $kgm_taskp + showipcheader + showipcint $kgm_taskp->itk_space 1 0 +end +document showtaskrights +Syntax: (gdb) showtaskrights +| Routine to print info about the ipc rights for a task +end + +define showtaskrightsbt + set $kgm_taskp = (task_t)$arg0 + showtaskheader + showtaskint $kgm_taskp + showipcheader + showipcint $kgm_taskp->itk_space 1 1 +end +document showtaskrightsbt +Syntax: (gdb) showtaskrightsbt +| Routine to print info about the ipc rights for a task with backtraces +end + +define showallipc + set $kgm_head_taskp = &tasks + set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_cur_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_cur_taskp + showipcheader + showipcint $kgm_cur_taskp->itk_space 0 0 + set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) + end +end +document showallipc +Syntax: (gdb) showallipc +| Routine to print a summary listing of all the ipc spaces +end + +define showipcsumheader + printf "task " + showptrhdrpad + printf " pid " + printf " #acts " + printf " tsize " + printf "command\n" +end + +define showipcsummaryint + set $kgm_taskp = (struct task *)$arg0 + showptr $arg0 + printf "%7d", ((struct proc *)$kgm_taskp->bsd_info)->p_pid + printf "%15d", $kgm_taskp->thread_count + printf "%15d", $kgm_cur_taskp->itk_space.is_table_size + printf " %s\n", ((struct proc *)$kgm_taskp->bsd_info)->p_comm +end + +define showipcsummary + showipcsumheader + set $kgm_head_taskp = &tasks + set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_cur_taskp != $kgm_head_taskp + showipcsummaryint $kgm_cur_taskp + set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) + end +end + +document showipcsummary +Syntax: (gdb) showipcsummary +| Summarizes the IPC state of all tasks. This is a convenient way to dump +| some basic clues about IPC messaging. You can use the output to determine +| tasks that are candidates for further investigation. +end + + +define showallrights + set $kgm_head_taskp = &tasks + set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_cur_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_cur_taskp + showipcheader + showipcint $kgm_cur_taskp->itk_space 1 0 + set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) + end +end +document showallrights +Syntax: (gdb) showallrights +| Routine to print a summary listing of all the ipc rights +end + + +define showtaskvm + set $kgm_taskp = (task_t)$arg0 + showtaskheader + showmapheader + showtaskint $kgm_taskp + showvmint $kgm_taskp->map 0 +end +document showtaskvm +Syntax: (gdb) showtaskvm +| Routine to print out info about a task's vm_map +end + +define showtaskvme + set $kgm_taskp = (task_t)$arg0 + showtaskheader + showtaskint $kgm_taskp + showmapheader + showvmint $kgm_taskp->map 1 +end +document showtaskvme +Syntax: (gdb) showtaskvme +| Routine to print out info about a task's vm_map_entries +end + + +define showtaskheader + printf "task " + showptrhdrpad + printf " vm_map " + showptrhdrpad + printf " ipc_space " + showptrhdrpad + printf " #acts " + showprocheader +end + + +define showtaskint + set $kgm_taskp = (struct task *)$arg0 + showptr $arg0 + printf " " + showptr $kgm_taskp->map + printf " " + showptr $kgm_taskp->itk_space + printf " %5d ", $kgm_taskp->thread_count + showprocint $kgm_taskp->bsd_info +end + +define showtask + showtaskheader + showtaskint $arg0 +end +document showtask +Syntax (gdb) showtask +| Routine to print out info about a task. +end + + +define showtaskthreads + showtaskheader + set $kgm_taskp = (struct task *)$arg0 + showtaskint $kgm_taskp + showactheader + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactint $kgm_actp 0 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end +end +document showtaskthreads +Syntax: (gdb) showtaskthreads +| Routine to print info about the threads in a task. +end + + +define showtaskstacks + showtaskheader + set $kgm_taskp = (struct task *)$arg0 + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactheader + showactint $kgm_actp 1 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end +end +document showtaskstacks +Syntax: (gdb) showtaskstacks +| Routine to print out the stack for each thread in a task. +end + +define showqueue_elems + set $queue_head = (struct queue_entry *)($arg0) + set $queue = (struct queue_entry *)($queue_head->next) + while $queue != $queue_head + showptr $queue + printf " " + set $thread = (struct thread *)$queue + set $task = (struct task *)$thread->task + set $bsd = (struct proc *)$task->bsd_info + set $guy = (char *)$bsd->p_comm + showptr $thread + printf " " + showptr $task + printf " " + showptr $bsd + printf " " + showptr $guy + #printf " %s\n", $kgm_procp->p_comm + printf "\n" + set $queue = (struct queue_entry *)($queue->next) + end +end + +define showalltasks + showtaskheader + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskint $kgm_taskp + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showalltasks +Syntax: (gdb) showalltasks +| Routine to print a summary listing of all the tasks +| wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" +| if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung +| io_policy -> RAGE - rapid aging of vnodes requested +| NORM - normal I/O explicitly requested (this is the default) +| PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) +| THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) +end + +define showprocheader + printf " pid process " + showptrhdrpad + printf "io_policy wq_state command\n" +end + +define showprocint + set $kgm_procp = (struct proc *)$arg0 + if $kgm_procp != 0 + set $kgm_printed = 0 + printf "%5d ", $kgm_procp->p_pid + showptr $kgm_procp + if ($kgm_procp->p_lflag & 0x400000) + printf " RAGE " + else + printf " " + end + set $ptask = (struct task *)$kgm_procp->task + set $diskpolicy = 0 + if ($ptask->ext_appliedstate.hw_disk != 0) + set $diskpolicy = $ptask->ext_appliedstate.hw_disk + else + if ($ptask->appliedstate.hw_disk != 0) + set $diskpolicy = $ptask->appliedstate.hw_disk + end + end + if ($ptask->ext_appliedstate.hw_bg != 0) + set $diskpolicy = 5 + end + if ($ptask->appliedstate.hw_bg != 0) + set $diskpolicy = 4 + end + if ($ptask->ext_appliedstate.apptype == 2) + set $diskpolicy = 6 + end + if ($diskpolicy == 2) + printf "PASS " + set $kgm_printed = 1 + end + if ($diskpolicy == 3) + printf "THROT " + set $kgm_printed = 1 + end + if ($diskpolicy == 4) + printf "BG_THRT " + set $kgm_printed = 1 + end + if ($diskpolicy == 5) + printf "EBG_THRT" + set $kgm_printed = 1 + end + if ($diskpolicy == 6) + printf "APD_THRT" + set $kgm_printed = 1 + end + if ($kgm_printed == 0) + printf " " + end + set $kgm_wqp = (struct workqueue *)$kgm_procp->p_wqptr + if $kgm_wqp != 0 + printf " %2d %2d %2d ", $kgm_wqp->wq_nthreads, $kgm_wqp->wq_thidlecount, $kgm_wqp->wq_reqcount + else + printf " " + end + printf " %s\n", $kgm_procp->p_comm + else + printf " *0* " + showptr 0 + printf " --\n" + end +end + +define showpid + showtaskheader + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info + if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0)) + showtaskint $kgm_taskp + set $kgm_taskp = $kgm_head_taskp + else + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + end +end +document showpid +Syntax: (gdb) showpid +| Routine to print a single process by pid +end + +define showproc + showtaskheader + set $kgm_procp = (struct proc *)$arg0 + showtaskint $kgm_procp->task +end + + +define kdb + set switch_debugger=1 + continue +end +document kdb +| kdb - Switch to the inline kernel debugger +| +| usage: kdb +| +| The kdb macro allows you to invoke the inline kernel debugger. +end + +define showpsetheader + printf "portset " + showptrhdrpad + printf "waitqueue " + showptrhdrpad + showptrhdrpad + printf "recvname flags refs recvname " + showptrhdrpad + printf "process\n" +end + +define showportheader + printf "port " + showptrhdrpad + printf "mqueue " + showptrhdrpad + showptrhdrpad + printf "recvname flags refs recvname " + showptrhdrpad + printf "dest\n" +end + +define showportmemberheader + printf "members " + showptrhdrpad + printf "port " + showptrhdrpad + showptrhdrpad + printf "recvname " + printf "flags refs mqueue " + showptrhdrpad + printf "msgcount\n" +end + +define showkmsgheader + printf "dest-port " + showptrhdrpad + printf "kmsg " + showptrhdrpad + showptrhdrpad + printf "msgid " + printf "disp size " + printf "reply-port " + showptrhdrpad + printf "source\n" +end + +define showkmsgsrcint + set $kgm_kmsgsrchp = ((ipc_kmsg_t)$arg0)->ikm_header +# set $kgm_kmsgsrctp = (mach_msg_audit_trailer_t *)((uintptr_t)$kgm_kmsgsrchp + $kgm_kmsgsrchp->msgh_size) +# set $kgm_kmsgpid = $kgm_kmsgsrctp->msgh_audit.val[5] + set $kgm_kmsgpid = (pid_t)((uint *)((uintptr_t)$kgm_kmsgsrchp + $kgm_kmsgsrchp->msgh_size))[10] +# compare against a well-known or cached value as this may be slow + if ($kgm_kmsgpid == 0) + set $kgm_kmsgsrcpid = (pid_t)0 + set $kgm_kmsgsrcprocp = (struct proc *)kernel_task->bsd_info + else + if ($kgm_kmsgpid != $kgm_kmsgsrcpid) + set $kgm_kmsgsrchead_taskp = &tasks + set $kgm_kmsgsrctaskp = (struct task *)($kgm_kmsgsrchead_taskp->next) + while $kgm_kmsgsrctaskp != $kgm_kmsgsrchead_taskp + set $kgm_kmsgsrcprocp = (struct proc *)$kgm_kmsgsrctaskp->bsd_info + set $kgm_kmsgsrcpid = $kgm_kmsgsrcprocp->p_pid + if (($kgm_kmsgsrcprocp != 0) && ($kgm_kmsgsrcprocp->p_pid == $kgm_kmsgpid)) + set $kgm_kmsgsrctaskp = $kgm_kmsgsrchead_taskp + else + set $kgm_kmsgsrctaskp = (struct task *)($kgm_kmsgsrctaskp->tasks.next) + end + end + end + end + if ($kgm_kmsgsrcprocp->p_pid == $kgm_kmsgpid) + printf "%s(%d)\n", $kgm_kmsgsrcprocp->p_comm, $kgm_kmsgpid + else + printf "unknown(%d)\n", $kgm_kmsgpid + end +end + +define showkmsgint + set $kgm_kmsghp = ((ipc_kmsg_t)$arg0)->ikm_header + set $kgm_kmsgh = *$kgm_kmsghp + if ($arg1 != 0) + printf " " + showptrhdrpad + else + showptr $kgm_kmsgh.msgh_remote_port + end + showptr $arg0 + showptrhdrpad + printf " 0x%08x ", $kgm_kmsgh.msgh_id + if (($kgm_kmsgh.msgh_bits & 0xff) == 19) + printf "rC" + else + printf "rM" + end + if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 << 8)) + printf "lC" + else + printf "lM" + end + if ($kgm_kmsgh.msgh_bits & 0xf0000000) + printf "c" + else + printf "s" + end + printf "%5d ", $kgm_kmsgh.msgh_size + showptr $kgm_kmsgh.msgh_local_port + printf " " + set $kgm_kmsgsrcpid = (pid_t)0 + showkmsgsrcint $arg0 +end + +define showkmsg + showkmsgint $arg0 0 +end + +define showkobject + set $kgm_portp = (struct ipc_port *)$arg0 + showptr $kgm_portp->ip_kobject + printf " kobject(" + set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff) + if ($kgm_kotype == 1) + printf "THREAD" + end + if ($kgm_kotype == 2) + printf "TASK" + end + if ($kgm_kotype == 3) + printf "HOST" + end + if ($kgm_kotype == 4) + printf "HOST_PRIV" + end + if ($kgm_kotype == 5) + printf "PROCESSOR" + end + if ($kgm_kotype == 6) + printf "PSET" + end + if ($kgm_kotype == 7) + printf "PSET_NAME" + end + if ($kgm_kotype == 8) + printf "TIMER" + end + if ($kgm_kotype == 9) + printf "PAGER_REQ" + end + if ($kgm_kotype == 10) + printf "DEVICE" + end + if ($kgm_kotype == 11) + printf "XMM_OBJECT" + end + if ($kgm_kotype == 12) + printf "XMM_PAGER" + end + if ($kgm_kotype == 13) + printf "XMM_KERNEL" + end + if ($kgm_kotype == 14) + printf "XMM_REPLY" + end + if ($kgm_kotype == 15) + printf "NOTDEF 15" + end + if ($kgm_kotype == 16) + printf "NOTDEF 16" + end + if ($kgm_kotype == 17) + printf "HOST_SEC" + end + if ($kgm_kotype == 18) + printf "LEDGER" + end + if ($kgm_kotype == 19) + printf "MASTER_DEV" + end + if ($kgm_kotype == 20) + printf "ACTIVATION" + end + if ($kgm_kotype == 21) + printf "SUBSYSTEM" + end + if ($kgm_kotype == 22) + printf "IO_DONE_QUE" + end + if ($kgm_kotype == 23) + printf "SEMAPHORE" + end + if ($kgm_kotype == 24) + printf "LOCK_SET" + end + if ($kgm_kotype == 25) + printf "CLOCK" + end + if ($kgm_kotype == 26) + printf "CLOCK_CTRL" + end + if ($kgm_kotype == 27) + printf "IOKIT_SPARE" + end + if ($kgm_kotype == 28) + printf "NAMED_MEM" + end + if ($kgm_kotype == 29) + printf "IOKIT_CON" + end + if ($kgm_kotype == 30) + printf "IOKIT_OBJ" + end + if ($kgm_kotype == 31) + printf "UPL" + end + if ($kgm_kotype == 34) + printf "FD" + end + printf ")\n" +end + +define showportdestproc + set $kgm_portp = (struct ipc_port *)$arg0 + set $kgm_spacep = $kgm_portp->data.receiver +# check against the previous cached value - this is slow + if ($kgm_spacep != $kgm_destspacep) + set $kgm_destprocp = (struct proc *)0 + set $kgm_head_taskp = &tasks + set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next) + while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp)) + set $kgm_destspacep = $kgm_desttaskp->itk_space + if ($kgm_destspacep == $kgm_spacep) + set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info + else + set $kgm_desttaskp = (struct task *)($kgm_desttaskp->tasks.next) + end + end + end + if $kgm_destprocp != 0 + printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid + else + printf "task " + showptr $kgm_desttaskp + printf "\n" + end +end + +define showportdest + set $kgm_portp = (struct ipc_port *)$arg0 + set $kgm_spacep = $kgm_portp->data.receiver + if ((uintptr_t)$kgm_spacep == (uintptr_t)ipc_space_kernel) + showkobject $kgm_portp + else + if ($kgm_portp->ip_object.io_bits & 0x80000000) + showptr $kgm_portp->ip_messages.data.port.receiver_name + printf " " + showportdestproc $kgm_portp + else + showptr $kgm_portp + printf " inactive-port\n" + end + end +end + +define showportmember + printf " " + showptrhdrpad + showptr $arg0 + showptrhdrpad + set $kgm_portp = (struct ipc_port *)$arg0 + printf " 0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name + if ($kgm_portp->ip_object.io_bits & 0x80000000) + printf "A" + else + printf " " + end + printf "Port" + printf "%5d ", $kgm_portp->ip_object.io_references + showptr &($kgm_portp->ip_messages) + printf " 0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount +end + +define showportbt + set $kgm_iebt = ((ipc_port_t) $arg0)->ip_callstack + set $kgm_iepid = ((ipc_port_t) $arg0)->ip_spares[0] + set $kgm_procpid = ((proc_t) (((task_t) $arg1)->bsd_info))->p_pid + if $kgm_iebt[0] != 0 + showptr $kgm_iebt[0] + set $kgm_iebt_loop_ctr = 1 + while ($kgm_iebt_loop_ctr < 16 && $kgm_iebt[$kgm_iebt_loop_ctr]) + printf " " + showptr $kgm_iebt[$kgm_iebt_loop_ctr] + set $kgm_iebt_loop_ctr = $kgm_iebt_loop_ctr + 1 + end + if $kgm_iepid != $kgm_procpid + printf " (%d)", $kgm_iepid + end + printf "\n" + end +end + +define showportint + showptr $arg0 + printf " " + set $kgm_portp = (struct ipc_port *)$arg0 + showptr &($kgm_portp->ip_messages) + showptrhdrpad + printf " 0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name + if ($kgm_portp->ip_object.io_bits & 0x80000000) + printf "A" + else + printf "D" + end + printf "Port" + printf "%5d ", $kgm_portp->ip_object.io_references + set $kgm_destspacep = (struct ipc_space *)0 + showportdest $kgm_portp + set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base + if $arg1 && $kgm_kmsgp + showkmsgheader + showkmsgint $kgm_kmsgp 1 + set $kgm_kmsgheadp = $kgm_kmsgp + set $kgm_kmsgp = $kgm_kmsgp->ikm_next + while $kgm_kmsgp != $kgm_kmsgheadp + showkmsgint $kgm_kmsgp 1 + set $kgm_kmsgp = $kgm_kmsgp->ikm_next + end + end +end + +define showpsetint + showptr $arg0 + printf " " + set $kgm_psetp = (struct ipc_pset *)$arg0 + showptr &($kgm_psetp->ips_messages) + showptrhdrpad + printf " 0x%08x ", $kgm_psetp->ips_messages.data.pset.local_name + if ($kgm_psetp->ips_object.io_bits & 0x80000000) + printf "A" + else + printf "D" + end + printf "Set " + printf "%5d ", $kgm_psetp->ips_object.io_references + showptr $kgm_psetp->ips_messages.data.pset.local_name + printf " " + set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.pset.set_queue.wqs_setlinks) + set $kgm_wql = (WaitQueueLink *)$kgm_setlinksp->next + set $kgm_found = 0 + while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp) + set $kgm_portp = (struct ipc_port *)((uintptr_t)($kgm_wql->wql_element->wqe_queue) - (uintptr_t)$kgm_portoff) + if !$kgm_found + set $kgm_destspacep = (struct ipc_space *)0 + showportdestproc $kgm_portp + showportmemberheader + set $kgm_found = 1 + end + showportmember $kgm_portp 0 + set $kgm_wql = (WaitQueueLink *)$kgm_wql->wql_setlinks.next + end + if !$kgm_found + printf "--n/e--\n" + end +end + +define showpset + set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages) + showpsetheader + showpsetint $arg0 1 +end + +define showport + showportheader + showportint $arg0 1 +end + +define showipcobject + set $kgm_objectp = (ipc_object_t)$arg0 + if ($kgm_objectp->io_bits & 0x7fff0000) + set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages) + showpset $kgm_objectp + else + showport $kgm_objectp + end +end + +define showmqueue + set $kgm_mqueue = *(struct ipc_mqueue *)$arg0 + if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d1) + set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages) + set $kgm_pset = (((long)$arg0) - ((long)$kgm_psetoff)) + showpsetheader + showpsetint $kgm_pset 1 + end + if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d0) + set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages) + set $kgm_port = (((long)$arg0) - ((long)$kgm_portoff)) + showportheader + showportint $kgm_port 1 + end +end + +define zprint_one + set $kgm_zone = (struct zone *)$arg0 + + showptr $kgm_zone + printf " %8d ",$kgm_zone->count + printf "%8x ",$kgm_zone->cur_size + printf "%8x ",$kgm_zone->max_size + printf "%8d ",$kgm_zone->elem_size + printf "%8x ",$kgm_zone->alloc_size + if ($kgm_mtype != $kgm_mtype_arm) + printf " %16ld ",$kgm_zone->num_allocs + printf "%16ld ",$kgm_zone->num_frees + end + printf "%s ",$kgm_zone->zone_name + + if ($kgm_zone->exhaustible) + printf "H" + end + if ($kgm_zone->collectable) + printf "C" + end + if ($kgm_zone->expandable) + printf "X" + end + if ($kgm_zone->noencrypt) + printf "$" + end + printf "\n" +end + + +define zprint + printf "ZONE " + showptrhdrpad + printf " COUNT TOT_SZ MAX_SZ ELT_SZ ALLOC_SZ TOT_ALLOC TOT_FREE NAME\n" + set $kgm_zone_ptr = (struct zone *)first_zone + while ($kgm_zone_ptr != 0) + zprint_one $kgm_zone_ptr + set $kgm_zone_ptr = $kgm_zone_ptr->next_zone + end + printf "\n" +end +document zprint +Syntax: (gdb) zprint +| Routine to print a summary listing of all the kernel zones +end + +define showmtxgrp + set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0 + + if ($kgm_mtxgrp->lck_grp_mtxcnt) + showptr $kgm_mtxgrp + printf " %8d ",$kgm_mtxgrp->lck_grp_mtxcnt + printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt + printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt + printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt + printf "%s ",&$kgm_mtxgrp->lck_grp_name + printf "\n" + end +end + + +define showallmtx + printf "LCK GROUP " + showptrhdrpad + printf " CNT UTIL MISS WAIT NAME\n" + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next + while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) + showmtxgrp $kgm_mtxgrp_ptr + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next + end + printf "\n" +end +document showallmtx +Syntax: (gdb) showallmtx +| Routine to print a summary listing of all mutexes +end + +define showrwlckgrp + set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0 + + if ($kgm_rwlckgrp->lck_grp_rwcnt) + showptr $kgm_rwlckgrp + printf " %8d ",$kgm_rwlckgrp->lck_grp_rwcnt + printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt + printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt + printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt + printf "%s ",&$kgm_rwlckgrp->lck_grp_name + printf "\n" + end +end + + +define showallrwlck + printf "LCK GROUP " + showptrhdrpad + printf " CNT UTIL MISS WAIT NAME\n" + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next + while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) + showrwlckgrp $kgm_rwlckgrp_ptr + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next + end + printf "\n" +end +document showallrwlck +Syntax: (gdb) showallrwlck +| Routine to print a summary listing of all read/writer locks +end + +set $kdp_act_counter = 0 +set $kdp_arm_act_counter = 0 + +set $r0_save = 0 +set $r1_save = 0 +set $r2_save = 0 +set $r3_save = 0 +set $r4_save = 0 +set $r5_save = 0 +set $r6_save = 0 +set $r7_save = 0 +set $r8_save = 0 +set $r9_save = 0 +set $r10_save = 0 +set $r11_save = 0 +set $r12_save = 0 +set $sp_save = 0 +set $lr_save = 0 +set $pc_save = 0 + +define showcontext_int + echo Context switched, current instruction pointer: + output/a $pc + echo \n +end + +define switchtoact + set $newact = (struct thread *) $arg0 + select 0 + if ($newact->kernel_stack == 0) + echo This activation does not have a stack.\n + echo continuation: + output/a (unsigned) $newact.continuation + echo \n + else + if ($kgm_mtype == $kgm_mtype_ppc) + if ($kdp_act_counter == 0) + set $kdpstate = (struct savearea *) kdp.saved_state + end + set $kdp_act_counter = $kdp_act_counter + 1 + set (struct savearea *) kdp.saved_state=$newact->machine->pcb + flushregs + flushstack + set $pc=$newact->machine->pcb.save_srr0 + update + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + if ($kdp_act_counter == 0) + set $kdpstate = *($kdpstatep) + end + set $kdp_act_counter = $kdp_act_counter + 1 + + set $kgm_statep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + set $kdpstatep->ebx = $kgm_statep->k_ebx + set $kdpstatep->ebp = $kgm_statep->k_ebp + set $kdpstatep->edi = $kgm_statep->k_edi + set $kdpstatep->esi = $kgm_statep->k_esi + set $kdpstatep->eip = $kgm_statep->k_eip + flushregs + flushstack + set $pc = $kgm_statep->k_eip + update + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state + if ($kdp_act_counter == 0) + set $kdpstate = *($kdpstatep) + end + set $kdp_act_counter = $kdp_act_counter + 1 + + set $kgm_statep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + set $kdpstatep->rbx = $kgm_statep->k_rbx + set $kdpstatep->rbp = $kgm_statep->k_rbp + set $kdpstatep->r12 = $kgm_statep->k_r12 + set $kdpstatep->r13 = $kgm_statep->k_r13 + set $kdpstatep->r14 = $kgm_statep->k_r14 + set $kdpstatep->r15 = $kgm_statep->k_r15 + set $kdpstatep->isf.rsp = $kgm_statep->k_rsp + flushregs + flushstack + set $pc = $kgm_statep->k_rip + update + end + if ($kgm_mtype == $kgm_mtype_arm) + set $kdp_arm_act_counter = $kdp_arm_act_counter + 1 + if ($kdp_arm_act_counter == 1) + set $r0_save = $r0 + set $r1_save = $r1 + set $r2_save = $r2 + set $r3_save = $r3 + set $r4_save = $r4 + set $r5_save = $r5 + set $r6_save = $r6 + set $r7_save = $r7 + set $r8_save = $r8 + set $r9_save = $r9 + set $r10_save = $r10 + set $r11_save = $r11 + set $r12_save = $r12 + set $sp_save = $sp + set $lr_save = $lr + set $pc_save = $pc + end + set $pc_ctx = load_reg+8 + set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr + set $r0 = $kgm_statep->r[0] + set $r1 = $kgm_statep->r[1] + set $r2 = $kgm_statep->r[2] + set $r3 = $kgm_statep->r[3] + set $r4 = $kgm_statep->r[4] + set $r5 = $kgm_statep->r[5] + set $r6 = $kgm_statep->r[6] + set $r8 = $kgm_statep->r[8] + set $r9 = $kgm_statep->r[9] + set $r10 = $kgm_statep->r[10] + set $r11 = $kgm_statep->r[11] + set $r12 = $kgm_statep->r[12] + set $sp = $kgm_statep->sp + set $lr = $kgm_statep->lr + set $pc = $pc_ctx + set $r7 = $kgm_statep->r[7] + flushregs + flushstack + end + end + showcontext_int +end + +document switchtoact +Syntax: switchtoact
+| This command allows gdb to examine the execution context and call +| stack for the specified activation. For example, to view the backtrace +| for an activation issue "switchtoact
", followed by "bt". +| Before resuming execution, issue a "resetctx" command, to +| return to the original execution context. +end + +define switchtoctx + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + if ($kdp_act_counter == 0) + set $kdpstate = (struct savearea *) kdp.saved_state + end + set $kdp_act_counter = $kdp_act_counter + 1 + set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0 + flushregs + flushstack + set $pc=((struct savearea *) $arg0)->save_srr0 + update + else + if ($kgm_mtype == $kgm_mtype_arm) + select 0 + set $kdp_arm_act_counter = $kdp_arm_act_counter + 1 + if ($kdp_arm_act_counter == 1) + set $r0_save = $r0 + set $r1_save = $r1 + set $r2_save = $r2 + set $r3_save = $r3 + set $r4_save = $r4 + set $r5_save = $r5 + set $r6_save = $r6 + set $r7_save = $r7 + set $r8_save = $r8 + set $r9_save = $r9 + set $r10_save = $r10 + set $r11_save = $r11 + set $r12_save = $r12 + set $sp_save = $sp + set $lr_save = $lr + set $pc_save = $pc + end + set $kgm_statep = (struct arm_saved_state *)$arg0 + set $r0 = $kgm_statep->r[0] + set $r1 = $kgm_statep->r[1] + set $r2 = $kgm_statep->r[2] + set $r3 = $kgm_statep->r[3] + set $r4 = $kgm_statep->r[4] + set $r5 = $kgm_statep->r[5] + set $r6 = $kgm_statep->r[6] + set $r8 = $kgm_statep->r[8] + set $r9 = $kgm_statep->r[9] + set $r10 = $kgm_statep->r[10] + set $r11 = $kgm_statep->r[11] + set $r12 = $kgm_statep->r[12] + set $sp = $kgm_statep->sp + set $lr = $kgm_statep->lr + set $r7 = $kgm_statep->r[7] + set $pc = $kgm_statep->pc + flushregs + flushstack + update + else + echo switchtoctx not implemented for this architecture.\n + end + end +end + + +document switchtoctx +Syntax: switchtoctx
+| This command allows gdb to examine an execution context and dump the +| backtrace for this execution context. +| Before resuming execution, issue a "resetctx" command, to +| return to the original execution context. +end + +define resetctx + select 0 + if ($kdp_act_counter != 0) + if ($kgm_mtype == $kgm_mtype_ppc) + set (struct savearea *)kdp.saved_state=$kdpstate + flushregs + flushstack + set $pc=((struct savearea *) kdp.saved_state)->save_srr0 + update + set $kdp_act_counter = 0 + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + set *($kdpstatep)=$kdpstate + flushregs + flushstack + set $pc=$kdpstatep->eip + update + set $kdp_act_counter = 0 + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state + set *($kdpstatep)=$kdpstate + flushregs + flushstack + set $pc=$kdpstatep->isf.rip + update + set $kdp_act_counter = 0 + end + showcontext_int + end + if ($kgm_mtype == $kgm_mtype_arm && $kdp_arm_act_counter != 0) + echo Restoring context\n + set $r0 = $r0_save + flushregs + set $r1 = $r1_save + flushregs + set $r2 = $r2_save + flushregs + set $r3 = $r3_save + flushregs + set $r4 = $r4_save + flushregs + set $r5 = $r5_save + flushregs + set $r6 = $r6_save + flushregs + set $r8 = $r8_save + flushregs + set $r9 = $r9_save + flushregs + set $r10 = $r10_save + flushregs + set $r11 = $r11_save + flushregs + set $r12 = $r12_save + flushregs + set $sp = $sp_save + flushregs + set $lr = $lr_save + flushregs + set $pc = $pc_save + flushregs + set $r7 = $r7_save + flushregs + flushstack + update + set $kdp_arm_act_counter = 0 + end +end + +document resetctx +| Syntax: resetctx +| Returns to the original execution context. This command should be +| issued if you wish to resume execution after using the "switchtoact" +| or "switchtoctx" commands. +end + +# This is a pre-hook for the continue command, to prevent inadvertent attempts +# to resume from the context switched to for examination. +define hook-continue + resetctx +end + +# This is a pre-hook for the detach command, to prevent inadvertent attempts +# to resume from the context switched to for examination. +define hook-detach + resetctx +end + +define resume_on + set $resume = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_RESUME + dumpinfoint $resume +end + +document resume_on +| Syntax: resume_on +| The target system will resume when detaching or exiting from gdb. +| This is the default behavior. +end + +define resume_off + set $noresume = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_NORESUME + dumpinfoint $noresume +end + +document resume_off +| Syntax: resume_off +| The target system won't resume after detaching from gdb and +| can be attached with a new gdb session +end + +define paniclog + set $kgm_panic_bufptr = debug_buf + set $kgm_panic_bufptr_max = debug_buf_ptr + while $kgm_panic_bufptr < $kgm_panic_bufptr_max + if *(char *)$kgm_panic_bufptr == 10 + printf "\n" + else + printf "%c", *(char *)$kgm_panic_bufptr + end + set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1 + end +end + +document paniclog +| Syntax: paniclog +| Display the panic log information +| +end + +define dumpcallqueue + set $kgm_callhead = $arg0 + set $kgm_callentry = $kgm_callhead->next + set $kgm_i = 0 + while $kgm_callentry != $kgm_callhead + set $kgm_call = (struct call_entry *)$kgm_callentry + showptr $kgm_call + printf "0x%lx 0x%lx ", $kgm_call->param0, $kgm_call->param1 + output $kgm_call->deadline + printf "\t" + output $kgm_call->func + printf "\n" + set $kgm_i = $kgm_i + 1 + set $kgm_callentry = $kgm_callentry->next + end + printf "%d entries\n", $kgm_i +end + +document dumpcallqueue +| Syntax: dumpcallqueue +| Displays the contents of the specified call_entry queue. +end + +define showtaskacts +showtaskthreads $arg0 +end +document showtaskacts +| See help showtaskthreads. +end + +define showallacts +showallthreads +end +document showallacts +| See help showallthreads. +end + + +define resetstacks + _kgm_flush_loop + set kdp_pmap = 0 + _kgm_flush_loop + resetctx + _kgm_flush_loop + _kgm_update_loop + resetctx + _kgm_update_loop +end + +document resetstacks +| Syntax: resetstacks +| Internal kgmacro routine used by the "showuserstack" macro +| to reset the target pmap to the kernel pmap. +end + +#Barely effective hacks to work around bugs in the "flush" and "update" +#gdb commands in Tiger (up to 219); these aren't necessary with Panther +#gdb, but do no harm. +define _kgm_flush_loop + set $kgm_flush_loop_ctr = 0 + while ($kgm_flush_loop_ctr < 30) + flushregs + flushstack + set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1 + end +end + +define _kgm_update_loop + set $kgm_update_loop_ctr = 0 + while ($kgm_update_loop_ctr < 30) + update + set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1 + end +end +# Internal routine used by "_loadfrom" to read from 64-bit addresses +# on 32-bit kernels +define _loadk32m64 + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = sizeof(uint64_t) + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_k32read64 = *(uint64_t *)$kgm_pkt->data + else + set $kgm_k32read64 = 0 + end +end + +# Internal routine used by "showx86backtrace" to abstract possible loads from +# user space +define _loadfrom + if (kdp_pmap == 0) + set $kgm_loadval = *(uintptr_t *)$arg0 + else + if ($kgm_x86_abi == 0xe) + set $kgm_loadval = *(uint32_t *)$arg0 + else + if ($kgm_x86_abi == 0xf) + if ($kgm_mtype == $kgm_mtype_i386) + _loadk32m64 $arg0 + set $kgm_loadval = $kgm_k32read64 + else + set $kgm_loadval = *(uint64_t *)$arg0 + end + end + end +end +end + + +#This is necessary since gdb often doesn't do backtraces on x86 correctly +#in the absence of symbols.The code below in showuserstack and +#showx86backtrace also contains several workarouds for the gdb bug where +#gdb stops macro evaluation because of spurious "Cannot read memory" +#errors on x86. These errors appear on ppc as well, but they don't +#always stop macro evaluation. + +set $kgm_cur_frame = 0 +set $kgm_cur_pc = 0 +set $kgm_x86_abi = 0 +define showx86backtrace + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_frame_reg = $ebp + set $kgm_pc = $eip + set $kgm_ret_off = 4 + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_frame_reg = $rbp + set $kgm_pc = $rip + set $kgm_ret_off = 8 + end + + if ($kgm_x86_abi == 0xe) + set $kgm_ret_off = 4 + end + if ($kgm_x86_abi == 0xf) + set $kgm_ret_off = 8 + end + + if ($kgm_cur_frame == 0) + set $kgm_cur_frame = $kgm_frame_reg + end + if ($kgm_cur_pc == 0) + set $kgm_cur_pc = $kgm_pc + end + printf "0: Frame: 0x%016llx PC: 0x%016llx\n", $kgm_cur_frame, $kgm_cur_pc + if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) + x/i $kgm_cur_pc + end + set $kgm_tmp_frame = $kgm_cur_frame + set $kgm_cur_frame = 0 + set $kgm_cur_pc = 0 + _loadfrom ($kgm_tmp_frame) + set $kgm_prev_frame = $kgm_loadval + _loadfrom ($kgm_tmp_frame+$kgm_ret_off) + set $kgm_prev_pc = $kgm_loadval + set $kgm_frameno = 1 + while ($kgm_prev_frame != 0) && ($kgm_prev_frame != 0x0000000800000008) + printf "%d: Saved frame: 0x%016llx Saved PC: 0x%016llx\n", $kgm_frameno, $kgm_prev_frame, $kgm_prev_pc + if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) + x/i $kgm_prev_pc + end + _loadfrom ($kgm_prev_frame+$kgm_ret_off) + set $kgm_prev_pc = $kgm_loadval + _loadfrom ($kgm_prev_frame) + set $kgm_prev_frame = $kgm_loadval + set $kgm_frameno = $kgm_frameno + 1 + end + set kdp_pmap = 0 + set $kgm_x86_abi = 0 +end + +define showx86backtrace2 + set $kgm_cur_frame = $arg0 + set $kgm_cur_pc = $arg1 + showx86backtrace +end + +define showuserstack + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + if ($kdp_act_counter == 0) + set $kdpstate = (struct savearea *) kdp.saved_state + end + set $kdp_act_counter = $kdp_act_counter + 1 + set $newact = (struct thread *) $arg0 + _kgm_flush_loop + set $checkpc = $newact->machine->upcb.save_srr0 + if ($checkpc == 0) + echo This activation does not appear to have + echo \20 a valid user context.\n + else + set (struct savearea *) kdp.saved_state=$newact->machine->upcb + set $pc = $checkpc +#flush and update seem to be executed lazily by gdb on Tiger, hence the +#repeated invocations - see 3743135 + _kgm_flush_loop +# This works because the new pmap is used only for reads + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + bt + resetstacks + _kgm_flush_loop + _kgm_update_loop + resetstacks + _kgm_flush_loop + _kgm_update_loop + end + else + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $newact = (struct thread *) $arg0 + set $newiss = (x86_saved_state_t *) ($newact->machine->iss) + set $kgm_x86_abi = $newiss.flavor + if ($newiss.flavor == 0xf) + set $checkpc = $newiss.uss.ss_64.isf.rip + set $checkframe = $newiss.uss.ss_64.rbp + + else + set $checkpc = $newiss.uss.ss_32.eip + set $checkframe = $newiss.uss.ss_32.ebp + end + + if ($checkpc == 0) + echo This activation does not appear to have + echo \20 a valid user context.\n + else + set $kgm_cur_frame = $checkframe + set $kgm_cur_pc = $checkpc +# When have more than one argument is present, don't print usage + if ( $argc == 1 ) + printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread (" + showptr $arg0 + printf "); you can also examine memory locations in this address space (pmap " + showptr $newact->task->map->pmap + printf ") before issuing the backtrace. This two-step process is necessary to work around various bugs in x86 gdb, which cause it to stop memory evaluation on spurious memory read errors. Additionally, you may need to issue a set kdp_pmap = 0 command after the showx86backtrace completes, to resume reading from the kernel address space.\n" + end + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + end + else + if ($kgm_mtype == $kgm_mtype_arm) + if (kdp->is_conn > 0) + set $kgm_threadp = (struct thread *)$arg0 + set $kgm_saved_pmap = kdp_pmap + showactheader + showactint $kgm_threadp 0 + set $kgm_thread_pmap = $kgm_threadp->task->map->pmap + set $kgm_thread_sp = $kgm_threadp.machine->PcbData.r[7] + showptrhdrpad + printf " " + showptr 0 + printf " " + showptr $kgm_threadp.machine->PcbData.pc + printf "\n" + set kdp_pmap = $kgm_thread_pmap + while ($kgm_thread_sp != 0) + set $link_register = *($kgm_thread_sp + 4) + showptrhdrpad + printf " " + showptr $kgm_thread_sp + printf " " + showptr $link_register + printf "\n" + set $kgm_thread_sp = *$kgm_thread_sp + end + set kdp_pmap = $kgm_saved_pmap + else + set $kgm_threadp = (struct thread *)$arg0 + showactheader + showactint $kgm_threadp 0 + set $kgm_thread_sp = $kgm_threadp.machine->PcbData.r[7] + while ($kgm_thread_sp != 0) + _map_user_data_from_task $kgm_threadp->task $kgm_thread_sp 8 + set $kgm_thread_sp_window = (int *)$kgm_map_user_window + set $link_register = *($kgm_thread_sp_window + 1) + showptrhdrpad + printf " " + showptr $kgm_thread_sp + printf " " + showptr $link_register + printf "\n" + set $kgm_thread_sp = *$kgm_thread_sp_window + _unmap_user_data_from_task + end + end + else + echo showuserstack not supported on this architecture\n + end + end + end +end +document showuserstack +Syntax: showuserstack
+|This command displays a numeric backtrace for the user space stack of +|the given thread activation. It may, of course, fail to display a +|complete backtrace if portions of the user stack are not mapped in. +|Symbolic backtraces can be obtained either by running gdb on the +|user space binary, or a tool such as "symbolicate". +|Note that while this command works on Panther's gdb, an issue +|with Tiger gdb (3743135) appears to hamper the evaluation of this +|macro in some cases. +end + +define showtaskuserstacks + set $kgm_taskp = (struct task *)$arg0 + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + printf "For thread " + showptr $kgm_actp + printf "\n" + showuserstack $kgm_actp quiet + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + showx86backtrace + end + set kdp_pmap=0 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + printf "\n" + end + showuserlibraries $kgm_taskp +end +document showtaskuserstacks +Syntax: (gdb) showtaskuserstacks +| Print out the user stack for each thread in a task, followed by the user libraries. +end + + +define showuserregisters + set $kgm_threadp = (struct thread *)$arg0 + set $kgm_taskp = $kgm_threadp->task + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $newiss = (x86_saved_state_t *) ($kgm_threadp->machine.iss) + set $kgm_x86_abi = $newiss.flavor + if ($newiss.flavor == 0xf) + printf "X86 Thread State (64-bit):\n" + set $kgm_ss64 = $newiss.uss.ss_64 + + printf " rax: " + showuserptr $kgm_ss64.rax + printf " rbx: " + showuserptr $kgm_ss64.rbx + printf " rcx: " + showuserptr $kgm_ss64.rcx + printf " rdx: " + showuserptr $kgm_ss64.rdx + printf "\n" + + printf " rdi: " + showuserptr $kgm_ss64.rdi + printf " rsi: " + showuserptr $kgm_ss64.rsi + printf " rbp: " + showuserptr $kgm_ss64.rbp + printf " rsp: " + showuserptr $kgm_ss64.isf.rsp + printf "\n" + + printf " r8: " + showuserptr $kgm_ss64.r8 + printf " r9: " + showuserptr $kgm_ss64.r9 + printf " r10: " + showuserptr $kgm_ss64.r10 + printf " r11: " + showuserptr $kgm_ss64.r11 + printf "\n" + + printf " r12: " + showuserptr $kgm_ss64.r12 + printf " r13: " + showuserptr $kgm_ss64.r13 + printf " r14: " + showuserptr $kgm_ss64.r14 + printf " r15: " + showuserptr $kgm_ss64.r15 + printf "\n" + + printf " rip: " + showuserptr $kgm_ss64.isf.rip + printf " rfl: " + showuserptr $kgm_ss64.isf.rflags + printf " cr2: " + showuserptr $kgm_ss64.cr2 + printf "\n" + else + printf "X86 Thread State (32-bit):\n" + set $kgm_ss32 = $newiss.uss.ss_32 + + printf " eax: " + showuserptr $kgm_ss32.eax + printf " ebx: " + showuserptr $kgm_ss32.ebx + printf " ecx: " + showuserptr $kgm_ss32.ecx + printf " edx: " + showuserptr $kgm_ss32.edx + printf "\n" + + printf " edi: " + showuserptr $kgm_ss32.edi + printf " esi: " + showuserptr $kgm_ss32.esi + printf " ebp: " + showuserptr $kgm_ss32.ebp + printf " esp: " + showuserptr $kgm_ss32.uesp + printf "\n" + + printf " ss: " + showuserptr $kgm_ss32.ss + printf " efl: " + showuserptr $kgm_ss32.efl + printf " eip: " + showuserptr $kgm_ss32.eip + printf " cs: " + showuserptr $kgm_ss32.cs + printf "\n" + + printf " ds: " + showuserptr $kgm_ss32.ds + printf " es: " + showuserptr $kgm_ss32.es + printf " fs: " + showuserptr $kgm_ss32.fs + printf " gs: " + showuserptr $kgm_ss32.gs + printf "\n" + + printf " cr2: " + showuserptr $kgm_ss32.cr2 + printf "\n" + end + else + if ($kgm_mtype == $kgm_mtype_arm) + printf "ARM Thread State:\n" + set $kgm_pcb = (arm_saved_state_t *) (&$kgm_threadp->machine.PcbData) + + printf " r0: " + showuserptr $kgm_pcb.r[0] + printf " r1: " + showuserptr $kgm_pcb.r[1] + printf " r2: " + showuserptr $kgm_pcb.r[2] + printf " r3: " + showuserptr $kgm_pcb.r[3] + printf "\n" + + printf " r4: " + showuserptr $kgm_pcb.r[4] + printf " r5: " + showuserptr $kgm_pcb.r[5] + printf " r6: " + showuserptr $kgm_pcb.r[6] + printf " r7: " + showuserptr $kgm_pcb.r[7] + printf "\n" + + printf " r8: " + showuserptr $kgm_pcb.r[8] + printf " r9: " + showuserptr $kgm_pcb.r[9] + printf " r10: " + showuserptr $kgm_pcb.r[10] + printf " r11: " + showuserptr $kgm_pcb.r[11] + printf "\n" + + printf " ip: " + showuserptr $kgm_pcb.r[12] + printf " sp: " + showuserptr $kgm_pcb.sp + printf " lr: " + showuserptr $kgm_pcb.lr + printf " pc: " + showuserptr $kgm_pcb.pc + printf "\n" + + printf " cpsr: " + showuserptr $kgm_pcb.cpsr + printf "\n" + else + echo showuserregisters not supported on this architecture\n + end + end +end +document showuserregisters +Syntax: showuserstack
+|This command displays the last known user register state +|for the thread. This map not be correct for cases where +|the thread is currently executing in userspace. However +|for threads that have entered the kernel (either explicitly +|with a system call or implicitly with a fault), it should +|be accurate +end + +define showtaskuserregisters + set $kgm_taskp = (struct task *)$arg0 + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + printf "For thread " + showptr $kgm_actp + printf "\n" + showuserregisters $kgm_actp + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + printf "\n" + end +end +document showtaskuserregisters +Syntax: (gdb) showtaskuserregisters +| Print out the user registers for each thread in a task +end + +define kdp-reboot +# Alternatively, set *(*(unsigned **) 0x2498) = 1 +# (or 0x5498 on PPC, 0xffffff8000002928 on x86_64, 0xffff049c on arm) + manualhdrint $kgm_kdp_pkt_hostreboot + detach +end + +document kdp-reboot +Syntax: kdp-reboot +|Reboot the remote target machine; not guaranteed to succeed. +end + +define kdpversionint + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_version_req_t) + set $kgm_pkt = (kdp_version_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_VERSION + set $kgm_pkt->hdr.len = sizeof(kdp_version_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_version_reply_t *)&manual_pkt.data + set $kgm_kdp_version = $kgm_pkt->version + set $kgm_kdp_feature = $kgm_pkt->feature +end + +define kdp-version + kdpversionint + printf "KDP VERSION = %d, FEATURE = 0x%x\n", $kgm_kdp_version, $kgm_kdp_feature +end + +document kdp-version +Syntax: kdp-version +|Get the KDP protocol version being used by the kernel. +end + +define dumpinfoint + # set up the manual KDP packet + set manual_pkt.input = 0 + + set manual_pkt.len = sizeof(kdp_dumpinfo_req_t) + set $kgm_pkt = (kdp_dumpinfo_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_DUMPINFO + set $kgm_pkt->hdr.len = sizeof(kdp_dumpinfo_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->type = $arg0 + set $kgm_pkt->name = "" + set $kgm_pkt->destip = "" + set $kgm_pkt->routerip = "" + set $kgm_pkt->port = 0 + + if $argc > 1 + set $kgm_pkt->name = "$arg1" + end + if $argc > 2 + set $kgm_pkt->destip = "$arg2" + end + if $argc > 3 + set $kgm_pkt->routerip = "$arg3" + end + if $argc > 4 + set $kgm_pkt->port = $arg4 + end + + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header +end + +define sendcore + if $argc > 1 + dumpinfoint KDP_DUMPINFO_CORE $arg1 $arg0 + else + dumpinfoint KDP_DUMPINFO_CORE \0 $arg0 + end +end + +document sendcore +Syntax: sendcore [filename] +|Configure the kernel to transmit a kernel coredump to a server (kdumpd) +|at the specified IP address. This is useful when the remote target has +|not been previously configured to transmit coredumps, and you wish to +|preserve kernel state for later examination. NOTE: You must issue a "continue" +|command after using this macro to trigger the kernel coredump. The kernel +|will resume waiting in the debugger after completion of the coredump. You +|may disable coredumps by executing the "disablecore" macro. You can +|optionally specify the filename to be used for the generated core file. +end + +define sendsyslog + if $argc > 1 + dumpinfoint KDP_DUMPINFO_SYSTEMLOG $arg1 $arg0 + else + dumpinfoint KDP_DUMPINFO_SYSTEMLOG \0 $arg0 + end +end + +document sendsyslog +Syntax: sendsyslog [filename] +|Configure the kernel to transmit a kernel system log to a server (kdumpd) +|at the specified IP address. NOTE: You must issue a "continue" +|command after using this macro to trigger the kernel system log. The kernel +|will resume waiting in the debugger after completion. You can optionally +|specify the name to be used for the generated system log. +end + +define sendpaniclog + if panicstr + if $argc > 1 + dumpinfoint KDP_DUMPINFO_PANICLOG $arg1 $arg0 + else + dumpinfoint KDP_DUMPINFO_PANICLOG \0 $arg0 + end + else + printf "No panic log available.\n" + end +end + +document sendpaniclog +Syntax: sendpaniclog [filename] +|Configure the kernel to transmit a kernel paniclog to a server (kdumpd) +|at the specified IP address. NOTE: You must issue a "continue" +|command after using this macro to trigger the kernel panic log. The kernel +|will resume waiting in the debugger after completion. You can optionally +|specify the name to be used for the generated panic log. +end + +define getdumpinfo + dumpinfoint KDP_DUMPINFO_GETINFO + set $kgm_dumpinfo = (kdp_dumpinfo_reply_t *) manual_pkt.data + if $kgm_dumpinfo->type & KDP_DUMPINFO_REBOOT + printf "System will reboot after kernel info gets dumped.\n" + else + printf "System will not reboot after kernel info gets dumped.\n" + end + if $kgm_dumpinfo->type & KDP_DUMPINFO_NORESUME + printf "System will allow a re-attach after a KDP disconnect.\n" + else + printf "System will resume after a KDP disconnect.\n" + end + set $kgm_dumpinfo_type = $kgm_dumpinfo->type & KDP_DUMPINFO_MASK + if $kgm_dumpinfo_type == KDP_DUMPINFO_DISABLE + printf "Kernel not setup for remote dumps.\n" + else + printf "Remote dump type: " + if $kgm_dumpinfo_type == KDP_DUMPINFO_CORE + printf "Core file\n" + end + if $kgm_dumpinfo_type == KDP_DUMPINFO_PANICLOG + printf "Panic log\n" + end + if $kgm_dumpinfo_type == KDP_DUMPINFO_SYSTEMLOG + printf "System log\n" + end + + printf "Name: " + if $kgm_dumpinfo->name[0] == '\0' + printf "(autogenerated)\n" + else + printf "%s\n", $kgm_dumpinfo->name + end + + printf "Network Info: %s[%d] ", $kgm_dumpinfo->destip, $kgm_dumpinfo->port + if $kgm_dumpinfo->routerip[0] == '\0' + printf "\n" + else + printf "Router: %s\n", $kgm_dumpinfo->routerip + end + end +end + +document getdumpinfo +Syntax: getdumpinfo +|Retrieve the current remote dump settings. +end + +define setdumpinfo + dumpinfoint KDP_DUMPINFO_SETINFO $arg0 $arg1 $arg2 $arg3 +end + +document setdumpinfo +Syntax: setdumpinfo +|Configure the current remote dump settings. Specify \0 if you +|want to use the defaults (filename) or previously configured +|settings (ip/router). Specify 0 for the port if you wish to +|use the previously configured/default setting for that. +end + +define disablecore + dumpinfoint KDP_DUMPINFO_DISABLE +end + +document disablecore +Syntax: disablecore +|Reconfigures the kernel so that it no longer transmits kernel coredumps. This +|complements the "sendcore" macro, but it may be used if the kernel has been +|configured to transmit coredumps through boot-args as well. +end + +define switchtocorethread + set $newact = (struct thread *) $arg0 + select 0 + if ($newact->kernel_stack == 0) + echo This thread does not have a stack.\n + echo continuation: + output/a (unsigned) $newact.continuation + echo \n + else + if ($kgm_mtype == $kgm_mtype_ppc) + loadcontext $newact->machine->pcb + flushstack + set $pc = $newact->machine->pcb.save_srr0 + else + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $kgm_cstatep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + loadcontext $kgm_cstatep + flushstack + else + echo switchtocorethread not supported on this architecture\n + end + end + showcontext_int + end +end + +document switchtocorethread +Syntax: switchtocorethread
+| The corefile equivalent of "switchtoact". When debugging a kernel coredump +| file, this command can be used to examine the execution context and stack +| trace for a given thread activation. For example, to view the backtrace +| for a thread issue "switchtocorethread
", followed by "bt". +| Before resuming execution, issue a "resetcorectx" command, to +| return to the original execution context. Note that this command +| requires gdb support, as documented in Radar 3401283. +end + +define loadcontext + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_contextp = (struct savearea *) $arg0 + set $pc = $kgm_contextp.save_srr0 + set $r1 = $kgm_contextp.save_r1 + set $lr = $kgm_contextp.save_lr + + set $r2 = $kgm_contextp.save_r2 + set $r3 = $kgm_contextp.save_r3 + set $r4 = $kgm_contextp.save_r4 + set $r5 = $kgm_contextp.save_r5 + set $r6 = $kgm_contextp.save_r6 + set $r7 = $kgm_contextp.save_r7 + set $r8 = $kgm_contextp.save_r8 + set $r9 = $kgm_contextp.save_r9 + set $r10 = $kgm_contextp.save_r10 + set $r11 = $kgm_contextp.save_r11 + set $r12 = $kgm_contextp.save_r12 + set $r13 = $kgm_contextp.save_r13 + set $r14 = $kgm_contextp.save_r14 + set $r15 = $kgm_contextp.save_r15 + set $r16 = $kgm_contextp.save_r16 + set $r17 = $kgm_contextp.save_r17 + set $r18 = $kgm_contextp.save_r18 + set $r19 = $kgm_contextp.save_r19 + set $r20 = $kgm_contextp.save_r20 + set $r21 = $kgm_contextp.save_r21 + set $r22 = $kgm_contextp.save_r22 + set $r23 = $kgm_contextp.save_r23 + set $r24 = $kgm_contextp.save_r24 + set $r25 = $kgm_contextp.save_r25 + set $r26 = $kgm_contextp.save_r26 + set $r27 = $kgm_contextp.save_r27 + set $r28 = $kgm_contextp.save_r28 + set $r29 = $kgm_contextp.save_r29 + set $r30 = $kgm_contextp.save_r30 + set $r31 = $kgm_contextp.save_r31 + + set $cr = $kgm_contextp.save_cr + set $ctr = $kgm_contextp.save_ctr + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_contextp = (struct x86_kernel_state *) $arg0 + set $ebx = $kgm_contextp->k_ebx + set $ebp = $kgm_contextp->k_ebp + set $edi = $kgm_contextp->k_edi + set $esi = $kgm_contextp->k_esi + set $eip = $kgm_contextp->k_eip + set $pc = $kgm_contextp->k_eip + else + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_contextp = (struct x86_kernel_state *) $arg0 + set $rbx = $kgm_contextp->k_rbx + set $rbp = $kgm_contextp->k_rbp + set $r12 = $kgm_contextp->k_r12 + set $r13 = $kgm_contextp->k_r13 + set $r14 = $kgm_contextp->k_r14 + set $r15 = $kgm_contextp->k_r15 + set $rip = $kgm_contextp->k_rip + set $pc = $kgm_contextp->k_rip + else + echo loadcontext not supported on this architecture\n + end + end + end +end + +define resetcorectx + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_corecontext = (struct savearea *) kdp.saved_state + loadcontext $kgm_corecontext + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + set $ebx = $kdpstatep->ebx + set $ebp = $kdpstatep->ebp + set $edi = $kdpstatep->edi + set $esi = $kdpstatep->esi + set $eip = $kdpstatep->eip + set $eax = $kdpstatep->eax + set $ecx = $kdpstatep->ecx + set $edx = $kdpstatep->edx + flushregs + flushstack + set $pc = $kdpstatep->eip + update + else + echo resetcorectx not supported on this architecture\n + end + end + showcontext_int +end + +document resetcorectx +Syntax: resetcorectx +| The corefile equivalent of "resetctx". Returns to the original +| execution context (that of the active thread at the time of the NMI or +| panic). This command should be issued if you wish to resume +| execution after using the "switchtocorethread" command. +end + +#Helper function for "showallgdbstacks" + +define showgdbthread + printf " 0x%08x ", $arg0 + set $kgm_thread = *(struct thread *)$arg0 + printf "0x%08x ", $arg0 + printf "%3d ", $kgm_thread.sched_pri + set $kgm_state = $kgm_thread.state + if $kgm_state & 0x80 + printf "I" + end + if $kgm_state & 0x40 + printf "P" + end + if $kgm_state & 0x20 + printf "A" + end + if $kgm_state & 0x10 + printf "H" + end + if $kgm_state & 0x08 + printf "U" + end + if $kgm_state & 0x04 + printf "R" + end + if $kgm_state & 0x02 + printf "S" + end + if $kgm_state & 0x01 + printf "W\t" + printf "0x%08x ", $kgm_thread.wait_queue + output /a (unsigned) $kgm_thread.wait_event + if ($kgm_thread.uthread != 0) + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_wmesg != 0) + printf " \"%s\"", $kgm_uthread->uu_wmesg + end + end + end + if $arg1 != 0 + if ($kgm_thread.kernel_stack != 0) + if ($kgm_thread.reserved_stack != 0) + printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack + end + printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack + if ($kgm_mtype == $kgm_mtype_ppc) + set $mysp = $kgm_thread.machine.pcb->save_r1 + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_statep = (struct x86_kernel_state *) \ + ($kgm_thread->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + set $mysp = $kgm_statep->k_ebp + end + if ($kgm_mtype == $kgm_mtype_arm) + if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) + set $mysp = $r7 + else + set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr + set $mysp = $kgm_statep->r[7] + end + end + set $prevsp = 0 + printf "\n\t\tstacktop=0x%08x", $mysp + if ($arg2 == 0) + switchtoact $arg0 + else + switchtocorethread $arg0 + end + bt + else + printf "\n\t\t\tcontinuation=" + output /a (unsigned) $kgm_thread.continuation + end + printf "\n" + else + printf "\n" + end +end + +#Use of this macro is currently (8/04) blocked by the fact that gdb +#stops evaluating macros when encountering an error, such as a failure +#to read memory from a certain location. Until this issue (described in +#3758949) is addressed, evaluation of this macro may stop upon +#encountering such an error. + +define showallgdbstacks + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactheader + showgdbthread $kgm_actp 1 0 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + resetctx +end + +document showallgdbstacks +Syntax: showallgdbstacks +| An alternative to "showallstacks". Iterates through the task list and +| displays a gdb generated backtrace for each kernel thread. It is +| advantageous in that it is much faster than "showallstacks", and +| decodes function call arguments and displays source level traces, but +| it has the drawback that it doesn't determine if frames belong to +| functions from kernel extensions, as with "showallstacks". +| This command may terminate prematurely because of a gdb bug +| (Radar 3758949), which stops macro evaluation on memory read +| errors. +end + +define showallgdbcorestacks + select 0 + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactheader + showgdbthread $kgm_actp 1 1 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + resetcorectx +end + + +document showallgdbcorestacks +Syntax: showallgdbcorestacks +|Corefile version of "showallgdbstacks" +end + + +define switchtouserthread + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + if ($kdp_act_counter == 0) + set $kdpstate = (struct savearea *) kdp.saved_state + end + set $kdp_act_counter = $kdp_act_counter + 1 + set $newact = (struct thread *) $arg0 + _kgm_flush_loop + set $checkpc = $newact->machine->upcb.save_srr0 + if ($checkpc == 0) + echo This activation does not appear to have + echo \20 a valid user context.\n + else + set (struct savearea *) kdp.saved_state=$newact->machine->upcb + set $pc = $checkpc +#flush and update seem to be executed lazily by gdb on Tiger, hence the +#repeated invocations - see 3743135 + _kgm_flush_loop +# This works because the new pmap is used only for reads + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + end + else + echo switchtouserthread not implemented for this architecture.\n + end +end + +document switchtouserthread +Syntax: switchtouserthread
+| Analogous to switchtoact, but switches to the user context of a +| specified thread address. Similar to the "showuserstack" +| command, but this command does not return gdb to the kernel context +| immediately. This is to assist with the following (rather risky) +| manoeuvre - upon switching to the user context and virtual address +| space, the user may choose to call remove-symbol-file on the +| mach_kernel symbol file, and then add-symbol-file on the user space +| binary's symfile. gdb can then generate symbolic backtraces +| for the user space thread. To return to the +| kernel context and virtual address space, the process must be +| reversed, i.e. call remove-symbol-file on the user space symbols, and +| then add-symbol-file on the appropriate mach_kernel, and issue the +| "resetstacks" command. Note that gdb may not react kindly to all these +| symbol file switches. The same restrictions that apply to "showuserstack" +| apply here - pages that have been paged out cannot be read while in the +| debugger context, so backtraces may terminate early. +| If the virtual addresses in the stack trace do not conflict with those +| of symbols in the kernel's address space, it may be sufficient to +| just do an add-symbol-file on the user space binary's symbol file. +| Note that while this command works on Panther's gdb, an issue +| with Tiger gdb (3743135) appears to hamper the evaluation of this +| macro in some cases. +end + +define showmetaclass + set $kgm_metaclassp = (OSMetaClass *)$arg0 + printf "%-5d", $kgm_metaclassp->instanceCount + printf "x %5d bytes", $kgm_metaclassp->classSize + printf " %s\n", $kgm_metaclassp->className->string +end + +define showstring + printf "\"%s\"", ((OSString *)$arg0)->string +end + +define shownumber + printf "%lld", ((OSNumber *)$arg0)->value +end + +define showboolean + if ($arg0 == gOSBooleanFalse) + printf "No" + else + printf "Yes" + end +end + +define showdatabytes + set $kgm_data = (OSData *)$arg0 + + printf "<" + set $kgm_datap = (const unsigned char *) $kgm_data->data + set $kgm_idx = 0 + while ( $kgm_idx < $kgm_data->length ) + printf "%02X", *$kgm_datap + set $kgm_datap = $kgm_datap + 1 + set $kgm_idx = $kgm_idx + 1 + end + printf ">\n" +end + +define showdata + set $kgm_data = (OSData *)$arg0 + + printf "<" + set $kgm_datap = (const unsigned char *) $kgm_data->data + + set $kgm_printstr = 0 + if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3)) + set $kgm_bytes = *(unsigned int *) $kgm_datap + if (0xffff0000 & $kgm_bytes) + set $kgm_idx = 0 + set $kgm_printstr = 1 + while ($kgm_idx++ < 4) + set $kgm_bytes = $kgm_bytes >> 8 + set $kgm_char = 0xff & $kgm_bytes + if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e))) + set $kgm_printstr = 0 + end + end + end + end + + set $kgm_idx = 0 + if ($kgm_printstr) + set $kgm_quoted = 0 + while ($kgm_idx < $kgm_data->length) + set $kgm_char = $kgm_datap[$kgm_idx++] + if ($kgm_char) + if (0 == $kgm_quoted) + set $kgm_quoted = 1 + if ($kgm_idx > 1) + printf ",\"" + else + printf "\"" + end + end + printf "%c", $kgm_char + else + if ($kgm_quoted) + set $kgm_quoted = 0 + printf "\"" + end + end + end + if ($kgm_quoted) + printf "\"" + end + else + if (0 == (3 & (unsigned int)$kgm_datap)) + while (($kgm_idx + 3) <= $kgm_data->length) + printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx] + set $kgm_idx = $kgm_idx + 4 + end + end + while ($kgm_idx < $kgm_data->length) + printf "%02x", $kgm_datap[$kgm_idx++] + end + end + printf ">" +end + +define showdictionaryint + set $kgm$arg0_dict = (OSDictionary *)$arg1 + + printf "{" + set $kgm$arg0_idx = 0 + while ($kgm$arg0_idx < $kgm$arg0_dict->count) + set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key + showobjectint _$arg0 $kgm_obj + printf "=" + set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value + showobjectint _$arg0 $kgm_obj + if ($kgm$arg0_idx < $kgm$arg0_dict->count) + printf "," + end + end + printf "}" +end + +define indent + set $kgm_idx = 0 + while ($kgm_idx < $arg0) + if ($arg1 & (1 << $kgm_idx++)) + printf "| " + else + printf " " + end + end +end + +define showregdictionary + indent $kgm_reg_depth+2 $arg1 + printf "{\n" + + set $kgm_reg_idx = 0 + while ($kgm_reg_idx < $arg0->count) + indent $kgm_reg_depth+2 $arg1 + printf " " + set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key + showobjectint _ $kgm_obj + printf " = " + + set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value + showobjectint _ $kgm_obj + printf "\n" + end + indent $kgm_reg_depth+2 $arg1 + printf "}\n" +end + + +define showorderedsetarrayint + set $kgm$arg0_array = (_Element *)$arg1 + set $kgm$arg0_count = $arg2 + + set $kgm$arg0_idx = 0 + while ($kgm$arg0_idx < $kgm$arg0_count) + set $kgm_obj = $kgm$arg0_array[$kgm$arg0_idx++] + showobjectint _$arg0 $kgm_obj + if ($kgm$arg0_idx < $kgm$arg0_count) + printf "," + end + end +end + +define showorderedsetint + set $kgm_array = ((OSOrderedSet *)$arg1)->array + set $count = ((OSOrderedSet *)$arg1)->count + printf "[" + showorderedsetarrayint $arg0 $kgm_array $count + printf "]" +end + +define showarraysetint + set $kgm$arg0_array = (OSArray *)$arg1 + + set $kgm$arg0_idx = 0 + while ($kgm$arg0_idx < $kgm$arg0_array->count) + set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++] + showobjectint _$arg0 $kgm_obj + if ($kgm$arg0_idx < $kgm$arg0_array->count) + printf "," + end + end +end + +define showarrayint + printf "(" + showarraysetint $arg0 $arg1 + printf ")" +end + +define showsetint + set $kgm_array = ((OSSet *)$arg1)->members + printf "[" + showarraysetint $arg0 $kgm_array + printf "]" +end + + +define showobjectint + set $kgm_obj = (OSObject *) $arg1 + set $kgm_vt = *((void **) $arg1) + + if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) + set $kgm_vt = $kgm_vt - 2 * sizeof(void *) + end + + if ($kgm_show_object_addrs) + printf "`object " + showptr $arg1 + printf ", vt " + output /a (unsigned long) $kgm_vt + if ($kgm_show_object_retain) + printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16 + end + printf "` " + end + + # No multiple-inheritance + set $kgm_shown = 0 + if ($kgm_vt == &_ZTV8OSString) + showstring $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV8OSSymbol) + showstring $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV8OSNumber) + shownumber $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV6OSData) + if $kgm_show_data_alwaysbytes == 1 + showdatabytes $arg1 + else + showdata $arg1 + end + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV9OSBoolean) + showboolean $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV12OSDictionary) + showdictionaryint _$arg0 $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV7OSArray) + showarrayint _$arg0 $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV5OSSet) + showsetint _$arg0 $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV12OSOrderedSet) + showorderedsetint _$arg0 $arg1 + set $kgm_shown = 1 + end + + if ($kgm_shown != 1) + if ($kgm_show_object_addrs == 0) + printf "`object " + showptr $arg1 + printf ", vt " + output /a (unsigned long) $kgm_vt + printf "`" + end + end +end + +define showobject + set $kgm_save = $kgm_show_object_addrs + set $kgm_show_object_addrs = 1 + set $kgm_show_object_retain = 1 + showobjectint _ $arg0 + set $kgm_show_object_addrs = $kgm_save + set $kgm_show_object_retain = 0 + printf "\n" +end +document showobject +Syntax: (gdb) showobject +| Show info about an OSObject - its vtable ptr and retain count. +| If the object is a simple container class, more info will be shown. +end + +define dictget + set $kgm_dictp = (OSDictionary *)$arg0 + set $kgm_keyp = (const OSSymbol *)$arg1 + set $kgm_idx = 0 + set $kgm_result = 0 + while (($kgm_idx < $kgm_dictp->count) && ($kgm_result == 0)) + if ($kgm_keyp == $kgm_dictp->dictionary[$kgm_idx].key) + set $kgm_result = $kgm_dictp->dictionary[$kgm_idx].value + end + set $kgm_idx = $kgm_idx + 1 + end +end + + +define _registryentryrecurseinit + set $kgm_re = (IOService *)$arg1 + set $kgm$arg0_stack = (unsigned long long) $arg2 + + if ($arg3) + set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth) + end + + dictget $kgm_re->fRegistryTable $kgm_childkey + set $kgm$arg0_child_array = (OSArray *) $kgm_result + + if ($kgm$arg0_child_array) + set $kgm$arg0_child_count = $kgm$arg0_child_array->count + else + set $kgm$arg0_child_count = 0 + end + + if ($kgm$arg0_child_count) + set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth) + end +end + +define findregistryentryrecurse + set $kgm_registry_entry = 0 + _registryentryrecurseinit $arg0 $arg1 $arg2 $arg3 + + dictget $kgm_re->fRegistryTable $kgm_namekey + if ($kgm_result == 0) + dictget $kgm_re->fRegistryTable gIONameKey + end + if ($kgm_result == 0) + dictget $kgm_re->fPropertyTable gIOClassKey + end + + if ($kgm_result != 0) + set $str = ((OSString *) $kgm_result)->string + strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8 + if $kgm_findregistry_verbose + echo . + end + + if $kgm_strcmp_result == 0 + if $kgm_findregistry_verbose + printf "\n%s:\n | ", ((OSString *) $kgm_result)->string + showobject $kgm_re + printf " | " + print $kgm_re + end + + # don't populate $kgm_registry_entry if we want to show everything + if !$kgm_findregistry_continue + set $kgm_registry_entry = $kgm_re + end + end + end + + # recurse + if (!$kgm_registry_entry && ($kgm$arg0_child_count != 0)) + set $kgm_reg_depth = $kgm_reg_depth + 1 + set $kgm$arg0_child_idx = 0 + + while ($kgm$arg0_child_idx < $kgm$arg0_child_count) + set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] + set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + findregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib + if $kgm_registry_entry + loop_break + end + end + set $kgm_reg_depth = $kgm_reg_depth - 1 + end +end + +define findregdictvalue + set $kgm_registry_value = 0 + set $kgm_reg_idx = 0 + while ($kgm_reg_idx < $arg0->count) + set $kgm_obj = $arg0->dictionary + $kgm_reg_idx + set $str = ((OSString *)$kgm_obj->key)->string + strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8 + + if $kgm_strcmp_result == 0 + set $kgm_registry_value = $kgm_obj->value + if $kgm_findregistry_verbose + showobject $kgm_registry_value + print $kgm_registry_value + end + loop_break + end + set $kgm_reg_idx = $kgm_reg_idx + 1 + end +end + +define setfindregistrystr + set $kgm_reg_find_str0 = 0 + set $kgm_reg_find_str1 = 0 + set $kgm_reg_find_str2 = 0 + set $kgm_reg_find_str3 = 0 + set $kgm_reg_find_str4 = 0 + set $kgm_reg_find_str5 = 0 + set $kgm_reg_find_str6 = 0 + set $kgm_reg_find_str7 = 0 + set $kgm_reg_find_str8 = 0 + + if $argc > 0 + set $kgm_reg_find_str0 = $arg0 + end + if $argc > 1 + set $kgm_reg_find_str1 = $arg1 + end + if $argc > 2 + set $kgm_reg_find_str2 = $arg2 + end + if $argc > 3 + set $kgm_reg_find_str3 = $arg3 + end + if $argc > 4 + set $kgm_reg_find_str4 = $arg4 + end + if $argc > 5 + set $kgm_reg_find_str5 = $arg5 + end + if $argc > 6 + set $kgm_reg_find_str6 = $arg6 + end + if $argc > 7 + set $kgm_reg_find_str7 = $arg7 + end + if $argc > 8 + set $kgm_reg_find_str8 = $arg8 + end +end + +document setfindregistrystr +Syntax: (gdb) setfindregistrystr [a] [b] [c] [d] [e] [f] [g] [h] [i] +| Store an encoded string into up to 9 arguments for use by +| findregistryprop or findregistryentry. The arguments are created +| through calls to strcmp_arg_pack64 +end + +define _findregistryprop + set $reg = (IOService *) $arg0 + set $kgm_props = $reg->fPropertyTable + set $kgm_findregistry_verbose = 0 + + findregdictvalue $kgm_props +end + +define findregistryprop + set $reg = (IOService *) $arg0 + set $kgm_props = $reg->fPropertyTable + + set $kgm_findregistry_verbose = 1 + findregdictvalue $kgm_props +end + +document findregistryprop +Syntax: (gdb) findregistryprop +| Given a registry entry, print out the contents for the property that matches +| the encoded string specified via setfindregistrystr. +| +| For example, the following will print out the "intel-pic" property stored in +| the AppleACPIPlatformExpert registry entry $pe_entry: +| strcmp_arg_pack64 'i' 'n' 't' 'e' 'l' '-' 'p' 'i' +| set $intel_pi = $kgm_strcmp_arg +| strcmp_arg_pack64 'c' 0 0 0 0 0 0 0 +| set $c = $kgm_strcmp_arg +| setfindregistrystr $intel_pi $c +| findregistryprop $pe_entry +end + +define findregistryentryint + if !$kgm_reg_plane + set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane + end + + if !$kgm_reg_plane + printf "Please load kgmacros after KDP attaching to the target.\n" + else + set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + if $kgm_findregistry_verbose + printf "Searching" + end + findregistryentryrecurse _ $arg0 0 0 + end +end + +define _findregistryentry + set $kgm_findregistry_verbose = 0 + set $kgm_findregistry_continue = 0 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +define findregistryentry + set $kgm_findregistry_verbose = 1 + set $kgm_findregistry_continue = 0 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +define findregistryentries + set $kgm_findregistry_verbose = 1 + set $kgm_findregistry_continue = 1 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +document findregistryentry +Syntax: (gdb) findregistryentry +| Search for a registry entry that matches the encoded string specified through +| setfindregistrystr. You can alter the search depth through use of +| $kgm_reg_depth_max. +| +| For example, the following will pull out the AppleACPIPlatformExpert registry +| entry: +| strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P' +| set $AppleACP = $kgm_strcmp_arg +| strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r' +| set $IPlatfor = $kgm_strcmp_arg +| strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0 +| set $mExpert = $kgm_strcmp_arg +| setfindregistrystr $AppleACP $IPlatfor $mExpert +| findregistryentry +end + +document findregistryentries +Syntax: (gdb) findregistryentries +| Search for all registry entries that match the encoded string specified through +| setfindregistrystr. You can alter the search depth through use of +| $kgm_reg_depth_max. See findregistryentry for an example of how to encode a string. +end + + +define showregistryentryrecurse + _registryentryrecurseinit $arg0 $arg1 $arg2 $arg3 + + indent $kgm_reg_depth $kgm$arg0_stack + printf "+-o " + + dictget $kgm_re->fRegistryTable $kgm_namekey + if ($kgm_result == 0) + dictget $kgm_re->fRegistryTable gIONameKey + end + if ($kgm_result == 0) + dictget $kgm_re->fPropertyTable gIOClassKey + end + + if ($kgm_result != 0) + printf "%s", ((OSString *)$kgm_result)->string + else + if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name) + printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name + else +# printf ", guessclass " +# guessclass $kgm_re + printf "??" + end + end + + + printf " IORegistryEntry::reserved->fRegistryEntryID + printf "vtable " + set $kgm_vt = (unsigned long) *(void**) $kgm_re + if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) + set $kgm_vt = $kgm_vt - 2 * sizeof(void *) + end + output /a $kgm_vt + + if ($kgm_vt != &_ZTV15IORegistryEntry) + printf ", " + set $kgm_state = $kgm_re->__state[0] + # kIOServiceRegisteredState + if (0 == ($kgm_state & 2)) + printf "!" + end + printf "registered, " + # kIOServiceMatchedState + if (0 == ($kgm_state & 4)) + printf "!" + end + printf "matched, " + # kIOServiceInactiveState + if ($kgm_state & 1) + printf "in" + end + printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount) + end + printf ">\n" + + if ($kgm_show_props) + set $kgm_props = $kgm_re->fPropertyTable + showregdictionary $kgm_props $kgm$arg0_stack + end + + # recurse + if ($kgm$arg0_child_count != 0) + + set $kgm_reg_depth = $kgm_reg_depth + 1 + set $kgm$arg0_child_idx = 0 + + while ($kgm$arg0_child_idx < $kgm$arg0_child_count) + set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] + set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib + end + + set $kgm_reg_depth = $kgm_reg_depth - 1 + end +end + +define showregistryentryint + if !$kgm_reg_plane + set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane + end + + if !$kgm_reg_plane + printf "Please load kgmacros after KDP attaching to the target.\n" + else + set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + showregistryentryrecurse _ $arg0 0 0 + end +end + +define showregistry + set $kgm_reg_depth = 0 + set $kgm_show_props = 0 + showregistryentryint gRegistryRoot +end +document showregistry +Syntax: (gdb) showregistry +| Show info about all registry entries in the current plane. You can specify the maximum +| display depth with $kgm_reg_depth_max. +end + +define showregistryprops + set $kgm_reg_depth = 0 + set $kgm_show_props = 1 + showregistryentryint gRegistryRoot +end +document showregistryprops +Syntax: (gdb) showregistryprops +| Show info about all registry entries in the current plane, and their properties. +| set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display +| more verbose information +end + +define showregistryentry + set $kgm_reg_depth = 0 + set $kgm_show_props = 1 + showregistryentryint $arg0 +end +document showregistryentry +Syntax: (gdb) showregistryentry +| Show info about a registry entry; its properties and descendants in the current plane. +end + +define setregistryplane + if ($arg0 != 0) + set $kgm_reg_plane = (IORegistryPlane *) $arg0 + else + showobjectint _ gIORegistryPlanes + printf "\n" + end +end +document setregistryplane +Syntax: (gdb) setregistryplane +| Set the plane to be used for the iokit registry macros. An argument of zero will +| display known planes. +end + +define guessclass + set $kgm_classidx = 0 + set $kgm_lookvt = *((void **) $arg0) + set $kgm_bestvt = (void *) 0 + set $kgm_bestidx = 0 + + while $kgm_classidx < sAllClassesDict->count + set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value + + set $kgm_vt = *((void **) $kgm_meta) + + if (($kgm_vt > $kgm_bestvt) && ($kgm_vt < $kgm_lookvt)) + set $kgm_bestvt = $kgm_vt + set $kgm_bestidx = $kgm_classidx + end + set $kgm_classidx = $kgm_classidx + 1 + end + printf "%s", sAllClassesDict->dictionary[$kgm_bestidx].key->string +end + +define showallclasses + set $kgm_classidx = 0 + while $kgm_classidx < sAllClassesDict->count + set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx++].value + showmetaclass $kgm_meta + end +end + +document showallclasses +Syntax: (gdb) showallclasses +| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details. +end + +define showioalloc + printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024 + printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024 + printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024 + printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024 +end + +document showioalloc +Syntax: (gdb) showioalloc +| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details. +end + +define showosobjecttracking + set $kgm_next = (OSObjectTracking *) gOSObjectTrackList.next + while $kgm_next != &gOSObjectTrackList + set $obj = (OSObject *) ($kgm_next+1) + showobject $obj + set $kgm_idx = 0 + while $kgm_idx < (sizeof($kgm_next->bt) / sizeof($kgm_next->bt[0])) + if ((unsigned long) $kgm_next->bt[$kgm_idx] > (unsigned long) &last_kernel_symbol) + showkmodaddr $kgm_next->bt[$kgm_idx] + printf "\n" + else + if ((unsigned long) $kgm_next->bt[$kgm_idx] > 0) + output /a $kgm_next->bt[$kgm_idx] + printf "\n" + end + end + set $kgm_idx = $kgm_idx + 1 + end + printf "\n" + set $kgm_next = (OSObjectTracking *) $kgm_next->link.next + end +end + +document showosobjecttracking +Syntax: (gdb) showosobjecttracking +| Show the list of tracked OSObject allocations with backtraces. +| Boot with the kOSTraceObjectAlloc (0x00400000) io debug flag set. +| Set gOSObjectTrackThread to 1 or a thread_t to capture new OSObjects allocated by a thread or all threads. +end + +# $kgm_readphys_force_kdp and $kgm_readphys_force_physmap +# can respectively cause physical memory access to use +# a KDP manual packet or the physical memory mapping +# even if the default behavior would be otherwise. +define readphysint + set $kgm_readphysint_result = 0xBAD10AD + + if ($kgm_readphys_force_kdp != 0) + set $kgm_readphys_use_kdp = 1 + else + if ($kgm_readphys_force_physmap) + set $kgm_readphys_use_kdp = 0 + else + set $kgm_readphys_use_kdp = ( kdp->is_conn > 0 ) + end + end + + if ($kgm_readphys_use_kdp) + + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readphysmem64_req_t) + set $kgm_pkt = (kdp_readphysmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READPHYSMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readphysmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = $arg2 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readphysmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + if $arg1 == 8 + set $kgm_readphysint_result = *((uint8_t *)$kgm_pkt->data) + end + if $arg1 == 16 + set $kgm_readphysint_result = *((uint16_t *)$kgm_pkt->data) + end + if $arg1 == 32 + set $kgm_readphysint_result = *((uint32_t *)$kgm_pkt->data) + end + if $arg1 == 64 + set $kgm_readphysint_result = *((uint64_t *)$kgm_pkt->data) + end + end + + else + # No KDP. Attempt to use physical memory mapping + + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_readphys_paddr_in_kva = (unsigned long long)$arg0 + physmap_base + else + if ($kgm_mtype == $kgm_mtype_arm) + set $kgm_readphys_paddr_in_kva = (unsigned long long)$arg0 - gPhysBase + gVirtBase + else + printf "readphys not available for current architecture.\n" + set $kgm_readphys_paddr_in_kva = 0 + end + end + if $kgm_readphys_paddr_in_kva + if $arg1 == 8 + set $kgm_readphysint_result = *((uint8_t *)$kgm_readphys_paddr_in_kva) + end + if $arg1 == 16 + set $kgm_readphysint_result = *((uint16_t *)$kgm_readphys_paddr_in_kva) + end + if $arg1 == 32 + set $kgm_readphysint_result = *((uint32_t *)$kgm_readphys_paddr_in_kva) + end + if $arg1 == 64 + set $kgm_readphysint_result = *((uint64_t *)$kgm_readphys_paddr_in_kva) + end + end + end +end + +define readphys8 + readphysint $arg0 8 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%02hhx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys16 + readphysint $arg0 16 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%04hx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys32 + readphysint $arg0 32 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%08x\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys64 + readphysint $arg0 64 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%016llx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys + readphys32 $arg0 +end + +document readphys8 +| See readphys64 +end + +document readphys16 +| See readphys64 +end + +document readphys32 +| See readphys64 +end + +document readphys64 +| The argument is interpreted as a physical address, and the 64-bit word +| addressed is displayed. Saves 64-bit result in $kgm_readphys_result. +end + +define writephysint + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writephysmem64_req_t) + set $kgm_pkt = (kdp_writephysmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEPHYSMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_writephysmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = $arg3 + if $arg1 == 8 + set *(uint8_t *)$kgm_pkt->data = (uint8_t)$arg2 + end + if $arg1 == 16 + set *(uint16_t *)$kgm_pkt->data = (uint16_t)$arg2 + end + if $arg1 == 32 + set *(uint32_t *)$kgm_pkt->data = (uint32_t)$arg2 + end + if $arg1 == 64 + set *(uint64_t *)$kgm_pkt->data = (uint64_t)$arg2 + end + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writephysmem64_reply_t *)&manual_pkt.data + set $kgm_writephysint_result = $kgm_pkt->error +end + +define writephys8 + writephysint $arg0 8 $arg1 $kgm_lcpu_self +end + +define writephys16 + writephysint $arg0 16 $arg1 $kgm_lcpu_self +end + +define writephys32 + writephysint $arg0 32 $arg1 $kgm_lcpu_self +end + +define writephys64 + writephysint $arg0 64 $arg1 $kgm_lcpu_self +end + +document writephys8 +| See writephys64 +end + +document writephys16 +| See writephys64 +end + +document writephys32 +| See writephys64 +end + +document writephys64 +| The argument is interpreted as a physical address, and the second argument is +| written to that address as a 64-bit word. +end + +define addkextsyms + if ($argc <= 1) + if ($argc == 0) + printf "Adding kext symbols from in-kernel summary data.\n" + add-all-kexts + else + printf "Adding kext symbols from $arg0.\n" + shell echo cd `pwd` > /tmp/gdb-cd + cd $arg0 + source kcbmacros + source /tmp/gdb-cd + end + set $kgm_show_kmod_syms = 1 +#ifndef _OPEN_SOURCE_ + echo \n\nIf you're having trouble with kext symbols, see:\n\thttp://eightball.apple.com/luna/index.php/DWARF_Kernel_Extensions\n\n +#endif + else + printf "| Usage:\n|\n" + help addkextsyms + end +end + +document addkextsyms +| If specified without an argument, uses gdb's add-all-kexts command to load +| kext symbols. Otherwise, takes a directory of kext symbols generated with +| kextcache -y or kcgen and loads them into gdb. +| (gdb) addkextsyms +| - or - +| (gdb) addkextsyms /path/to/symboldir +end + +define showprocfiles + if ($argc == 1) + _showprocheader + _showprocfiles $arg0 + else + printf "| Usage:\n|\n" + help showprocfiles + end +end +document showprocfiles +Syntax: (gdb) showprocfiles +| Given a proc_t pointer, display the list of open file descriptors for the +| referenced process. +end + +define _showprocheader + printf "fd fileglob " + showptrhdrpad + printf " fg flags fg type fg data " + showptrhdrpad + printf " info\n" + printf "----- ----------" + if $kgm_lp64 + printf "--------" + end + printf " ---------- -------- ----------" + if $kgm_lp64 + printf "--------" + end + printf " -------------------\n" +end + +define _showprocfiles + set $kgm_spf_filedesc = ((proc_t)$arg0)->p_fd + set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile + set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles + set $kgm_spf_count = 0 + while ($kgm_spf_count <= $kgm_spf_last) + if ($kgm_spf_ofiles[$kgm_spf_count] == 0) + # DEBUG: For files that were open, but are now closed + # printf "%-5d FILEPROC_NULL\n", $kgm_spf_count + else + # display fd #, fileglob address, fileglob flags + set $kgm_spf_flags = $kgm_spf_ofiles[$kgm_spf_count].f_flags + set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob + printf "%-5d ", $kgm_spf_count + showptr $kgm_spf_fg + printf " 0x%08x ", $kgm_spf_flags + # decode fileglob type + set $kgm_spf_fgt = $kgm_spf_fg->fg_type + if ($kgm_spf_fgt == 1) + printf "VNODE " + end + if ($kgm_spf_fgt == 2) + printf "SOCKET " + end + if ($kgm_spf_fgt == 3) + printf "PSXSHM " + end + if ($kgm_spf_fgt == 4) + printf "PSXSEM " + end + if ($kgm_spf_fgt == 5) + printf "KQUEUE " + end + if ($kgm_spf_fgt == 6) + printf "PIPE " + end + if ($kgm_spf_fgt == 7) + printf "FSEVENTS" + end + if ($kgm_spf_fgt < 1 || $kgm_spf_fgt > 7) + printf "?: %-5d", $kgm_spf_fgt + end + + # display fileglob data address and decode interesting fact(s) + # about data, if we know any + set $kgm_spf_fgd = $kgm_spf_fg->fg_data + printf " " + showptr $kgm_spf_fgd + printf " " + if ($kgm_spf_fgt == 1) + set $kgm_spf_name = ((struct vnode *)$kgm_spf_fgd)->v_name + if ($kgm_spf_name == 0) + printf "(null)" + else + printf "%s", $kgm_spf_name + end + end + printf "\n" + end + set $kgm_spf_count = $kgm_spf_count + 1 + end +end + +# +# Show all the advisory file locks held by a process for each of the vnode +# type files that it has open; do this by walking the per process open file +# table and looking at any vnode type fileglob that has a non-NULL lock list +# associated with it. +# +define showproclocks + if ($argc == 1) + _showproclocks $arg0 + else + printf "| Usage:\n|\n" + help showproclocks + end +end +document showproclocks +Syntax: (gdb) showproclocks +| Given a proc_t pointer, display the list of advisory file locks held by the +| referenced process. +end + +define _showproclocks + set $kgm_spl_filedesc = ((proc_t)$arg0)->p_fd + set $kgm_spl_last = $kgm_spl_filedesc->fd_lastfile + set $kgm_spl_ofiles = $kgm_spl_filedesc->fd_ofiles + set $kgm_spl_count = 0 + set $kgm_spl_seen = 0 + while ($kgm_spl_count <= $kgm_spl_last) + if ($kgm_spl_ofiles[$kgm_spl_count] == 0) + # DEBUG: For files that were open, but are now closed + # printf "%-5d FILEPROC_NULL\n", $kgm_spl_count + else + set $kgm_spl_fg = $kgm_spl_ofiles[$kgm_spl_count].f_fglob + # decode fileglob type + set $kgm_spl_fgt = $kgm_spl_fg->fg_type + if ($kgm_spl_fgt == 1) + set $kgm_spl_fgd = $kgm_spl_fg->fg_data + set $kgm_spl_name = ((struct vnode *)$kgm_spl_fgd)->v_name + set $kgm_spl_vnode = ((vnode_t)$kgm_spl_fgd) + set $kgm_spl_lockiter = $kgm_spl_vnode->v_lockf + if ($kgm_spl_lockiter != 0) + if ($kgm_spl_seen == 0) + _showvnodelockheader + end + set $kgm_spl_seen = $kgm_spl_seen + 1 + printf "( fd %d, name ", $kgm_spl_count + if ($kgm_spl_name == 0) + printf "(null) )" + else + printf "%s )\n", $kgm_spl_name + end + _showvnodelocks $kgm_spl_fgd + end + end + end + set $kgm_spl_count = $kgm_spf_count + 1 + end + printf "%d total locks for ", $kgm_spl_seen + showptr $arg0 + printf "\n" +end + +define showprocinfo + set $kgm_spi_proc = (proc_t)$arg0 + printf "Process " + showptr $kgm_spi_proc + printf "\n" + printf " name %s\n", $kgm_spi_proc->p_comm + printf " pid:%.8d", $kgm_spi_proc->p_pid + printf " task:" + showptr $kgm_spi_proc->task + printf " p_stat:%.1d", $kgm_spi_proc->p_stat + printf " parent pid:%.8d", $kgm_spi_proc->p_ppid + printf "\n" + # decode part of credential + set $kgm_spi_cred = $kgm_spi_proc->p_ucred + if ($kgm_spi_cred != 0) + printf "Cred: euid %d ruid %d svuid %d\n", $kgm_spi_cred->cr_posix.cr_uid, $kgm_spi_cred->cr_posix.cr_ruid, $kgm_spi_cred->cr_posix.cr_svuid + else + printf "Cred: (null)\n" + end + # decode flags + set $kgm_spi_flag = $kgm_spi_proc->p_flag + printf "Flags: 0x%08x\n", $kgm_spi_flag + if ($kgm_spi_flag & 0x00000001) + printf " 0x00000001 - may hold advisory locks\n" + end + if ($kgm_spi_flag & 0x00000002) + printf " 0x00000002 - has a controlling tty\n" + end + if ($kgm_spi_flag & 0x00000004) + printf " 0x00000004 - process is 64 bit\n" + else + printf " !0x00000004 - process is 32 bit\n" + end + if ($kgm_spi_flag & 0x00000008) + printf " 0x00000008 - no SIGCHLD on child stop\n" + end + if ($kgm_spi_flag & 0x00000010) + printf " 0x00000010 - waiting for child exec/exit\n" + end + if ($kgm_spi_flag & 0x00000020) + printf " 0x00000020 - has started profiling\n" + end + if ($kgm_spi_flag & 0x00000040) + printf " 0x00000040 - in select; wakeup/waiting danger\n" + end + if ($kgm_spi_flag & 0x00000080) + printf " 0x00000080 - was stopped and continued\n" + end + if ($kgm_spi_flag & 0x00000100) + printf " 0x00000100 - has set privileges since exec\n" + end + if ($kgm_spi_flag & 0x00000200) + printf " 0x00000200 - system process: no signals, stats, or swap\n" + end + if ($kgm_spi_flag & 0x00000400) + printf " 0x00000400 - timing out during a sleep\n" + end + if ($kgm_spi_flag & 0x00000800) + printf " 0x00000800 - debugged process being traced\n" + end + if ($kgm_spi_flag & 0x00001000) + printf " 0x00001000 - debugging process has waited for child\n" + end + if ($kgm_spi_flag & 0x00002000) + printf " 0x00002000 - exit in progress\n" + end + if ($kgm_spi_flag & 0x00004000) + printf " 0x00004000 - process has called exec\n" + end + if ($kgm_spi_flag & 0x00008000) + printf " 0x00008000 - owe process an addupc() XXX\n" + end + if ($kgm_spi_flag & 0x00010000) + printf " 0x00010000 - affinity for Rosetta children\n" + end + if ($kgm_spi_flag & 0x00020000) + printf " 0x00020000 - wants to run Rosetta\n" + end + if ($kgm_spi_flag & 0x00040000) + printf " 0x00040000 - has wait() in progress\n" + end + if ($kgm_spi_flag & 0x00080000) + printf " 0x00080000 - kdebug tracing on for this process\n" + end + if ($kgm_spi_flag & 0x00100000) + printf " 0x00100000 - blocked due to SIGTTOU or SIGTTIN\n" + end + if ($kgm_spi_flag & 0x00200000) + printf " 0x00200000 - has called reboot()\n" + end + if ($kgm_spi_flag & 0x00400000) + printf " 0x00400000 - is TBE state\n" + end + if ($kgm_spi_flag & 0x00800000) + printf " 0x00800000 - signal exceptions\n" + end + if ($kgm_spi_flag & 0x01000000) + printf " 0x01000000 - has thread cwd\n" + end + if ($kgm_spi_flag & 0x02000000) + printf " 0x02000000 - has vfork() children\n" + end + if ($kgm_spi_flag & 0x04000000) + printf " 0x04000000 - not allowed to attach\n" + end + if ($kgm_spi_flag & 0x08000000) + printf " 0x08000000 - vfork() in progress\n" + end + if ($kgm_spi_flag & 0x10000000) + printf " 0x10000000 - no shared libraries\n" + end + if ($kgm_spi_flag & 0x20000000) + printf " 0x20000000 - force quota for root\n" + end + if ($kgm_spi_flag & 0x40000000) + printf " 0x40000000 - no zombies when children exit\n" + end + if ($kgm_spi_flag & 0x80000000) + printf " 0x80000000 - don't hang on remote FS ops\n" + end + # decode state + set $kgm_spi_state = $kgm_spi_proc->p_stat + printf "State: " + if ($kgm_spi_state == 1) + printf "Idle\n" + end + if ($kgm_spi_state == 2) + printf "Run\n" + end + if ($kgm_spi_state == 3) + printf "Sleep\n" + end + if ($kgm_spi_state == 4) + printf "Stop\n" + end + if ($kgm_spi_state == 5) + printf "Zombie\n" + end + if ($kgm_spi_state == 6) + printf "Reaping\n" + end + if ($kgm_spi_state < 1 || $kgm_spi_state > 6) + printf "(Unknown)\n" + end +end + +document showprocinfo +Syntax: (gdb) showprocinfo +| Displays name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields. +end + +# +# dump the zombprocs +# +define zombproc + set $basep = (struct proc *)zombproc->lh_first + set $pp = $basep + while $pp + showprocinfo $pp + set $pp = $pp->p_list.le_next + end +end + +document zombproc +Syntax: (gdb) zombproc +| Routine to print out all procs in the zombie list +end + +# +# dump the zombstacks +# +define zombstacks + set $basep = (struct proc *)zombproc->lh_first + set $pp = $basep + while $pp + if $pp->p_stat != 5 + showtaskstacks $pp->task + end + set $pp = $pp->p_list.le_next + end +end + +document zombstacks +Syntax: (gdb) zombstacks +| Routine to print out all stacks of tasks that are exiting +end + + +# +# dump the allprocs +# +define allproc + set $basep = (struct proc *)allproc->lh_first + set $pp = $basep + while $pp + showprocinfo $pp + set $pp = $pp->p_list.le_next + end +end + +document allproc +Syntax: (gdb) allproc +| Routine to print out all process in the system +| which are not in the zombie list +end +define showprocsiblingint + set $kgm_sibling_ptr = (struct proc *)$arg0 + set $kgm_lx = $arg1 + while $kgm_lx + printf "| " + set $kgm_lx = $kgm_lx-3 + end + printf "|--%d %s [ 0x%llx ]\n", $kgm_sibling_ptr->p_pid, $kgm_sibling_ptr->p_comm, $kgm_sibling_ptr +end +define showproctreeint +#Initialize all the set variables used in this macro + set $kgm_basep1 = 0 + set $kgm_sibling_ptr = 0 + set $kgm_lx = 0 + set $kgm_tmp_base = 0 + set $kgm_head_ptr = 0 + set $kgm_search_pid = 0 + set $kgm_rev = 0 + set $kgm_x = 0 + + set $kgm_basep1 = (struct proc *)allproc->lh_first + if ($arg0 == 0) + set $kgm_head_ptr = (struct proc *)initproc + end + if ($arg0 > 0) + set $kgm_tmp_base = (struct proc *)allproc->lh_first + set $kgm_search_pid = $arg0 + while $kgm_tmp_base + if ( $kgm_tmp_base->p_pid == $kgm_search_pid) + if ($kgm_tmp_base->p_childrencnt > 0) + set $kgm_head_ptr = $kgm_tmp_base->p_children.lh_first + else + set $kgm_head_ptr = 0 + printf "No children present for PID=%d", $kgm_search_pid + end + loop_break + end + set $kgm_tmp_base = $kgm_tmp_base->p_list.le_next + end + end + set $kgm_rev = 0 + set $kgm_x = 0 + if ($kgm_head_ptr) + printf "PID PROCESS POINTER]\n" + printf "=== ======= =======\n" + printf "%d %s [ 0x%llx ]\n", $kgm_head_ptr->p_ppid, $kgm_head_ptr->p_pptr->p_comm, $kgm_head_ptr + printf "|--%d %s [ 0x%llx ]\n", $kgm_head_ptr->p_pid, $kgm_head_ptr->p_comm, $kgm_head_ptr + end + while ($kgm_head_ptr) + #Is childrencnt = 0? YES {=> no children} + if ($kgm_head_ptr->p_childrencnt == 0) + # Does it have sibling? + if($kgm_head_ptr->p_sibling.le_next == 0) + #No, it does not have sibling, so go back to its parent which will go to its sibling + if($kgm_head_ptr == $kgm_head_ptr->p_pptr) + loop_break + end + set $kgm_head_ptr = $kgm_head_ptr->p_pptr + if ($kgm_head_ptr == $kgm_tmp_base) + loop_break + end + if ($kgm_x > 3) + set $kgm_x = $kgm_x - 3 + end + set $kgm_rev = 1 + end + if($kgm_head_ptr->p_sibling.le_next != 0) + # Yes, it has sibling. So print sibling + set $kgm_rev = 0 + showprocsiblingint $kgm_head_ptr->p_sibling.le_next $kgm_x + set $kgm_head_ptr = $kgm_head_ptr->p_sibling.le_next + end + # childrencnt != 0 {=> it has children} + else + if ($kgm_rev == 1) + if($kgm_head_ptr->p_sibling.le_next == 0) + #No, it does not have sibling, so go back to its parent which will go to its sibling + if($kgm_head_ptr == $kgm_head_ptr->p_pptr) + loop_break + end + set $kgm_head_ptr = $kgm_head_ptr->p_pptr + if ($kgm_head_ptr == $kgm_tmp_base) + loop_break + end + + if ($kgm_x > 3) + set $kgm_x = $kgm_x - 3 + end + set $kgm_rev = 1 + end + if($kgm_head_ptr->p_sibling.le_next != 0) + set $kgm_rev = 0 + # Yes, it has sibling. So print sibling + showprocsiblingint $kgm_head_ptr->p_sibling.le_next $kgm_x + set $kgm_head_ptr = $kgm_head_ptr->p_sibling.le_next + end + else + set $kgm_head_ptr = $kgm_head_ptr->p_children.lh_first + set $kgm_x = $kgm_x + 3 + set $kgm_lx = $kgm_x + while $kgm_lx + printf "| " + set $kgm_lx = $kgm_lx-3 + end + printf "|--%d %s [ 0x%llx ] \n", $kgm_head_ptr->p_pid, $kgm_head_ptr->p_comm, $kgm_head_ptr + end + end + end + printf "\n" +#Unset all the set variables used in this macro + set $kgm_basep1 = 0 + set $kgm_sibling_ptr = 0 + set $kgm_lx = 0 + set $kgm_tmp_base = 0 + set $kgm_head_ptr = 0 + set $kgm_search_pid = 0 + set $kgm_rev = 0 + set $kgm_x = 0 +end +define showproctree + if ($argc > 0) + showproctreeint $arg0 + else + showproctreeint 0 + end +end +document showproctree +Syntax: (gdb) showproctree +| Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes. +| If no argument is given, showproctree will print all the processes in the system. +| If pid is specified, showproctree prints all the descendants of the indicated process +end + + +define print_vnode + set $vp = (struct vnode *)$arg0 + printf " " + printf " vp " + showptr $vp + printf " use %d", $vp->v_usecount + printf " io %d", $vp->v_iocount + printf " kuse %d", $vp->v_kusecount + printf " type %d", $vp->v_type + printf " flg 0x%.8x", $vp->v_flag + printf " lflg 0x%.8x", $vp->v_lflag + printf " par " + showptr $vp->v_parent + set $_name = (char *)$vp->v_name + if ($_name != 0) + printf " %s", $_name + end + if ($vp->v_type == VREG) && ($vp->v_un.vu_ubcinfo != 0) + printf " mapped %d", ($vp->v_un.vu_ubcinfo.ui_flags & 0x08) ? 1 : 0 + end + printf "\n" +end + +document print_vnode +Syntax: (gdb) print_vnode +| Prints out the fields of a vnode struct +end + +define showprocvnodes + set $pp = (struct proc *)$arg0 + set $fdp = (struct filedesc *)$pp->p_fd + set $cvp = $fdp->fd_cdir + set $rvp = $fdp->fd_rdir + if $cvp + printf "Current Working Directory \n" + print_vnode $cvp + printf "\n" + end + if $rvp + printf "Current Root Directory \n" + print_vnode $rvp + printf "\n" + end + set $count = 0 + set $fpp = (struct fileproc **)($fdp->fd_ofiles) + set $fpo = (char)($fdp->fd_ofileflags[0]) + while $count < $fdp->fd_nfiles + #printf"fpp %x ", *$fpp + if *$fpp + set $fg =(struct fileglob *)((**$fpp)->f_fglob) + if $fg && (($fg)->fg_type == 1) + if $fdp->fd_ofileflags[$count] & 4 + printf "U: " + else + printf " " + end + printf "fd = %d ", $count + print_vnode $fg->fg_data + end + end + set $fpp = $fpp + 1 + set $count = $count + 1 + end +end + +document showprocvnodes +Syntax: (gdb) showprocvnodes +| Routine to print out all the open fds +| which are vnodes in a process +end + +define showallprocvnodes + set $basep = (struct proc *)allproc->lh_first + set $pp = $basep + while $pp + printf "============================================ \n" + showprocinfo $pp + showprocvnodes $pp + set $pp = $pp->p_list.le_next + end +end + +document showallprocvnodes +Syntax: (gdb) showallprocvnodes +| Routine to print out all the open fds +| which are vnodes +end + + +# +# dump the childrent of a proc +# +define showinitchild + set $basep = (struct proc *)initproc->p_children.lh_first + set $pp = $basep + while $pp + showprocinfo $pp + set $pp = $pp->p_sibling.le_next + end +end + +document showinitchild +Syntax: (gdb) showinitchild +| Routine to print out all processes in the system +| which are children of init process +end + + +define showmountallvnodes + set $mp = (struct mount *)$arg0 + set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first + set $vp = $basevp + printf "____________________ Vnode list Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end + set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first + set $vp = $basevp + printf "____________________ Worker Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end + set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first + set $vp = $basevp + printf "____________________ New vnodes Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end +end +document showmountallvnodes +Syntax: showmountallvnodes +| Print the vnode inactive list +end + + +define showmountvnodes + set $mp = (struct mount *)$arg0 + set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first + set $vp = $basevp + printf "____________________ Vnode list Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end +end +document showmountvnodes +Syntax: showmountvnodes +| Print the vnode list +end + + + +define showworkqvnodes + set $mp = (struct mount *)$arg0 + set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first + set $vp = $basevp + printf "____________________ Worker Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end +end +document showworkqvnodes +Syntax: showworkqvnodes +| Print the vnode worker list +end + + +define shownewvnodes + set $mp = (struct mount *)$arg0 + set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first + set $vp = $basevp + printf "____________________ New vnodes Queue ---------------\n" + while $vp + print_vnode $vp + set $vp = $vp->v_mntvnodes->tqe_next + end +end + +document shownewvnodes +Syntax: shownewvnodes +| Print the new vnode list +end + + +# +# print mount point info +define print_mount + set $mp = (struct mount *)$arg0 + printf " " + printf " mp " + showptr $mp + printf " flag %x", $mp->mnt_flag + printf " kern_flag %x", $mp->mnt_kern_flag + printf " lflag %x", $mp->mnt_lflag + printf " type: %s", $mp->mnt_vfsstat.f_fstypename + printf " mnton: %s", $mp->mnt_vfsstat.f_mntonname + printf " mntfrom: %s", $mp->mnt_vfsstat.f_mntfromname + printf "\n" +end + +define showallmounts + set $mp=(struct mount *)mountlist.tqh_first + while $mp + print_mount $mp + set $mp = $mp->mnt_list.tqe_next + end +end + +document showallmounts +Syntax: showallmounts +| Print all mount points +end + +define pcprint + if (((unsigned long) $arg0 < (unsigned long) &_mh_execute_header || \ + (unsigned long) $arg0 >= (unsigned long) &last_kernel_symbol )) + showkmodaddr $arg0 + else + output /a $arg0 + end +end + +define mbuf_walkpkt + set $mp = (struct mbuf *)$arg0 + set $cnt = 1 + set $tot = 0 + while $mp + printf "%4d: %p [len %4d, type %2d, ", $cnt, $mp, \ + $mp->m_hdr.mh_len, $mp->m_hdr.mh_type + if mclaudit != 0 + mbuf_buf2mca $mp + printf ", " + end + set $tot = $tot + $mp->m_hdr.mh_len + printf "total %d]\n", $tot + set $mp = $mp->m_hdr.mh_nextpkt + set $cnt = $cnt + 1 + end +end + +document mbuf_walkpkt +Syntax: (gdb) mbuf_walkpkt +| Given an mbuf address, walk its m_nextpkt pointer +end + +define mbuf_walk + set $mp = (struct mbuf *)$arg0 + set $cnt = 1 + set $tot = 0 + while $mp + printf "%4d: %p [len %4d, type %2d, ", $cnt, $mp, \ + $mp->m_hdr.mh_len, $mp->m_hdr.mh_type + if mclaudit != 0 + mbuf_buf2mca $mp + printf ", " + end + set $tot = $tot + $mp->m_hdr.mh_len + printf "total %d]\n", $tot + set $mp = $mp->m_hdr.mh_next + set $cnt = $cnt + 1 + end +end + +document mbuf_walk +Syntax: (gdb) mbuf_walk +| Given an mbuf address, walk its m_next pointer +end + +define mbuf_buf2slab + set $addr = $arg0 + set $gix = ((char *)$addr - (char *)mbutl) >> 20 + set $ix = ((char *)$addr - (char *)slabstbl[$gix].slg_slab[0].sl_base) >> 12 + set $slab = &slabstbl[$gix].slg_slab[$ix] + if $kgm_lp64 + printf "0x%-16llx", $slab + else + printf "0x%-8x", $slab + end +end + +document mbuf_buf2slab +| Given an mbuf object, find its corresponding slab address. +end + +define mbuf_buf2mca + set $addr = $arg0 + set $ix = ((char *)$addr - (char *)mbutl) >> 12 + set $clbase = ((union mbigcluster *)mbutl) + $ix + set $mclidx = (((char *)$addr - (char *)$clbase) >> 8) + set $mca = mclaudit[$ix].cl_audit[$mclidx] + if $kgm_lp64 + printf "mca: 0x%-16llx", $mca + else + printf "mca: 0x%-8x", $mca + end +end + +document mbuf_buf2mca +Syntax: (gdb) mbuf_buf2mca +| Given an mbuf object, find its buffer audit structure address. +| This requires mbuf buffer auditing to be turned on, by setting +| the appropriate flags to the "mbuf_debug" boot-args parameter. +end + +define mbuf_showmca + set language c + set $mca = (mcache_audit_t *)$arg0 + set $cp = (mcache_t *)$mca->mca_cache + printf "object type:\t\t" + mbuf_mca_ctype $mca 1 + printf "\ncontrolling mcache:\t%p (%s)\n", $mca->mca_cache, $cp->mc_name + if $mca->mca_uflags & $MB_SCVALID + set $ix = ((char *)$mca->mca_addr - (char *)mbutl) >> 12 + set $clbase = ((union mbigcluster *)mbutl) + $ix + set $mclidx = (((char *)$mca->mca_addr - (char *)$clbase) >> 8) + printf "mbuf obj:\t\t%p\n", $mca->mca_addr + printf "mbuf index:\t\t%d (out of 16) in cluster base %p\n", \ + $mclidx + 1, $clbase + if $mca->mca_uptr != 0 + set $peer_mca = (mcache_audit_t *)$mca->mca_uptr + printf "paired cluster obj:\t%p (mca %p)\n", \ + $peer_mca->mca_addr, $peer_mca + end + printf "saved contents:\t\t%p (%d bytes)\n", \ + $mca->mca_contents, $mca->mca_contents_size + else + printf "cluster obj:\t\t%p\n", $mca->mca_addr + if $mca->mca_uptr != 0 + set $peer_mca = (mcache_audit_t *)$mca->mca_uptr + printf "paired mbuf obj:\t%p (mca %p)\n", \ + $peer_mca->mca_addr, $peer_mca + end + end + printf "recent transaction for this buffer (thread %p):\n", \ + $mca->mca_thread + set $cnt = 0 + while $cnt < $mca->mca_depth + set $kgm_pc = $mca->mca_stack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + if $mca->mca_pdepth > 0 + printf "previous transaction for this buffer (thread %p):\n", \ + $mca->mca_pthread + end + set $cnt = 0 + while $cnt < $mca->mca_pdepth + set $kgm_pc = $mca->mca_pstack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + set language auto +end + +document mbuf_showmca +Syntax: (gdb) mbuf_showmca +| Given an mbuf/cluster buffer audit structure address, print the audit +| records including the stack trace of the last buffer transaction. +end + +define mbuf_topleak + set language c + set $topcnt = 0 + if $arg0 < 5 + set $maxcnt = $arg0 + else + set $maxcnt = 5 + end + while $topcnt < $maxcnt + mbuf_traceleak mleak_top_trace[$topcnt] + set $topcnt = $topcnt + 1 + end + set language auto +end + +document mbuf_topleak +Syntax: (gdb) mbuf_topleak +| Prints information about the top suspected mbuf leakers +| where is a value <= 5 +end + +define mbuf_traceleak + set language c + set $trace = (struct mtrace *) $arg0 + if $trace->allocs != 0 + printf "%p:%d outstanding allocs\n", $trace, $trace->allocs + printf "backtrace saved %d deep:\n", $trace->depth + if $trace->depth != 0 + set $cnt = 0 + while $cnt < $trace->depth + printf "%4d: ", $cnt + 1 + pcprint $trace->addr[$cnt] + printf "\n" + set $cnt = $cnt + 1 + end + end + end + set language auto +end + +document mbuf_traceleak +Syntax: (gdb) mbuf_traceleak +| Given an mbuf leak trace (mtrace) structure address, print out the +| stored information with that trace +end + +set $MCF_NOCPUCACHE = 0x10 + +define mcache_stat + set $head = (mcache_t *)mcache_head + set $mc = $head + + if $kgm_lp64 + printf "cache cache cache buf buf backing (# of retries) bufs\n" + printf "name state addr size align zone wait nowait failed incache\n" + printf "------------------------- -------- ------------------ ------ ----- ------------------ -------------------------- --------\n" + else + printf "cache cache cache buf buf backing (# of retries) bufs\n" + printf "name state addr size align zone wait nowait failed incache\n" + printf "------------------------- -------- ---------- ------ ----- ---------- -------------------------- --------\n" + end + while $mc != 0 + set $bktsize = $mc->mc_cpu.cc_bktsize + printf "%-25s ", $mc->mc_name + if ($mc->mc_flags & $MCF_NOCPUCACHE) + printf "disabled" + else + if $mc->mc_purge_cnt > 0 + printf " purging" + else + if $bktsize == 0 + printf " offline" + else + printf " online" + end + end + end + printf " %p %6d %5d ",$mc, \ + $mc->mc_bufsize, $mc->mc_align + if $mc->mc_slab_zone != 0 + printf "%p", $mc->mc_slab_zone + else + if $kgm_lp64 + printf " custom" + else + printf " custom" + end + end + set $tot = 0 + set $tot += $mc->mc_full.bl_total * $bktsize + set $ccp = (mcache_cpu_t *)$mc->mc_cpu + set $n = 0 + while $n < ncpu + if $ccp->cc_objs > 0 + set $tot += $ccp->cc_objs + end + if $ccp->cc_pobjs > 0 + set $tot += $ccp->cc_pobjs + end + set $n += 1 + set $ccp += 1 + end + printf " %8d %8d %8d %8d", $mc->mc_wretry_cnt, \ + $mc->mc_nwretry_cnt, $mc->mc_nwfail_cnt, $tot + printf "\n" + set $mc = (mcache_t *)$mc->mc_list.le_next + end +end + +document mcache_stat +Syntax: (gdb) mcache_stat +| Print all mcaches in the system. +end + +define mcache_showzone + set $mc = (mcache_t *)$arg0 + if $mc->mc_slab_zone != 0 + printf "%p", $mc->mc_slab_zone + else + printf " custom" +end + +document mcache_showzone +Syntax: (gdb) mcache_showzone +| Print the type of backend (custom or zone) of a mcache. +end + +define mcache_walkobj + set $p = (mcache_obj_t *)$arg0 + set $cnt = 1 + set $tot = 0 + while $p + printf "%4d: %p\n", $cnt, $p, + set $p = $p->obj_next + set $cnt = $cnt + 1 + end +end + +document mcache_walkobj +Syntax: (gdb) mcache_walkobj +| Given a mcache object address, walk its obj_next pointer +end + +define mcache_showcache + set $cp = (mcache_t *)$arg0 + set $ccp = (mcache_cpu_t *)$cp->mc_cpu + set $bktsize = $cp->mc_cpu.cc_bktsize + set $cnt = 0 + set $tot = 0 + printf "Showing cache '%s':\n\n", $cp->mc_name + printf " CPU cc_objs cc_pobjs total\n" + printf "---- -------- -------- --------\n" + while $cnt < ncpu + set $objs = $ccp->cc_objs + if $objs <= 0 + set $objs = 0 + end + set $pobjs = $ccp->cc_pobjs + if $pobjs <= 0 + set $pobjs = 0 + end + set $tot_cpu = $objs + $pobjs + set $tot += $tot_cpu + printf "%4d %8d %8d %8d\n", $cnt, $objs, $pobjs, $tot_cpu + set $ccp += 1 + set $cnt += 1 + end + printf " ========\n" + printf " %8d\n", $tot + printf "\n" + set $tot += $cp->mc_full.bl_total * $bktsize + printf "Total # of full buckets (%d objs/bkt):\t%-8d\n", \ + $bktsize, $cp->mc_full.bl_total + printf "Total # of objects cached:\t\t%-8d\n", $tot +end + +document mcache_showcache +| Display the number of objects in the cache +end + +set $NSLABSPMB = sizeof(mcl_slabg_t)/sizeof(mcl_slab_t) + +define mbuf_slabstbl + set $x = 0 + + if $kgm_lp64 + printf "slot slabg slabs range\n" + printf "---- ------------------ -------------------------------------------\n" + else + printf "slot slabg slabs range\n" + printf "---- ---------- ---------------------------\n" + end + while $x < maxslabgrp + set $slg = slabstbl[$x] + printf "%3d: ", $x + if $slg == 0 + printf "-\n" + else + if $kgm_lp64 + printf "0x%-16llx [ 0x%-16llx - 0x%-16llx ]\n", $slg, &$slg->slg_slab[0], \ + &$slg->slg_slab[$NSLABSPMB-1] + else + printf "0x%-8x [ 0x%-8x - 0x%-8x ]\n", $slg, &$slg->slg_slab[0], \ + &$slg->slg_slab[$NSLABSPMB-1] + end + end + set $x += 1 + end +end + +document mbuf_slabstbl +| Display the mbuf slabs table +end + +set $SLF_MAPPED=0x0001 +set $SLF_PARTIAL=0x0002 +set $SLF_DETACHED=0x0004 + +define mbuf_slabs + set $slg = (mcl_slabg_t *)$arg0 + set $x = 0 + + if $kgm_lp64 + printf "slot slab next obj mca C R N size flags\n" + printf "---- ------------------ ------------------ ------------------ ------------------ -- -- -- ------ -----\n" + else + printf "slot slab next obj mca C R N size flags\n" + printf "---- ---------- ---------- ---------- ---------- -- -- -- ------ -----\n" + end + while $x < $NSLABSPMB + set $sl = &$slg->slg_slab[$x] + set $mca = 0 + set $obj = $sl->sl_base + + if mclaudit != 0 + set $ix = ((char *)$obj - (char *)mbutl) >> 12 + set $clbase = ((union mbigcluster *)mbutl) + $ix + set $mclidx = (((char *)$obj - (char *)$clbase) >> 8) + set $mca = mclaudit[$ix].cl_audit[$mclidx] + end + + if $kgm_lp64 + printf "%3d: 0x%-16llx 0x%-16llx 0x%-16llx 0x%-16llx %2d %2d %2d %6d 0x%04x ", \ + $x + 1, $sl, $sl->sl_next, $obj, $mca, $sl->sl_class, \ + $sl->sl_refcnt, $sl->sl_chunks, $sl->sl_len, \ + $sl->sl_flags + else + printf "%3d: 0x%-8x 0x%-8x 0x%-8x 0x%-8x %2d %2d %2d %6d 0x%04x ", \ + $x + 1, $sl, $sl->sl_next, $obj, $mca, $sl->sl_class, \ + $sl->sl_refcnt, $sl->sl_chunks, $sl->sl_len, \ + $sl->sl_flags + end + if $sl->sl_flags != 0 + printf "<" + if $sl->sl_flags & $SLF_MAPPED + printf "mapped" + end + if $sl->sl_flags & $SLF_PARTIAL + printf ",partial" + end + if $sl->sl_flags & $SLF_DETACHED + printf ",detached" + end + printf ">" + end + printf "\n" + + if $sl->sl_chunks > 1 + set $z = 1 + set $c = $sl->sl_len / $sl->sl_chunks + + while $z < $sl->sl_chunks + set $obj = $sl->sl_base + ($c * $z) + set $mca = 0 + + if mclaudit != 0 + set $ix = ((char *)$obj - (char *)mbutl) >> 12 + set $clbase = ((union mbigcluster *)mbutl) + $ix + set $mclidx = (((char *)$obj - (char *)$clbase) >> 8) + set $mca = mclaudit[$ix].cl_audit[$mclidx] + end + + if $kgm_lp64 + printf " 0x%-16llx 0x%-16llx\n", $obj, $mca + else + printf " 0x%-8x 0x%-8x\n", $obj, $mca + end + set $z += 1 + end + end + + set $x += 1 + end +end + +document mbuf_slabs +| Display all mbuf slabs in the group +end + +define mbuf_stat + set $x = 0 + + printf "class total cached uncached inuse failed waiter notified purge\n" + printf "name objs objs objs / slabs objs alloc count count count count\n" + printf "---------------- -------- -------- ------------------- -------- ---------------- -------- -------- --------\n" + while $x < (sizeof(mbuf_table) / sizeof(mbuf_table[0])) + set $mbt = mbuf_table[$x] + set $mcs = (mb_class_stat_t *)mbuf_table[$x].mtbl_stats + set $tot = 0 + set $mc = $mbt->mtbl_cache + set $bktsize = $mc->mc_cpu.cc_bktsize + set $tot += $mc->mc_full.bl_total * $bktsize + set $ccp = (mcache_cpu_t *)$mc->mc_cpu + set $n = 0 + while $n < ncpu + if $ccp->cc_objs > 0 + set $tot += $ccp->cc_objs + end + if $ccp->cc_pobjs > 0 + set $tot += $ccp->cc_pobjs + end + set $n += 1 + set $ccp += 1 + end + + printf "%-16s %8d %8d %8d / %-8d %8d %16llu %8d %8llu %8llu", \ + $mcs->mbcl_cname, $mcs->mbcl_total, $tot, \ + $mcs->mbcl_infree, $mcs->mbcl_slab_cnt, \ + ($mcs->mbcl_total - $tot - $mcs->mbcl_infree), \ + $mcs->mbcl_fail_cnt, $mc->mc_waiter_cnt, \ + $mcs->mbcl_notified, $mcs->mbcl_purge_cnt + printf "\n" + set $x += 1 + end +end + +document mbuf_stat +| Print extended mbuf allocator statistics. +end + +set $MB_INUSE = 0x1 +set $MB_COMP_INUSE = 0x2 +set $MB_SCVALID = 0x4 + +set $MCLBYTES = 2048 +set $MSIZE = 256 +set $NBPG = 4096 +set $M16KCLBYTES = 16384 + +define mbuf_mca_ctype + set $mca = (mcache_audit_t *)$arg0 + set $vopt = $arg1 + set $cp = $mca->mca_cache + set $class = (unsigned int)$cp->mc_private + set $csize = mbuf_table[$class].mtbl_stats->mbcl_size + set $done = 0 + if $csize == $MSIZE + if $vopt + printf "M (mbuf) " + else + printf "M " + end + set $done = 1 + end + if !$done && $csize == $MCLBYTES + if $vopt + printf "CL (2K cluster) " + else + printf "CL " + end + set $done = 1 + end + if !$done && $csize == $NBPG + if $vopt + printf "BCL (4K cluster) " + else + printf "BCL " + end + set $done = 1 + end + if !$done && $csize == $M16KCLBYTES + if $vopt + printf "JCL (16K cluster) " + else + printf "JCL " + end + set $done = 1 + end + if !$done && $csize == ($MSIZE+$MCLBYTES) + if $mca->mca_uflags & $MB_SCVALID + if $mca->mca_uptr + printf "M+CL " + if $vopt + printf "(paired mbuf, 2K cluster)" + end + else + printf "M-CL " + if $vopt + printf "(unpaired mbuf, 2K cluster) " + end + end + else + if $mca->mca_uptr + printf "CL+M " + if $vopt + printf "(paired 2K cluster, mbuf) " + end + else + printf "CL-M " + if $vopt + printf "(paired 2K cluster, mbuf) " + end + end + end + set $done = 1 + end + if !$done && $csize == ($MSIZE+$NBPG) + if $mca->mca_uflags & $MB_SCVALID + if $mca->mca_uptr + printf "M+BCL " + if $vopt + printf "(paired mbuf, 4K cluster) " + end + else + printf "M-BCL " + if $vopt + printf "(unpaired mbuf, 4K cluster) " + end + end + else + if $mca->mca_uptr + printf "BCL+M " + if $vopt + printf "(paired 4K cluster, mbuf) " + end + else + printf "BCL-M " + if $vopt + printf "(unpaired 4K cluster, mbuf) " + end + end + end + set $done = 1 + end + if !$done && $csize == ($MSIZE+$M16KCLBYTES) + if $mca->mca_uflags & $MB_SCVALID + if $mca->mca_uptr + printf "M+JCL " + if $vopt + printf "(paired mbuf, 16K cluster) " + end + else + printf "M-JCL " + if $vopt + printf "(unpaired mbuf, 16K cluster) " + end + end + else + if $mca->mca_uptr + printf "JCL+M " + if $vopt + printf "(paired 16K cluster, mbuf) " + end + else + printf "JCL-M " + if $vopt + printf "(unpaired 16K cluster, mbuf) " + end + end + end + set $done = 1 + end + if !$done + printf "unknown: %s ", $cp->mc_name + end +end + +document mbuf_mca_ctype +| This is a helper macro for mbuf_show{active,inactive,all} that prints +| out the mbuf object type represented by a given mcache audit structure. +end + +define mbuf_showactive + if $argc == 0 + mbuf_walkallslabs 1 0 + else + mbuf_walkallslabs 1 0 $arg0 + end +end + +document mbuf_showactive +Syntax: (gdb) mbuf_showactive +| Walk the mbuf objects pool and print only the active ones; this +| requires mbuf debugging to be turned on, by setting the appropriate flags +| to the "mbuf_debug" boot-args parameter. Active objects are those that +| are outstanding (have not returned to the mbuf slab layer) and in use +| by the client (have not been freed). +end + +define mbuf_showinactive + mbuf_walkallslabs 0 1 +end + +document mbuf_showinactive +Syntax: (gdb) mbuf_showinactive +| Walk the mbuf objects pool and print only the inactive ones; this +| requires mbuf debugging to be turned on, by setting the appropriate flags +| to the "mbuf_debug" boot-args parameter. Inactive objects are those that +| are outstanding (have not returned to the mbuf slab layer) but have been +| freed by the client, i.e. they still reside in the mcache layer ready to +| be used for subsequent allocation requests. +end + +define mbuf_showall + mbuf_walkallslabs 1 1 +end + +document mbuf_showall +Syntax: (gdb) mbuf_showall +| Walk the mbuf objects pool and print them all; this requires +| mbuf debugging to be turned on, by setting the appropriate flags to the +| "mbuf_debug" boot-args parameter. +end + +define mbuf_mcaobjs +end + +define mbuf_walkallslabs + set $show_a = $arg0 + set $show_f = $arg1 + if $argc == 3 + set $show_tr = $arg2 + else + set $show_tr = 0 + end + set $x = 0 + set $total = 0 + set $total_a = 0 + set $total_f = 0 + + printf "(" + if $show_a && !$show_f + printf "Searching only for active " + end + if !$show_a && $show_f + printf "Searching only for inactive " + end + if $show_a && $show_f + printf "Displaying all " + end + printf "objects; this may take a while ...)\n\n" + + if $kgm_lp64 + printf " slab mca obj allocation\n" + printf "slot idx address address address type state\n" + printf "---- ---- ------------------ ------------------ ------------------ ----- -----------\n" + else + printf " slab mca obj allocation\n" + printf "slot idx address address address type state\n" + printf "---- ---- ---------- ---------- ---------- ----- -----------\n" + end + + while $x < slabgrp + set $slg = slabstbl[$x] + set $y = 0 + set $stop = 0 + while $y < $NSLABSPMB && $stop == 0 + set $sl = &$slg->slg_slab[$y] + set $base = (char *)$sl->sl_base + set $ix = ($base - (char *)mbutl) >> 12 + set $clbase = ((union mbigcluster *)mbutl) + $ix + set $mclidx = ($base - (char *)$clbase) >> 8 + set $mca = mclaudit[$ix].cl_audit[$mclidx] + set $first = 1 + + while $mca != 0 && $mca->mca_addr != 0 + set $printmca = 0 + if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE) + set $total_a = $total_a + 1 + set $printmca = $show_a + else + set $total_f = $total_f + 1 + set $printmca = $show_f + end + + if $printmca != 0 + if $first == 1 + if $kgm_lp64 + printf "%4d %4d 0x%-16llx ", $x, $y, $sl + else + printf "%4d %4d 0x%-8x ", $x, $y, $sl + end + else + if $kgm_lp64 + printf " " + else + printf " " + end + end + + if $kgm_lp64 + printf "0x%-16llx 0x%-16llx ", $mca, $mca->mca_addr + else + printf "0x%-8x 0x%-8x ", $mca, $mca->mca_addr + end + + mbuf_mca_ctype $mca 0 + if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE) + printf "active " + else + printf " freed " + end + if $first == 1 + set $first = 0 + end + printf "\n" + set $total = $total + 1 + + if $show_tr != 0 + printf "recent transaction for this buffer (thread %p):\n", \ + $mca->mca_thread + set $cnt = 0 + while $cnt < $mca->mca_depth + set $kgm_pc = $mca->mca_stack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + end + end + + set $mca = $mca->mca_next + end + set $y += 1 + if $slg->slg_slab[$y].sl_base == 0 + set $stop = 1 + end + end + set $x += 1 + end + if $total && $show_a && $show_f + printf "\ntotal objects:\t%d\n", $total + printf "active/unfreed:\t%d\n", $total_a + printf "freed/in_cache:\t%d\n", $total_f + end +end + +document mbuf_walkallslabs +| Walk the mbuf objects pool; this requires mbuf debugging to be +| turned on, by setting the appropriate flags to the "mbuf_debug" boot-args +| parameter. This is a backend routine for mbuf_show{active,inactive,all}. +end + +define mbuf_countchain + set $mp = (struct mbuf *)$arg0 + + set $pkt = 0 + set $nxt = 0 + + while $mp != 0 + set $pkt = $pkt + 1 + + set $mn = (struct mbuf *)$mp->m_hdr.mh_next + while $mn != 0 + set $nxt = $nxt + 1 + + set $mn = (struct mbuf *)$mn->m_hdr.mh_next + end + + set $mp = $mp->m_hdr.mh_nextpkt + + if (($pkt + $nxt) % 50) == 0 + printf "... %d\n", $pkt + $nxt + end + end + + printf "\ntotal: %d (via m_next: %d)\n", $pkt + $nxt, $nxt +end + +document mbuf_countchain +Syntax: mbuf_countchain +| Count the total number of mbufs chained from the given the address of an mbuf. +| The routine follows both the m_next pointers and m_nextpkt pointers. +end + +set $RTF_UP = 0x1 +set $RTF_GATEWAY = 0x2 +set $RTF_HOST = 0x4 +set $RTF_REJECT = 0x8 +set $RTF_DYNAMIC = 0x10 +set $RTF_MODIFIED = 0x20 +set $RTF_DONE = 0x40 +set $RTF_DELCLONE = 0x80 +set $RTF_CLONING = 0x100 +set $RTF_XRESOLVE = 0x200 +set $RTF_LLINFO = 0x400 +set $RTF_STATIC = 0x800 +set $RTF_BLACKHOLE = 0x1000 +set $RTF_PROTO2 = 0x4000 +set $RTF_PROTO1 = 0x8000 +set $RTF_PRCLONING = 0x10000 +set $RTF_WASCLONED = 0x20000 +set $RTF_PROTO3 = 0x40000 +set $RTF_PINNED = 0x100000 +set $RTF_LOCAL = 0x200000 +set $RTF_BROADCAST = 0x400000 +set $RTF_MULTICAST = 0x800000 +set $RTF_IFSCOPE = 0x1000000 +set $RTF_CONDEMNED = 0x2000000 +set $RTF_IFREF = 0x4000000 +set $RTF_PROXY = 0x8000000 +set $RTF_ROUTER = 0x10000000 + +set $AF_INET = 2 +set $AF_INET6 = 30 +set $AF_LINK = 18 + +define rtentry_prdetails + set $rt = (struct rtentry *)$arg0 + set $is_v6 = 0 + + set $dst = (struct sockaddr *)$rt->rt_nodes->rn_u.rn_leaf.rn_Key + if $dst->sa_family == $AF_INET + showsockaddr_in $dst + printf " " + else + if $dst->sa_family == $AF_INET6 + showsockaddr_in6 $dst + printf " " + set $is_v6 = 1 + else + if $dst->sa_family == $AF_LINK + showsockaddr_dl $dst + printf " " + else + showsockaddr_unspec $dst + end + end + end + + set $dst = (struct sockaddr *)$rt->rt_gateway + if $dst->sa_family == $AF_INET + showsockaddr_in $dst + printf " " + else + if $dst->sa_family == $AF_INET6 + set $is_v6 = 1 + showsockaddr_in6 $dst + printf " " + else + if $dst->sa_family == $AF_LINK + showsockaddr_dl $dst + if $is_v6 + printf " " + else + printf " " + end + else + showsockaddr_unspec $dst + end + end + end + + if $rt->rt_flags & $RTF_WASCLONED + if $kgm_lp64 + printf "%18p ", $rt->rt_parent + else + printf "%10p ", $rt->rt_parent + end + else + if $kgm_lp64 + printf " " + else + printf " " + end + end + + printf "%6u %8u ", $rt->rt_refcnt, $rt->rt_rmx.rmx_pksent + + if $rt->rt_flags & $RTF_UP + printf "U" + end + if $rt->rt_flags & $RTF_GATEWAY + printf "G" + end + if $rt->rt_flags & $RTF_HOST + printf "H" + end + if $rt->rt_flags & $RTF_REJECT + printf "R" + end + if $rt->rt_flags & $RTF_DYNAMIC + printf "D" + end + if $rt->rt_flags & $RTF_MODIFIED + printf "M" + end + if $rt->rt_flags & $RTF_CLONING + printf "C" + end + if $rt->rt_flags & $RTF_PRCLONING + printf "c" + end + if $rt->rt_flags & $RTF_LLINFO + printf "L" + end + if $rt->rt_flags & $RTF_STATIC + printf "S" + end + if $rt->rt_flags & $RTF_PROTO1 + printf "1" + end + if $rt->rt_flags & $RTF_PROTO2 + printf "2" + end + if $rt->rt_flags & $RTF_PROTO3 + printf "3" + end + if $rt->rt_flags & $RTF_WASCLONED + printf "W" + end + if $rt->rt_flags & $RTF_BROADCAST + printf "b" + end + if $rt->rt_flags & $RTF_MULTICAST + printf "m" + end + if $rt->rt_flags & $RTF_XRESOLVE + printf "X" + end + if $rt->rt_flags & $RTF_BLACKHOLE + printf "B" + end + if $rt->rt_flags & $RTF_IFSCOPE + printf "I" + end + if $rt->rt_flags & $RTF_CONDEMNED + printf "Z" + end + if $rt->rt_flags & $RTF_IFREF + printf "i" + end + if $rt->rt_flags & $RTF_PROXY + printf "Y" + end + if $rt->rt_flags & $RTF_ROUTER + printf "r" + end + + printf "/%s%d", $rt->rt_ifp->if_name, $rt->rt_ifp->if_unit +end + +set $RNF_ROOT = 2 + +define _rttable_dump + set $rnh = $arg0 + set $rn = (struct radix_node *)$rnh->rnh_treetop + set $rnh_cnt = $rnh->rnh_cnt + + while $rn->rn_bit >= 0 + set $rn = $rn->rn_u.rn_node.rn_L + end + + while 1 + set $base = (struct radix_node *)$rn + while ($rn->rn_parent->rn_u.rn_node.rn_R == $rn) && ($rn->rn_flags & $RNF_ROOT) == 0 + set $rn = $rn->rn_parent + end + set $rn = $rn->rn_parent->rn_u.rn_node.rn_R + while $rn->rn_bit >= 0 + set $rn = $rn->rn_u.rn_node.rn_L + end + set $next = $rn + while $base != 0 + set $rn = $base + set $base = $rn->rn_u.rn_leaf.rn_Dupedkey + if ($rn->rn_flags & $RNF_ROOT) == 0 + + set $rt = (struct rtentry *)$rn + + if $kgm_lp64 + printf "%18p ", $rt + else + printf "%10p ", $rt + end + rtentry_prdetails $rt + printf "\n" + + end + end + set $rn = $next + if ($rn->rn_flags & $RNF_ROOT) != 0 + loop_break + end + end +end + + +define show_rt_inet + if $kgm_lp64 + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " ----------------- --------------- ----------------- ------------------ ------ -------- -----------\n" + else + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " --------- --------------- ----------------- ---------- ------ -------- -----------\n" + end + _rttable_dump rt_tables[2] +end + +document show_rt_inet +Syntax: (gdb) show_rt_inet +| Show the entries of the IPv4 routing table. +end + +define show_rt_inet6 + if $kgm_lp64 + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " ----------------- --------------------------------------- --------------------------------------- ------------------ ------ -------- -----------\n" + else + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " --------- --------------------------------------- --------------------------------------- ---------- ------ -------- -----------\n" + end + _rttable_dump rt_tables[30] +end + +document show_rt_inet6 +Syntax: (gdb) show_rt_inet6 +| Show the entries of the IPv6 routing table. +end + +define rtentry_trash + set $rtd = (struct rtentry_dbg *)rttrash_head.tqh_first + set $cnt = 0 + while $rtd != 0 + if $cnt == 0 + if $kgm_lp64 + printf " rtentry ref hold rele dst gw parent flags/if\n" + printf " ----------------- --- ------ ------ --------------- ----- ------------------ -----------\n" + else + printf " rtentry ref hold rele dst gw parent flags/if\n" + printf " --------- --- ------ ------ --------------- ----- ---------- -----------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $rtd, \ + $rtd->rtd_refhold_cnt - $rtd->rtd_refrele_cnt, \ + $rtd->rtd_refhold_cnt, $rtd->rtd_refrele_cnt + rtentry_prdetails $rtd + printf "\n" + set $rtd = $rtd->rtd_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +document rtentry_trash +Syntax: (gdb) rtentry_trash +| Walk the list of trash route entries; this requires route entry +| debugging to be turned on, by setting the appropriate flags to the +| "rte_debug" boot-args parameter. +end + +set $CTRACE_STACK_SIZE = ctrace_stack_size +set $CTRACE_HIST_SIZE = ctrace_hist_size + +define rtentry_showdbg + set $rtd = (struct rtentry_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $rtd->rtd_refhold_cnt + printf "Total releases:\t%d\n", $rtd->rtd_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $rtd->rtd_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $rtd->rtd_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $rtd->rtd_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + + printf "\nTotal locks:\t%d\n", $rtd->rtd_lock_cnt + printf "Total unlocks:\t%d\n", $rtd->rtd_unlock_cnt + + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_lock[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nLock [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_lock[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_unlock[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nUnlock [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_unlock[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document rtentry_showdbg +Syntax: (gdb) rtentry_showdbg +| Given a route entry structure address, print the debug information +| related to it. This requires route entry debugging to be turned +| on, by setting the appropriate flags to the "rte_debug" boot-args +| parameter. +end + +set $INIFA_TRACE_HIST_SIZE = inifa_trace_hist_size + +define inifa_showdbg + set $inifa = (struct in_ifaddr_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $inifa->inifa_refhold_cnt + printf "Total releases:\t%d\n", $inifa->inifa_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $inifa->inifa_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $inifa->inifa_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $INIFA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $inifa->inifa_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $INIFA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $inifa->inifa_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document inifa_showdbg +Syntax: (gdb) inifa_showdbg +| Given an IPv4 interface structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_debug" boot-args +| parameter. +end + +set $IN6IFA_TRACE_HIST_SIZE = in6ifa_trace_hist_size + +define in6ifa_showdbg + set $in6ifa = (struct in6_ifaddr_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $in6ifa->in6ifa_refhold_cnt + printf "Total releases:\t%d\n", $in6ifa->in6ifa_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $in6ifa->in6ifa_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $in6ifa->in6ifa_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $IN6IFA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $in6ifa->in6ifa_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $IN6IFA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $in6ifa->in6ifa_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document in6ifa_showdbg +Syntax: (gdb) in6ifa_showdbg +| Given an IPv6 interface structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_debug" boot-args +| parameter. +end + +set $IFMA_TRACE_HIST_SIZE = ifma_trace_hist_size + +define ifma_showdbg + set $ifma = (struct ifmultiaddr_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $ifma->ifma_refhold_cnt + printf "Total releases:\t%d\n", $ifma->ifma_refrele_cnt + + while $cnt < $IFMA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $ifma->ifma_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $ifma->ifma_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $IFMA_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $ifma->ifma_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $ifma->ifma_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document ifma_showdbg +Syntax: (gdb) ifma_showdbg +| Given a link multicast structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_debug" boot-args +| parameter. +end + +set $INM_TRACE_HIST_SIZE = inm_trace_hist_size + +define inm_showdbg + set $inm = (struct in_multi_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $inm->inm_refhold_cnt + printf "Total releases:\t%d\n", $inm->inm_refrele_cnt + + while $cnt < $INM_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inm->inm_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $inm->inm_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $INM_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inm->inm_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $inm->inm_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document inm_showdbg +Syntax: (gdb) inm_showdbg +| Given an IPv4 multicast structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_debug" boot-args +| parameter. +end + +set $IF_REF_TRACE_HIST_SIZE = if_ref_trace_hist_size + +define ifpref_showdbg + set $dl_if = (struct dlil_ifnet_dbg *)$arg0 + set $cnt = 0 + + printf "Total references:\t%d\n", $dl_if->dldbg_if_refhold_cnt + printf "Total releases:\t\t%d\n", $dl_if->dldbg_if_refrele_cnt + + while $cnt < $IF_REF_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $dl_if->dldbg_if_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, \ + $dl_if->dldbg_if_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $IF_REF_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $dl_if->dldbg_if_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, \ + $dl_if->dldbg_if_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document ifpref_showdbg +Syntax: (gdb) ifpref_showdbg +| Given an ifnet structure address, print the debug information +| related to its refcnt. This requires ifnet debugging to be turned +| on, by setting the appropriate flags to the "ifnet_debug" boot-args +| parameter. +end + +define in6ifa_trash + set $ifa = (struct in6_ifaddr_dbg *)in6ifa_trash_head.tqh_first + set $cnt = 0 + while $ifa != 0 + if $cnt == 0 + if $kgm_lp64 + printf " in6_ifa ref hold rele\n" + printf " ----------------- --- ------ ------\n" + else + printf " in6_ifa ref hold rele\n" + printf " --------- --- ------ ------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $ifa, \ + $ifa->in6ifa_refhold_cnt - $ifa->in6ifa_refrele_cnt, \ + $ifa->in6ifa_refhold_cnt, $ifa->in6ifa_refrele_cnt + showsockaddr_in6 $ifa->in6ifa.ia_ifa.ifa_addr + printf "\n" + set $ifa = $ifa->in6ifa_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +set $NDPR_TRACE_HIST_SIZE = ndpr_trace_hist_size + +define ndpr_showdbg + set $ndpr = (struct nd_prefix_dbg *)$arg0 + set $cnt = 0 + + printf "Total references:\t%d\n", $ndpr->ndpr_refhold_cnt + printf "Total releases:\t\t%d\n", $ndpr->ndpr_refrele_cnt + + while $cnt < $NDPR_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $ndpr->ndpr_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, \ + $ndpr->ndpr_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $NDPR_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $ndpr->ndpr_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, \ + $ndpr->ndpr_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document ndpr_showdbg +Syntax: (gdb) ndpr_showdbg +| Given a nd_prefix structure address, print the debug information +| related to its refcnt. This requires the interface address debugging +| to be turned on, by setting the appropriate flags to the "ifa_debug" +| boot-args parameter. +end + +set $NDDR_TRACE_HIST_SIZE = nddr_trace_hist_size + +define nddr_showdbg + set $nddr = (struct nd_defrouter_dbg *)$arg0 + set $cnt = 0 + + printf "Total references:\t%d\n", $nddr->nddr_refhold_cnt + printf "Total releases:\t\t%d\n", $nddr->nddr_refrele_cnt + + while $cnt < $NDDR_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $nddr->nddr_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, \ + $nddr->nddr_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $NDDR_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $nddr->nddr_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, \ + $nddr->nddr_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document nddr_showdbg +Syntax: (gdb) nddr_showdbg +| Given a nd_defrouter structure address, print the debug information +| related to its refcnt. This requires the interface address debugging +| to be turned on, by setting the appropriate flags to the "ifa_debug" +| boot-args parameter. +end +set $IMO_TRACE_HIST_SIZE = imo_trace_hist_size + +define imo_showdbg + set $imo = (struct ip_moptions_dbg *)$arg0 + set $cnt = 0 + + printf "Total references:\t%d\n", $imo->imo_refhold_cnt + printf "Total releases:\t\t%d\n", $imo->imo_refrele_cnt + + while $cnt < $IMO_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $imo->imo_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, \ + $imo->imo_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $IMO_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $imo->imo_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, \ + $imo->imo_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document imo_showdbg +Syntax: (gdb) imo_showdbg +| Given a ip_moptions structure address, print the debug information +| related to its refcnt. This requires the interface address debugging +| to be turned on, by setting the appropriate flags to the "ifa_debug" +| boot-args parameter. +end + +set $IM6O_TRACE_HIST_SIZE = im6o_trace_hist_size + +define im6o_showdbg + set $im6o = (struct ip6_moptions_dbg *)$arg0 + set $cnt = 0 + + printf "Total references:\t%d\n", $im6o->im6o_refhold_cnt + printf "Total releases:\t\t%d\n", $im6o->im6o_refrele_cnt + + while $cnt < $IM6O_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $im6o->im6o_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, \ + $im6o->im6o_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $IM6O_TRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $im6o->im6o_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, \ + $im6o->im6o_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document im6o_showdbg +Syntax: (gdb) im6o_showdbg +| Given a ip6_moptions structure address, print the debug information +| related to its refcnt. This requires the interface address debugging +| to be turned on, by setting the appropriate flags to the "ifa_debug" +| boot-args parameter. +end + +document in6ifa_trash +Syntax: (gdb) in6ifa_trash +| Walk the list of trash in6_ifaddr entries; this requires interface +| address debugging to be turned on, by setting the appropriate flags +| to the "ifa_debug" boot-args parameter. +end + +define inifa_trash + set $ifa = (struct in_ifaddr_dbg *)inifa_trash_head.tqh_first + set $cnt = 0 + while $ifa != 0 + if $cnt == 0 + if $kgm_lp64 + printf " in_ifa ref hold rele\n" + printf " ----------------- --- ------ ------\n" + else + printf " in_ifa ref hold rele\n" + printf " --------- --- ------ ------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $ifa, \ + $ifa->inifa_refhold_cnt - $ifa->inifa_refrele_cnt, \ + $ifa->inifa_refhold_cnt, $ifa->inifa_refrele_cnt + showsockaddr_in $ifa->inifa.ia_ifa.ifa_addr + printf "\n" + set $ifa = $ifa->inifa_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +document inifa_trash +Syntax: (gdb) inifa_trash +| Walk the list of trash in_ifaddr entries; this requires interface +| address debugging to be turned on, by setting the appropriate flags +| to the "ifa_debug" boot-args parameter. +end + +define ifma_trash + set $ifma = (struct ifmultiaddr_dbg *)ifma_trash_head.tqh_first + set $cnt = 0 + while $ifma != 0 + if $cnt == 0 + if $kgm_lp64 + printf " ifma ref hold rele\n" + printf " ----------------- --- ------ ------\n" + else + printf " ifma ref hold rele\n" + printf " --------- --- ------ ------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $ifma, \ + $ifma->ifma_refhold_cnt - $ifma->ifma_refrele_cnt, \ + $ifma->ifma_refhold_cnt, $ifma->ifma_refrele_cnt + showsockaddr $ifma->ifma.ifma_addr + printf " @ %s%d", $ifma->ifma.ifma_ifp->if_name, \ + $ifma->ifma.ifma_ifp->if_unit + printf "\n" + set $ifma = $ifma->ifma_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +document ifma_trash +Syntax: (gdb) ifma_trash +| Walk the list of trash ifmultiaddr entries; this requires interface +| address debugging to be turned on, by setting the appropriate flags +| to the "ifa_debug" boot-args parameter. +end + +define inm_trash + set $inm = (struct in_multi_dbg *)inm_trash_head.tqh_first + set $cnt = 0 + while $inm != 0 + if $cnt == 0 + if $kgm_lp64 + printf " inm ref hold rele\n" + printf " ----------------- --- ------ ------\n" + else + printf " inm ref hold rele\n" + printf " --------- --- ------ ------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $inm, \ + $inm->inm_refhold_cnt - $inm->inm_refrele_cnt, \ + $inm->inm_refhold_cnt, $inm->inm_refrele_cnt + show_in_addr &($inm->inm.inm_addr) + printf "\n" + set $inm = $inm->inm_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +document inm_trash +Syntax: (gdb) inm_trash +| Walk the list of trash in_multi entries; this requires interface +| address debugging to be turned on, by setting the appropriate flags +| to the "ifa_debug" boot-args parameter. +end + +define in6m_trash + set $in6m = (struct in6_multi_dbg *)in6m_trash_head.tqh_first + set $cnt = 0 + while $in6m != 0 + if $cnt == 0 + if $kgm_lp64 + printf " in6m ref hold rele\n" + printf " ----------------- --- ------ ------\n" + else + printf " in6m ref hold rele\n" + printf " --------- --- ------ ------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $in6m, \ + $in6m->in6m_refhold_cnt - $in6m->in6m_refrele_cnt, \ + $in6m->in6m_refhold_cnt, $in6m->in6m_refrele_cnt + show_in_addr &($in6m->in6m.in6m_addr) + printf "\n" + set $in6m = $in6m->in6m_trash_link.tqe_next + set $cnt = $cnt + 1 + end +end + +document in6m_trash +Syntax: (gdb) in6m_trash +| Walk the list of trash in6_multi entries; this requires interface +| address debugging to be turned on, by setting the appropriate flags +| to the "ifa_debug" boot-args parameter. +end + +# +# print all OSMalloc stats + +define ostag_print +set $kgm_tagp = (OSMallocTag)$arg0 +printf "0x%08x: ", $kgm_tagp +printf "%8d ",$kgm_tagp->OSMT_refcnt +printf "%8x ",$kgm_tagp->OSMT_state +printf "%8x ",$kgm_tagp->OSMT_attr +printf "%s ",$kgm_tagp->OSMT_name +printf "\n" +end + + +define showosmalloc +printf "TAG COUNT STATE ATTR NAME\n" +set $kgm_tagheadp = (struct _OSMallocTag_ *)&OSMalloc_tag_list + set $kgm_tagptr = (struct _OSMallocTag_ * )($kgm_tagheadp->OSMT_link.next) + while $kgm_tagptr != $kgm_tagheadp + ostag_print $kgm_tagptr + set $kgm_tagptr = (struct _OSMallocTag_ *)$kgm_tagptr->OSMT_link.next + end + printf "\n" +end +document showosmalloc +Syntax: (gdb) showosmalloc +| Print the outstanding allocation count by OSMallocTags. +end + + +define systemlog + if msgbufp->msg_bufc[msgbufp->msg_bufx] == 0 \ + && msgbufp->msg_bufc[0] != 0 + # The buffer hasn't wrapped, so take the easy (and fast!) path + printf "%s", msgbufp->msg_bufc + else + set $kgm_msgbuf = *msgbufp + set $kgm_syslog_bufsize = $kgm_msgbuf.msg_size + set $kgm_syslog_bufend = $kgm_msgbuf.msg_bufx + if $kgm_syslog_bufend >= $kgm_syslog_bufsize + set $kgm_syslog_bufend = 0 + end + + # print older messages from msg_bufx to end of buffer + set $kgm_i = $kgm_syslog_bufend + while $kgm_i < $kgm_syslog_bufsize + set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i] + if $kgm_syslog_char == 0 + # break out of loop + set $kgm_i = $kgm_syslog_bufsize + else + printf "%c", $kgm_syslog_char + end + set $kgm_i = $kgm_i + 1 + end + + # print newer messages from start of buffer to msg_bufx + set $kgm_i = 0 + while $kgm_i < $kgm_syslog_bufend + set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i] + if $kgm_syslog_char != 0 + printf "%c", $kgm_syslog_char + end + set $kgm_i = $kgm_i + 1 + end + end + printf "\n" +end +document systemlog +| Syntax: systemlog +| Display the kernel's printf ring buffer +end + + +define hexdump + set $kgm_addr = (unsigned char *)$arg0 + set $kgm_len = $arg1 + while $kgm_len > 0 + showptr $kgm_addr + printf ": " + set $kgm_i = 0 + while $kgm_i < 16 + printf "%02x ", *($kgm_addr+$kgm_i) + set $kgm_i += 1 + end + printf " |" + set $kgm_i = 0 + while $kgm_i < 16 + set $kgm_temp = *($kgm_addr+$kgm_i) + if $kgm_temp < 32 || $kgm_temp >= 127 + printf "." + else + printf "%c", $kgm_temp + end + set $kgm_i += 1 + end + printf "|\n" + set $kgm_addr += 16 + set $kgm_len -= 16 + end +end +document hexdump +| Show the contents of memory as a hex/ASCII dump +| The following is the syntax: +| (gdb) hexdump
+end + + +define printcolonhex + if ($argc == 2) + set $addr = $arg0 + set $count = $arg1 + set $li = 0 + while ($li < $count) + if ($li == 0) + printf "%02x", (u_char)$addr[$li] + end + if ($li != 0) + printf ":%02x", (u_char)$addr[$li] + end + set $li = $li + 1 + end + end +end + +define showsockaddr_dl + set $sdl = (struct sockaddr_dl *)$arg0 + if ($sdl == 0) + printf "(null) " + else + if $sdl->sdl_nlen == 0 && $sdl->sdl_alen == 0 && $sdl->sdl_slen == 0 + printf "link#%3d ", $sdl->sdl_index + else + set $addr = $sdl->sdl_data + $sdl->sdl_nlen + set $count = $sdl->sdl_alen + printcolonhex $addr $count + end + end +end + +define showsockaddr_unspec + set $sockaddr = (struct sockaddr *)$arg0 + set $addr = $sockaddr->sa_data + set $count = $sockaddr->sa_len - 2 + printcolonhex $addr $count +end + +define showsockaddr_at + set $sockaddr = (struct sockaddr *)$arg0 + set $addr = $sockaddr->sa_data + set $count = $sockaddr->sa_len - 2 + printcolonhex $addr $count +end + +define show_in_addr + set $ia = (unsigned char *)$arg0 + printf "%3u.%03u.%03u.%03u", $ia[0], $ia[1], $ia[2], $ia[3] +end + +define showsockaddr_in + set $sin = (struct sockaddr_in *)$arg0 + set $sa_bytes = (unsigned char *)&($sin->sin_addr) + show_in_addr $sa_bytes +end + +define show_in6_addr + set $ia = (unsigned char *)$arg0 + printf "%2x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + $ia[0], $ia[1], $ia[2], $ia[3], $ia[4], $ia[5], $ia[6], $ia[7], $ia[8], $ia[9], $ia[10], $ia[11], $ia[12], $ia[13], $ia[14], $ia[15] +end + +define showsockaddr_in6 + set $sin6 = (struct sockaddr_in6 *)$arg0 + set $sa_bytes = $sin6->sin6_addr.__u6_addr.__u6_addr8 + show_in6_addr $sa_bytes +end + +define showsockaddr_un + set $sun = (struct sockaddr_un *)$arg0 + if $sun == 0 + printf "(null)" + else + if $sun->sun_path[0] == 0 + printf "\"\"" + else + printf "%s", $sun->sun_path + end + end +end + +define showifmultiaddrs + set $ifp = (struct ifnet *)$arg0 + set $if_multi = (struct ifmultiaddr *)$ifp->if_multiaddrs->lh_first + set $mymulti = $if_multi + set $myi = 0 + while ($mymulti != 0) + printf "%2d. %p ", $myi, $mymulti + set $sa_family = $mymulti->ifma_addr.sa_family + if ($sa_family == 2) + if ($mymulti->ifma_ll != 0) + showsockaddr_dl $mymulti->ifma_ll->ifma_addr + printf " " + end + showsockaddr_in $mymulti->ifma_addr + end + if ($sa_family == 30) + if ($mymulti->ifma_ll != 0) + showsockaddr_dl $mymulti->ifma_ll->ifma_addr + printf " " + end + showsockaddr_in6 $mymulti->ifma_addr + end + if ($sa_family == 18) + showsockaddr_dl $mymulti->ifma_addr + end + if ($sa_family == 0) + showsockaddr_unspec $mymulti->ifma_addr 6 + end + printf " [%d]", $mymulti->ifma_refcount + printf "\n" + set $mymulti = $mymulti->ifma_link.le_next + set $myi = $myi + 1 + end +end + +document showifmultiaddrs +Syntax showifmultiaddrs +| show the (struct ifnet).if_multiaddrs list of multicast addresses for the given ifp +end + +define showinmultiaddrs + set $in_multi = (struct in_multi *)(in_multihead->lh_first) + set $mymulti = $in_multi + set $myi = 0 + while ($mymulti != 0) + set $ifp = (struct ifnet *)$mymulti->inm_ifp + printf "%2d. %p ", $myi, $mymulti + show_in_addr &($mymulti->inm_addr) + printf " (ifp %p [%s%d] ifma %p) ", $ifp, $ifp->if_name, \ + $ifp->if_unit, $mymulti->inm_ifma + printf "\n" + set $mymulti = $mymulti->inm_link.le_next + set $myi = $myi + 1 + end +end + +document showinmultiaddrs +Syntax showinmultiaddrs +| show the contents of IPv4 multicast address records +end + +define showin6multiaddrs + set $in6_multi = (struct in6_multi *)(in6_multihead->lh_first) + set $mymulti = $in6_multi + set $myi = 0 + while ($mymulti != 0) + set $ifp = (struct ifnet *)$mymulti->in6m_ifp + printf "%2d. %p ", $myi, $mymulti + show_in6_addr &($mymulti->in6m_addr) + printf " (ifp %p [%s%d] ifma %p) ", $ifp, $ifp->if_name, \ + $ifp->if_unit, $mymulti->in6m_ifma + printf "\n" + set $mymulti = $mymulti->in6m_entry.le_next + set $myi = $myi + 1 + end +end + +document showin6multiaddrs +Syntax showin6multiaddrs +| show the contents of IPv6 multicast address records +end + +define showsockaddr + set $mysock = (struct sockaddr *)$arg0 + set $showsockaddr_handled = 0 + if ($mysock == 0) + printf "(null)" + else + if ($mysock->sa_family == 0) + printf "UNSPC" + showsockaddr_unspec $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 1) + printf "UNIX " + showsockaddr_un $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 2) + printf "INET " + showsockaddr_in $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 30) + printf "INET6 " + showsockaddr_in6 $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 18) + printf "LINK " + showsockaddr_dl $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 16) + printf "ATLK " + showsockaddr_at $mysock + set $showsockaddr_handled = 1 + end + if ($showsockaddr_handled == 0) + printf "FAM %d ", $mysock->sa_family + set $addr = $mysock->sa_data + set $count = $mysock->sa_len + printcolonhex $addr $count + end + end +end + +define showifflags + set $flags = (u_short)$arg0 + set $first = 1 + printf "<" + if ($flags & 0x1) + printf "UP" + set $first = 0 + end + if ($flags & 0x2) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "BROADCAST" + end + if ($flags & 0x4) + printf "DEBUG" + end + if ($flags & 0x8) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "LOOPBACK" + end + if ($flags & 0x10) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "POINTTOPOINT" + end +## if ($flags & 0x20) +## if ($first == 1) +# set $first = 0 +## else +# printf "," +# end +# printf "NOTRAILERS" +# end + if ($flags & 0x40) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "RUNNING" + end + if ($flags & 0x80) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "NOARP" + end + if ($flags & 0x100) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "PROMISC" + end + if ($flags & 0x200) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "ALLMULTI" + end + if ($flags & 0x400) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "OACTIVE" + end + if ($flags & 0x800) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "SIMPLEX" + end + if ($flags & 0x1000) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "LINK0" + end + if ($flags & 0x2000) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "LINK1" + end + if ($flags & 0x4000) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "LINK2-ALTPHYS" + end + if ($flags & 0x8000) + if ($first == 1) + set $first = 0 + else + printf "," + end + printf "MULTICAST" + end + printf ">" +end + +define showifaddrs + set $ifp = (struct ifnet *)$arg0 + set $myifaddr = (struct ifaddr *)$ifp->if_addrhead->tqh_first + set $myi = 0 + while ($myifaddr != 0) + printf "\t%d. %p ", $myi, $myifaddr + showsockaddr $myifaddr->ifa_addr + printf " [%d]\n", $myifaddr->ifa_refcnt + set $myifaddr = $myifaddr->ifa_link->tqe_next + set $myi = $myi + 1 + end +end + +document showifaddrs +Syntax: showifaddrs +| show the (struct ifnet).if_addrhead list of addresses for the given ifp +end + +define ifconfig + set $ifconfig_all = 0 + if ($argc == 1) + set $ifconfig_all = 1 + end + set $ifp = (struct ifnet *)(ifnet_head->tqh_first) + while ($ifp != 0) + printf "%s%d: flags=%hx", $ifp->if_name, $ifp->if_unit, (u_short)$ifp->if_flags + showifflags $ifp->if_flags + printf " index %d", $ifp->if_index + printf " mtu %d\n", $ifp->if_data.ifi_mtu + printf "\t(struct ifnet *)" + showptr $ifp + printf "\n" + if ($ifconfig_all == 1) + showifaddrs $ifp + end + set $ifp = $ifp->if_link->tqe_next + end +end +document ifconfig +Syntax: (gdb) ifconfig +| display ifconfig-like output, and print the (struct ifnet *) pointers for further inspection +end + +set $DLIF_INUSE = 0x1 +set $DLIF_REUSE = 0x2 + +define showifnets + set $all = 0 + if ($argc == 1) + set $all = 1 + end + set $dlifp = (struct dlil_ifnet *)(dlil_ifnet_head->tqh_first) + while ($dlifp != 0) + set $ifp = (struct ifnet *)$dlifp + if ($dlifp->dl_if_flags & $DLIF_REUSE) + printf "*" + end + if ($dlifp->dl_if_flags & $DLIF_INUSE) + printf "%s%d: ", $ifp->if_name, $ifp->if_unit + else + printf "[%s%d]: ", $ifp->if_name, $ifp->if_unit + end + printf "flags=%hx", (u_short)$ifp->if_flags + showifflags $ifp->if_flags + printf " index %d", $ifp->if_index + printf " mtu %d\n", $ifp->if_data.ifi_mtu + printf "\t(struct ifnet *)" + showptr $ifp + printf "\n" + if ($all == 1) + showifaddrs $ifp + end + set $dlifp = $dlifp->dl_if_link->tqe_next + end +end + +document showifnets +Syntax: (gdb) showifnets +| Display ifconfig-like output for all attached and detached interfaces +end + +define _show_unix_domain_socket + set $so = (struct socket *)$arg0 + set $pcb = (struct unpcb *)$so->so_pcb + if $pcb == 0 + printf "unpcb: (null) " + else + printf "unpcb: %p ", $pcb + printf "unp_vnode: %p ", $pcb->unp_vnode + printf "unp_conn: %p ", $pcb->unp_conn + printf "unp_addr: " + showsockaddr_un $pcb->unp_addr + end +end + +define _show_in_port + set $str = (unsigned char *)$arg0 + set $port = *(unsigned short *)$arg0 + + if (((($port & 0xff00) >> 8) == $str[0])) && ((($port & 0x00ff) == $str[1])) + #printf "big endian " + printf ":%d ", $port + else + #printf "little endian " + printf ":%d ", (($port & 0xff00) >> 8) | (($port & 0x00ff) << 8) + end +end + +define _show_in_addr_4in6 + set $ia = (unsigned char *)$arg0 + if $ia + printf "%3u.%03u.%03u.%03u", $ia[0], $ia[1], $ia[2], $ia[3] + end +end + +define _show_in6_addr + set $ia = (unsigned char *)$arg0 + if $ia + printf "%2x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + $ia[0], $ia[1], $ia[2], $ia[3], $ia[4], $ia[5], $ia[6], $ia[7], \ + $ia[8], $ia[9], $ia[10], $ia[11], $ia[12], $ia[13], $ia[14], $ia[15] + end +end + +define _showtcpstate + set $tp = (struct tcpcb *)$arg0 + if $tp + if $tp->t_state == 0 + printf "CLOSED " + end + if $tp->t_state == 1 + printf "LISTEN " + end + if $tp->t_state == 2 + printf "SYN_SENT " + end + if $tp->t_state == 3 + printf "SYN_RCVD " + end + if $tp->t_state == 4 + printf "ESTABLISHED " + end + if $tp->t_state == 5 + printf "CLOSE_WAIT " + end + if $tp->t_state == 6 + printf "FIN_WAIT_1 " + end + if $tp->t_state == 7 + printf "CLOSING " + end + if $tp->t_state == 8 + printf "LAST_ACK " + end + if $tp->t_state == 9 + printf "FIN_WAIT_2 " + end + if $tp->t_state == 10 + printf "TIME_WAIT " + end + end +end + +define _showsockprotocol + set $so = (struct socket *)$arg0 + set $inpcb = (struct inpcb *)$so->so_pcb + + if $so->so_proto->pr_protocol == 6 + printf "TCP " + _showtcpstate $inpcb->inp_ppcb + end + if $so->so_proto->pr_protocol == 17 + printf "UDP " + end + if $so->so_proto->pr_protocol == 1 + printf "ICMP " + end + if $so->so_proto->pr_protocol == 254 + printf "DIVERT " + end + if $so->so_proto->pr_protocol == 255 + printf "RAW " + end +end + +define _show_ipv4_socket + set $so = (struct socket *)$arg0 + set $inpcb = (struct inpcb *)$so->so_pcb + if $inpcb == 0 + printf "inpcb: (null) " + else + printf "inpcb: %p ", $inpcb + + _showsockprotocol $so + + _show_in_addr_4in6 &$inpcb->inp_dependladdr.inp46_local + _show_in_port &$inpcb->inp_lport + printf "-> " + _show_in_addr_4in6 &$inpcb->inp_dependfaddr.inp46_foreign + _show_in_port &$inpcb->inp_fport + end +end + +define _show_ipv6_socket + set $so = (struct socket *)$arg0 + set $pcb = (struct inpcb *)$so->so_pcb + if $pcb == 0 + printf "inpcb: (null) " + else + printf "inpcb: %p ", $pcb + + _showsockprotocol $so + + _show_in6_addr &$pcb->inp_dependladdr.inp6_local + _show_in_port &$pcb->inp_lport + printf "-> " + _show_in6_addr &$pcb->inp_dependfaddr.inp6_foreign + _show_in_port &$pcb->inp_fport + end +end + + +define showsocket + set $so = (struct socket *)$arg0 + if $so == 0 + printf "so: (null) " + else + printf "so: %p ", $so + if $so && $so->so_proto && $so->so_proto->pr_domain + set $domain = (struct domain *) $so->so_proto->pr_domain + + printf "%s ", $domain->dom_name + if $domain->dom_family == 1 + _show_unix_domain_socket $so + end + if $domain->dom_family == 2 + _show_ipv4_socket $so + end + if $domain->dom_family == 30 + _show_ipv6_socket $so + end + end + end + printf "\n" +end +document showsocket +Syntax: (gdb) showsocket +| Routine to print out a socket +end + +define showprocsockets + set $pp = (struct proc *)$arg0 + set $fdp = (struct filedesc *)$pp->p_fd + + set $count = 0 + set $fpp = (struct fileproc **)($fdp->fd_ofiles) + set $fpo = (char)($fdp->fd_ofileflags[0]) + while $count < $fdp->fd_nfiles + if *$fpp + set $fg =(struct fileglob *)((**$fpp)->f_fglob) + if $fg && (($fg)->fg_type == 2) + if $fdp->fd_ofileflags[$count] & 4 + printf "U: " + else + printf " " + end + printf "fd = %d ", $count + if $fg->fg_data + showsocket $fg->fg_data + else + printf "\n" + end + end + end + set $fpp = $fpp + 1 + set $count = $count + 1 + end +end +document showprocsockets +Syntax: (gdb) showprocsockets +| Routine to print out all the open fds +| which are sockets in a process +end + +define showallprocsockets + set $basep = (struct proc *)allproc->lh_first + set $pp = $basep + while $pp + printf "============================================ \n" + showproc $pp + showprocsockets $pp + set $pp = $pp->p_list.le_next + end +end +document showallprocsockets +Syntax: (gdb) showallprocsockets +| Routine to print out all the open fds +| which are sockets +end + +define _print_ntohs + set $port = (unsigned short)$arg0 + set $port = (unsigned short)((($arg0 & 0xff00) >> 8) & 0xff) + set $port |= (unsigned short)(($arg0 & 0xff) << 8) + printf "%5d", $port +end + +set $INPCB_STATE_INUSE=0x1 +set $INPCB_STATE_CACHED=0x2 +set $INPCB_STATE_DEAD=0x3 + +set $INP_RECVOPTS=0x01 +set $INP_RECVRETOPTS=0x02 +set $INP_RECVDSTADDR=0x04 +set $INP_HDRINCL=0x08 +set $INP_HIGHPORT=0x10 +set $INP_LOWPORT=0x20 +set $INP_ANONPORT=0x40 +set $INP_RECVIF=0x80 +set $INP_MTUDISC=0x100 +set $INP_STRIPHDR=0x200 +set $INP_RECV_ANYIF=0x400 +set $INP_INADDR_ANY=0x800 +set $INP_RECVTTL=0x1000 +set $INP_UDP_NOCKSUM=0x2000 +set $IN6P_IPV6_V6ONLY=0x008000 +set $IN6P_PKTINFO=0x010000 +set $IN6P_HOPLIMIT=0x020000 +set $IN6P_HOPOPTS=0x040000 +set $IN6P_DSTOPTS=0x080000 +set $IN6P_RTHDR=0x100000 +set $IN6P_RTHDRDSTOPTS=0x200000 +set $IN6P_AUTOFLOWLABEL=0x800000 +set $IN6P_BINDV6ONLY=0x10000000 + +set $INP_IPV4=0x1 +set $INP_IPV6=0x2 + +set $IPPROTO_TCP=6 +set $IPPROTO_UDP=17 + +define _dump_inpcb + set $pcb = (struct inpcb *)$arg0 + if $kgm_lp64 + printf "%18p", $pcb + else + printf "%10p ", $pcb + end + if $arg1 == $IPPROTO_TCP + printf "tcp" + else + if $arg1 == $IPPROTO_UDP + printf "udp" + else + printf "%2d.", $arg1 + end + end + if ($pcb->inp_vflag & $INP_IPV4) + printf "4 " + end + if ($pcb->inp_vflag & $INP_IPV6) + printf "6 " + end + + if ($pcb->inp_vflag & $INP_IPV4) + printf " " + _show_in_addr &$pcb->inp_dependladdr.inp46_local.ia46_addr4 + else + _show_in6_addr &$pcb->inp_dependladdr.inp6_local + end + printf " " + _print_ntohs $pcb->inp_lport + printf " " + if ($pcb->inp_vflag & $INP_IPV4) + printf " " + _show_in_addr &($pcb->inp_dependfaddr.inp46_foreign.ia46_addr4) + else + _show_in6_addr &($pcb->inp_dependfaddr.inp6_foreign) + end + printf " " + _print_ntohs $pcb->inp_fport + printf " " + + if $arg1 == $IPPROTO_TCP + _showtcpstate $pcb->inp_ppcb + end + +# printf "phd " +# set $phd = $pcb->inp_phd +# while $phd != 0 +# printf " " +# _print_ntohs $phd->phd_port +# set $phd = $phd->phd_hash.le_next +# end +# printf ", " + if ($pcb->inp_flags & $INP_RECVOPTS) + printf "recvopts " + end + if ($pcb->inp_flags & $INP_RECVRETOPTS) + printf "recvretopts " + end + if ($pcb->inp_flags & $INP_RECVDSTADDR) + printf "recvdstaddr " + end + if ($pcb->inp_flags & $INP_HDRINCL) + printf "hdrincl " + end + if ($pcb->inp_flags & $INP_HIGHPORT) + printf "highport " + end + if ($pcb->inp_flags & $INP_LOWPORT) + printf "lowport " + end + if ($pcb->inp_flags & $INP_ANONPORT) + printf "anonport " + end + if ($pcb->inp_flags & $INP_RECVIF) + printf "recvif " + end + if ($pcb->inp_flags & $INP_MTUDISC) + printf "mtudisc " + end + if ($pcb->inp_flags & $INP_STRIPHDR) + printf "striphdr " + end + if ($pcb->inp_flags & $INP_RECV_ANYIF) + printf "recv_anyif " + end + if ($pcb->inp_flags & $INP_INADDR_ANY) + printf "inaddr_any " + end + if ($pcb->inp_flags & $INP_RECVTTL) + printf "recvttl " + end + if ($pcb->inp_flags & $INP_UDP_NOCKSUM) + printf "nocksum " + end + if ($pcb->inp_flags & $IN6P_IPV6_V6ONLY) + printf "v6only " + end + if ($pcb->inp_flags & $IN6P_PKTINFO) + printf "pktinfo " + end + if ($pcb->inp_flags & $IN6P_HOPLIMIT) + printf "hoplimit " + end + if ($pcb->inp_flags & $IN6P_HOPOPTS) + printf "hopopts " + end + if ($pcb->inp_flags & $IN6P_DSTOPTS) + printf "dstopts " + end + if ($pcb->inp_flags & $IN6P_RTHDR) + printf "rthdr " + end + if ($pcb->inp_flags & $IN6P_RTHDRDSTOPTS) + printf "rthdrdstopts " + end + if ($pcb->inp_flags & $IN6P_AUTOFLOWLABEL) + printf "autoflowlabel " + end + if ($pcb->inp_flags & $IN6P_BINDV6ONLY) + printf "bindv6only " + end + set $so = (struct socket *)$pcb->inp_socket + if $so != 0 + printf "[so=%p s=%ld r=%ld usecnt=%ld] ", $so, $so->so_snd.sb_cc, \ + $so->so_rcv.sb_cc, $so->so_usecount + end + if ($pcb->inp_state == 0 || $pcb->inp_state == $INPCB_STATE_INUSE) + printf "inuse, " + else + if ($pcb->inp_state == $INPCB_STATE_CACHED) + printf "cached, " + else + if ($pcb->inp_state == $INPCB_STATE_DEAD) + printf "dead, " + else + printf "unknown (%d), ", $pcb->inp_state + end + end + end +end + +define _dump_inpcbport + set $ppcb = (struct inpcbport *)$arg0 + printf "%p: lport ", $ppcb + _print_ntohs $ppcb->phd_port +end + +set $UDBHASHSIZE=16 + +define _dump_pcbinfo + set $snd_cc = 0 + set $snd_buf = (unsigned int)0 + set $rcv_cc = 0 + set $rcv_buf = (unsigned int)0 + set $pcbseen = 0 + set $pcbi = (struct inpcbinfo *)$arg0 + printf "lastport %d lastlow %d lasthi %d\n", \ + $pcbi->lastport, $pcbi->lastlow, $pcbi->lasthi + printf "active pcb count is %d\n", $pcbi->ipi_count + set $hashsize = $pcbi->hashmask + 1 + printf "hash size is %d\n", $hashsize + printf "hash base %p has the following inpcb(s):\n", $pcbi->hashbase + if $kgm_lp64 + printf "pcb prot source address port destination address port\n" + printf "------------------ ---- --------------------------------------- ----- --------------------------------------- -----\n" + else + printf "pcb prot source address port destination address port\n" + printf "---------- ---- --------------------------------------- ----- --------------------------------------- -----\n" + end + set $i = 0 + set $hashbase = $pcbi->hashbase + set $head = *(uintptr_t *)$hashbase + while $i < $hashsize + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + set $pcbseen += 1 + _dump_inpcb $pcb0 $arg1 + set $so = (struct socket *)$pcb->inp_socket + if $so != 0 + set $snd_cc += $so->so_snd.sb_cc + set $mp = $so->so_snd.sb_mb + while $mp + set $snd_buf += 256 + if ($mp->m_hdr.mh_flags & 0x01) + set $snd_buf += $mp->M_dat.MH.MH_dat.MH_ext.ext_size + end + set $mp = $mp->m_hdr.mh_next + end + set $rcv_cc += $so->so_rcv.sb_cc + set $mp = $so->so_rcv.sb_mb + while $mp + set $rcv_buf += 256 + if ($mp->m_hdr.mh_flags & 0x01) + set $rcv_buf += $mp->M_dat.MH.MH_dat.MH_ext.ext_size + end + set $mp = $mp->m_hdr.mh_next + end + end + set $pcb0 = $pcb0->inp_hash.le_next + printf "\n" + end + end + set $i += 1 + set $hashbase += 1 + set $head = *(uintptr_t *)$hashbase + end + printf "total seen %ld snd_cc %ld rcv_cc %ld\n", $pcbseen, $snd_cc, $rcv_cc + printf "total snd_buf %u rcv_buf %u \n", (unsigned int)$snd_buf, (unsigned int)$rcv_buf + printf "port hash base is %p\n", $pcbi->porthashbase + set $i = 0 + set $hashbase = $pcbi->porthashbase + set $head = *(uintptr_t *)$hashbase + while $i < $hashsize + if $head != 0 + set $pcb0 = (struct inpcbport *)$head + while $pcb0 != 0 + printf "\t" + _dump_inpcbport $pcb0 + printf "\n" + set $pcb0 = $pcb0->phd_hash.le_next + end + end + set $i += 1 + set $hashbase += 1 + set $head = *(uintptr_t *)$hashbase + end +end + +set $N_TIME_WAIT_SLOTS=128 + +define show_tcp_timewaitslots + set $slot = -1 + set $all = 0 + if $argc == 1 + if (int)$arg0 == -1 + set $all = 1 + else + set $slot = (int)$arg0 + end + end + printf "time wait slot size %d cur_tw_slot %ld\n", $N_TIME_WAIT_SLOTS, cur_tw_slot + set $i = 0 + while $i < $N_TIME_WAIT_SLOTS + set $perslot = 0 + set $head = (uintptr_t *)time_wait_slots[$i] + if $i == $slot || $slot == -1 + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + set $perslot += 1 + set $pcb0 = $pcb0->inp_list.le_next + end + end + printf " slot %ld count %ld\n", $i, $perslot + end + if $all || $i == $slot + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + printf "\t" + _dump_inpcb $pcb0 $IPPROTO_TCP + printf "\n" + set $pcb0 = $pcb0->inp_list.le_next + end + end + end + set $i += 1 + end +end +document show_tcp_timewaitslots +Syntax: (gdb) show_tcp_timewaitslots +| Print the list of TCP protocol control block in the TIMEWAIT state +| Pass -1 to see the list of PCB for each slot +| Pass a slot number to see information for that slot with the list of PCB +end + +define show_tcp_pcbinfo + _dump_pcbinfo &tcbinfo $IPPROTO_TCP +end +document show_tcp_pcbinfo +Syntax: (gdb) show_tcp_pcbinfo +| Print the list of TCP protocol control block information +end + + +define show_udp_pcbinfo + _dump_pcbinfo &udbinfo $IPPROTO_UDP +end +document show_udp_pcbinfo +Syntax: (gdb) show_udp_pcbinfo +| Print the list of UDP protocol control block information +end + +define showbpfdtab + set $myi = 0 + while ($myi < bpf_dtab_size) + if (bpf_dtab[$myi] != 0) + printf "Address 0x%x, bd_next 0x%x\n", bpf_dtab[$myi], bpf_dtab[$myi]->bd_next + print *bpf_dtab[$myi] + end + set $myi = $myi + 1 + end +end + +define printvnodepathint_recur + if $arg0 != 0 + if ($arg0->v_flag & 0x000001) && ($arg0->v_mount != 0) + if $arg0->v_mount->mnt_vnodecovered != 0 + printvnodepathint_recur $arg0->v_mount->mnt_vnodecovered $arg0->v_mount->mnt_vnodecovered->v_name + end + else + printvnodepathint_recur $arg0->v_parent $arg0->v_parent->v_name + printf "/%s", $arg1 + end + end +end + +define showvnodepath + set $vp = (struct vnode *)$arg0 + if $vp != 0 + if ($vp->v_flag & 0x000001) && ($vp->v_mount != 0) && ($vp->v_mount->mnt_flag & 0x00004000) + printf "/" + else + printvnodepathint_recur $vp $vp->v_name + end + end + printf "\n" +end + +document showvnodepath +Syntax: (gdb) showvnodepath +| Prints the path for a vnode +end + +define showallvols + printf "volume " + showptrhdrpad + printf " mnt_data " + showptrhdrpad + printf " mnt_devvp " + showptrhdrpad + printf " typename mountpoint\n" + set $kgm_vol = (mount_t) mountlist.tqh_first + while $kgm_vol + showptr $kgm_vol + printf " " + showptr $kgm_vol->mnt_data + printf " " + showptr $kgm_vol->mnt_devvp + printf " " + if ($kgm_vol->mnt_vtable->vfc_name[0] == 'h') && \ + ($kgm_vol->mnt_vtable->vfc_name[1] == 'f') && \ + ($kgm_vol->mnt_vtable->vfc_name[2] == 's') && \ + ($kgm_vol->mnt_vtable->vfc_name[3] == '\0') + set $kgm_hfsmount = \ + (struct hfsmount *) $kgm_vol->mnt_data + if $kgm_hfsmount->hfs_freezing_proc != 0 + printf "FROZEN hfs " + else + printf "hfs " + end + else + printf "%-10s ", $kgm_vol->mnt_vtable->vfc_name + end + printf "%s\n", $kgm_vol->mnt_vfsstat.f_mntonname + + set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next + end +end + +document showallvols +Syntax: (gdb) showallvols +| Display a summary of mounted volumes +end + +define showvnodeheader + printf "vnode " + showptrhdrpad + printf " usecount iocount v_data " + showptrhdrpad + printf " vtype parent " + showptrhdrpad + printf " name\n" +end + +define showvnodeint + set $kgm_vnode = (vnode_t) $arg0 + showptr $kgm_vnode + printf " %8d ", $kgm_vnode->v_usecount + printf "%7d ", $kgm_vnode->v_iocount +# print information about clean/dirty blocks? + showptr $kgm_vnode->v_data + printf " " + # print the vtype, using the enum tag + set $kgm_vtype = $kgm_vnode->v_type + if $kgm_vtype == VNON + printf "VNON " + end + if $kgm_vtype == VREG + printf "VREG " + end + if $kgm_vtype == VDIR + printf "VDIR " + end + if $kgm_vtype == VBLK + printf "VBLK " + end + if $kgm_vtype == VCHR + printf "VCHR " + end + if $kgm_vtype == VLNK + printf "VLNK " + end + if $kgm_vtype == VSOCK + printf "VSOCK " + end + if $kgm_vtype == VFIFO + printf "VFIFO " + end + if $kgm_vtype == VBAD + printf "VBAD " + end + if ($kgm_vtype < VNON) || ($kgm_vtype > VBAD) + printf "%5d ", $kgm_vtype + end + + showptr $kgm_vnode->v_parent + printf " " + if ($kgm_vnode->v_name != 0) + printf "%s\n", $kgm_vnode->v_name + else + # If this is HFS vnode, get name from the cnode + if ($kgm_vnode->v_tag == 16) + set $kgm_cnode = (struct cnode *)$kgm_vnode->v_data + printf "hfs: %s\n", (char *)$kgm_cnode->c_desc->cd_nameptr + else + printf "\n" + end + end +end + +define showvnode + showvnodeheader + showvnodeint $arg0 +end + +document showvnode +Syntax: (gdb) showvnode +| Display info about one vnode +end + +define showvolvnodes + showvnodeheader + set $kgm_vol = (mount_t) $arg0 + set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first + while $kgm_vnode + showvnodeint $kgm_vnode + set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next + end +end + +document showvolvnodes +Syntax: (gdb) showvolvnodes +| Display info about all vnodes of a given mount_t +end + +define showvolbusyvnodes + showvnodeheader + set $kgm_vol = (mount_t) $arg0 + set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first + while $kgm_vnode + if $kgm_vnode->v_iocount != 0 + showvnodeint $kgm_vnode + end + set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next + end +end + +document showvolbusyvnodes +Syntax: (gdb) showvolbusyvnodes +| Display info about busy (iocount!=0) vnodes of a given mount_t +end + +define showallbusyvnodes + showvnodeheader + set $kgm_vol = (mount_t) mountlist.tqh_first + while $kgm_vol + set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first + while $kgm_vnode + if $kgm_vnode->v_iocount != 0 + showvnodeint $kgm_vnode + end + set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next + end + set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next + end +end + +document showallbusyvnodes +Syntax: (gdb) showallbusyvnodes +| Display info about all busy (iocount!=0) vnodes +end + +define showallvnodes + showvnodeheader + set $kgm_vol = (mount_t) mountlist.tqh_first + while $kgm_vol + set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first + while $kgm_vnode + showvnodeint $kgm_vnode + set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next + end + set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next + end +end + +document showallvnodes +Syntax: (gdb) showallvnodes +| Display info about all vnodes +end + +define _showvnodelockheader + printf "* type W held by lock type start end\n" + printf "- ----- - ------------- --------- ------------------ ------------------\n" +end + +define _showvnodelock + set $kgm_svl_lock = ((struct lockf *)$arg0) + + # decode flags + set $kgm_svl_flags = $kgm_svl_lock->lf_flags + set $kgm_svl_type = $kgm_svl_lock->lf_type + if ($kgm_svl_flags & 0x20) + printf "flock" + end + if ($kgm_svl_flags & 0x40) + printf "posix" + end + if ($kgm_svl_flags & 0x80) + printf "prov " + end + if ($kgm_svl_flags & 0x10) + printf " W " + else + printf " . " + end + + # POSIX file vs. advisory range locks + if ($kgm_svl_flags & 0x40) + set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id + printf "PID %8d ", $kgm_svl_proc->p_pid + else + printf "ID 0x%08x ", $kgm_svl_lock->lf_id + end + + # lock type + if ($kgm_svl_type == 1) + printf "shared " + else + if ($kgm_svl_type == 3) + printf "exclusive " + else + if ($kgm_svl_type == 2) + printf "unlock " + else + printf "unknown " + end + end + end + + # start and stop + printf "0x%016x..", $kgm_svl_lock->lf_start + printf "0x%016x ", $kgm_svl_lock->lf_end + printf "\n" +end +# Body of showvnodelocks, not including header +define _showvnodelocks + set $kgm_svl_vnode = ((vnode_t)$arg0) + set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf + while ($kgm_svl_lockiter != 0) + # locks that are held + printf "H " + _showvnodelock $kgm_svl_lockiter + + # and any locks blocked by them + set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first + while ($kgm_svl_blocker != 0) + printf "> " + _showvnodelock $kgm_svl_blocker + set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next + end + + # and on to the next one... + set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next + end +end + + +define showvnodelocks + if ($argc == 1) + _showvnodelockheader + _showvnodelocks $arg0 + else + printf "| Usage:\n|\n" + help showvnodelocks + end +end + +document showvnodelocks +Syntax: (gdb) showvnodelocks +| Given a vnodet pointer, display the list of advisory record locks for the +| referenced pvnodes +end + +define showbootargs + printf "%s\n", (char*)((boot_args*)PE_state.bootArgs).CommandLine +end + +document showbootargs +Syntax: showbootargs +| Display boot arguments passed to the target kernel +end + +define showbootermemorymap + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_voffset = 0 + else + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_voffset = 0xFFFFFF8000000000ULL + else + echo showbootermemorymap not supported on this architecture + end + end + + set $kgm_boot_args = kernelBootArgs + set $kgm_msize = kernelBootArgs->MemoryMapDescriptorSize + set $kgm_mcount = kernelBootArgs->MemoryMapSize / $kgm_msize + set $kgm_i = 0 + + printf "Type Physical Start Number of Pages Virtual Start Attributes\n" + while $kgm_i < $kgm_mcount + set $kgm_mptr = (EfiMemoryRange *)((unsigned long)kernelBootArgs->MemoryMap + $kgm_voffset + $kgm_i * $kgm_msize) +# p/x *$kgm_mptr + if $kgm_mptr->Type == 0 + printf "Reserved " + end + if $kgm_mptr->Type == 1 + printf "LoaderCode" + end + if $kgm_mptr->Type == 2 + printf "LoaderData" + end + if $kgm_mptr->Type == 3 + printf "BS_code " + end + if $kgm_mptr->Type == 4 + printf "BS_data " + end + if $kgm_mptr->Type == 5 + printf "RT_code " + end + if $kgm_mptr->Type == 6 + printf "RT_data " + end + if $kgm_mptr->Type == 7 + printf "Convention" + end + if $kgm_mptr->Type == 8 + printf "Unusable " + end + if $kgm_mptr->Type == 9 + printf "ACPI_recl " + end + if $kgm_mptr->Type == 10 + printf "ACPI_NVS " + end + if $kgm_mptr->Type == 11 + printf "MemMapIO " + end + if $kgm_mptr->Type == 12 + printf "MemPortIO " + end + if $kgm_mptr->Type == 13 + printf "PAL_code " + end + if $kgm_mptr->Type > 13 + printf "UNKNOWN " + end + + printf " %016llx %016llx", $kgm_mptr->PhysicalStart, $kgm_mptr->NumberOfPages + if $kgm_mptr->VirtualStart != 0 + printf " %016llx", $kgm_mptr->VirtualStart + else + printf " " + end + printf " %016llx\n", $kgm_mptr->Attribute + set $kgm_i = $kgm_i + 1 + end +end + +document showbootermemorymap +Syntax: (gdb) showbootermemorymap +| Prints out the phys memory map from kernelBootArgs +end + + +define showstacksaftertask + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)$arg0 + set $kgm_taskp = (struct task *)$kgm_taskp->tasks.next + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + showactheader + if ($decode_wait_events > 0) + showactint $kgm_actp 1 + else + showactint $kgm_actp 2 + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showstacksaftertask +Syntax: (gdb) showstacksaftertask +| Routine to print out all stacks (as in showallstacks) starting after a given task +| Useful if that gdb refuses to print a certain task's stack. +end + +define showpmworkqueueint + set $kgm_pm_workqueue = (IOPMWorkQueue *)$arg0 + set $kgm_pm_wq = &($kgm_pm_workqueue->fWorkQueue) + set $kgm_pm_wqe = (IOServicePM *)$kgm_pm_wq->next + while ((queue_entry_t) $kgm_pm_wqe != (queue_entry_t) $kgm_pm_wq) + printf "service " + showptrhdrpad + printf " ps ms wr name\n" + showptr $kgm_pm_wqe->Owner + printf " " + printf "%02d ", $kgm_pm_wqe->CurrentPowerState + printf "%02d ", $kgm_pm_wqe->MachineState + printf "%02d ", $kgm_pm_wqe->WaitReason + printf "%s\n", $kgm_pm_wqe->Name + printf "request " + showptrhdrpad + printf " type next " + showptrhdrpad + printf " root " + showptrhdrpad + printf " work_wait free_wait\n" + set $kgm_pm_rq = &($kgm_pm_wqe->RequestHead) + set $kgm_pm_rqe = (IOPMRequest *)$kgm_pm_rq->next + while ((queue_entry_t) $kgm_pm_rqe != (queue_entry_t) $kgm_pm_rq) + showptr $kgm_pm_rqe + printf " 0x%02x ", $kgm_pm_rqe->fType + showptr $kgm_pm_rqe->fRequestNext + printf " " + showptr $kgm_pm_rqe->fRequestRoot + printf " 0x%08x 0x%08x\n", $kgm_pm_rqe->fWorkWaitCount, $kgm_pm_rqe->fFreeWaitCount + showptrhdrpad + printf " args " + showptr $kgm_pm_rqe->fArg0 + printf " " + showptr $kgm_pm_rqe->fArg1 + printf " " + showptr $kgm_pm_rqe->fArg2 + printf "\n" + set $kgm_pm_rqe = (IOPMRequest *)$kgm_pm_rqe->fCommandChain.next + end + printf "\n" + set $kgm_pm_wqe = (IOServicePM *)$kgm_pm_wqe->WorkChain.next + end +end + +define showpmworkqueue + printf "IOPMWorkQueue " + showptr gIOPMWorkQueue + printf " length " + printf "%u", gIOPMWorkQueue->fQueueLength + printf "\n" + if (gIOPMWorkQueue->fQueueLength > 0) + showpmworkqueueint gIOPMWorkQueue + end +end + +document showpmworkqueue +Syntax: (gdb) showpmworkqueue +| Display the IOPMWorkQueue object +end + +define showioservicepm + set $kgm_iopmpriv = (IOServicePM *)$arg0 + printf "{ " + printf "MachineState = %d (", $kgm_iopmpriv->MachineState + if ( $kgm_iopmpriv->MachineState == 0 ) + printf "kIOPM_Finished" + else + if ( $kgm_iopmpriv->MachineState == 1 ) + printf "kIOPM_OurChangeTellClientsPowerDown" + else + if ( $kgm_iopmpriv->MachineState == 2 ) + printf "kIOPM_OurChangeTellPriorityClientsPowerDown" + else + if ( $kgm_iopmpriv->MachineState == 3 ) + printf "kIOPM_OurChangeNotifyInterestedDriversWillChange" + else + if ( $kgm_iopmpriv->MachineState == 4 ) + printf "kIOPM_OurChangeSetPowerState" + else + if ( $kgm_iopmpriv->MachineState == 5 ) + printf "kIOPM_OurChangeWaitForPowerSettle" + else + if ( $kgm_iopmpriv->MachineState == 6 ) + printf "kIOPM_OurChangeNotifyInterestedDriversDidChange" + else + if ( $kgm_iopmpriv->MachineState == 7 ) + printf "kIOPM_OurChangeTellCapabilityDidChange" + else + if ( $kgm_iopmpriv->MachineState == 8 ) + printf "kIOPM_OurChangeFinish" + else + if ( $kgm_iopmpriv->MachineState == 9 ) + printf "Unused_MachineState_9" + else + if ( $kgm_iopmpriv->MachineState == 10 ) + printf "kIOPM_ParentChangeTellPriorityClientsPowerDown" + else + if ( $kgm_iopmpriv->MachineState == 11 ) + printf "kIOPM_ParentChangeNotifyInterestedDriversWillChange" + else + if ( $kgm_iopmpriv->MachineState == 12 ) + printf "kIOPM_ParentChangeSetPowerState" + else + if ( $kgm_iopmpriv->MachineState == 13 ) + printf "kIOPM_ParentChangeWaitForPowerSettle" + else + if ( $kgm_iopmpriv->MachineState == 14) + printf "kIOPM_ParentChangeNotifyInterestedDriversDidChange" + else + if ( $kgm_iopmpriv->MachineState == 15) + printf "kIOPM_ParentChangeTellCapabilityDidChange" + else + if ( $kgm_iopmpriv->MachineState == 16) + printf "kIOPM_ParentChangeAcknowledgePowerChange" + else + if ( $kgm_iopmpriv->MachineState == 17) + printf "kIOPM_NotifyChildrenStart" + else + if ( $kgm_iopmpriv->MachineState == 18) + printf "kIOPM_NotifyChildrenOrdered" + else + if ( $kgm_iopmpriv->MachineState == 19) + printf "kIOPM_NotifyChildrenDelayed" + else + if ( $kgm_iopmpriv->MachineState == 20) + printf "kIOPM_SyncTellClientsPowerDown" + else + if ( $kgm_iopmpriv->MachineState == 21) + printf "kIOPM_SyncTellPriorityClientsPowerDown" + else + if ( $kgm_iopmpriv->MachineState == 22) + printf "kIOPM_SyncNotifyWillChange" + else + if ( $kgm_iopmpriv->MachineState == 23) + printf "kIOPM_SyncNotifyDidChange" + else + if ( $kgm_iopmpriv->MachineState == 24) + printf "kIOPM_SyncTellCapabilityDidChange" + else + if ( $kgm_iopmpriv->MachineState == 25) + printf "kIOPM_SyncFinish" + else + if ( $kgm_iopmpriv->MachineState == 26) + printf "kIOPM_TellCapabilityChangeDone" + else + if ( $kgm_iopmpriv->MachineState == 27) + printf "kIOPM_DriverThreadCallDone" + else + printf "Unknown_MachineState" + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + printf "), " + + if ( $kgm_iopmpriv->MachineState != 20 ) + printf "DriverTimer = %d, ",(unsigned int)$kgm_iopmpriv->DriverTimer + printf "SettleTime = %d, ",(unsigned int)$kgm_iopmpriv->SettleTimeUS + printf "HeadNoteFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteChangeFlags + printf "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks + end + + if ( $kgm_iopmpriv->DeviceOverrideEnabled != 0 ) + printf"DeviceOverrides, " + end + + printf "DeviceDesire = %d, ",(unsigned int)$kgm_iopmpriv->DeviceDesire + printf "DesiredPowerState = %d, ",(unsigned int)$kgm_iopmpriv->DesiredPowerState + printf "PreviousRequest = %d }\n",(unsigned int)$kgm_iopmpriv->PreviousRequestPowerFlags +end + +document showioservicepm +Syntax: (gdb) showioservicepm +| Routine to dump the IOServicePM object +end + +define showregistryentryrecursepmstate + set $kgm_re = (IOService *)$arg1 + set $kgm$arg0_stack = (unsigned long long) $arg2 + + if ($arg3) + set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth) + end + + dictget $kgm_re->fRegistryTable $kgm_childkey + set $kgm$arg0_child_array = (OSArray *) $kgm_result + + if ($kgm$arg0_child_array) + set $kgm$arg0_child_count = $kgm$arg0_child_array->count + else + set $kgm$arg0_child_count = 0 + end + + if ($kgm$arg0_child_count) + set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth) + end + + indent $kgm_reg_depth $kgm$arg0_stack + printf "+-o " + + dictget $kgm_re->fRegistryTable $kgm_namekey + if ($kgm_result == 0) + dictget $kgm_re->fRegistryTable gIONameKey + end + if ($kgm_result == 0) + dictget $kgm_re->fPropertyTable gIOClassKey + end + + if ($kgm_result != 0) + printf "%s <%p>", ((OSString *)$kgm_result)->string, $kgm_re + else + if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name) + printf "%s <", ((IOService*)$kgm_re)->pwrMgt->Name + showptr $kgm_re + printf ">" + else + printf "?? <" + showptr $kgm_re + printf ">" + end + end + + if (((IOService*)$kgm_re)->pwrMgt ) + printf " Current Power State: %ld ", ((IOService*)$kgm_re)->pwrMgt->CurrentPowerState + #printf " Mach State %ld", ((IOService*)$kgm_re)->pwrMgt->MachineState + showioservicepm ((IOService*)$kgm_re)->pwrMgt + end + printf "\n" + + + # recurse + if ($kgm$arg0_child_count != 0) + + set $kgm_reg_depth = $kgm_reg_depth + 1 + set $kgm$arg0_child_idx = 0 + + while ($kgm$arg0_child_idx < $kgm$arg0_child_count) + set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] + set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + showregistryentryrecursepmstate _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib + end + + set $kgm_reg_depth = $kgm_reg_depth - 1 + end +end + +define showregistryentryintpmstate + if !$kgm_reg_plane + set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane + end + + if !$kgm_reg_plane + printf "Please load kgmacros after KDP attaching to the target.\n" + else + set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + showregistryentryrecursepmstate _ $arg0 0 0 + end +end + +define showregistrypmstate +# setregistryplane gIOPowerPlane + set $kgm_reg_depth = 0 + set $kgm_show_props = 1 + showregistryentryintpmstate gRegistryRoot +end + +document showregistrypmstate +Syntax: (gdb) showregistrypmstate +| Routine to dump the PM state of each IOPower registry entry +end + +define showstacksafterthread + set $kgm_head_taskp = &tasks + set $kgm_actp = (struct thread *)$arg0 + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + set $kgm_taskp = (struct task *)$kgm_actp->task + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + if $kgm_actp == 0 + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + end + while $kgm_actp != $kgm_head_actp + showactheader + if ($decode_wait_events > 0) + showactint $kgm_actp 1 + else + showactint $kgm_actp 2 + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + set $kgm_actp = 0 + end +end + +document showstacksafterthread +Syntax: (gdb) showstacksafterthread +| Routine to print out all stacks (as in showallstacks) starting after a given thread +| Useful if that gdb refuses to print a certain task's stack. +end + +define kdp-reenter + set kdp_reentry_deadline = ((unsigned) $arg0)*1000 + continue +end + +document kdp-reenter +Syntax: (gdb) kdp-reenter +| Schedules reentry into the debugger after seconds, and resumes +| the target system. +end + +define _if_present + if (!$arg0) + printf " not" + end + printf " present" +end + +define showMCAstate + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "Not available for current architecture.\n" + else + printf "MCA" + _if_present mca_MCA_present + printf ", control MSR" + _if_present mca_control_MSR_present + printf ", threshold status" + _if_present mca_threshold_status_present + printf "\n%d error banks, ", mca_error_bank_count + printf "family code 0x%x, ", mca_family + printf "machine-check dump state: %d\n", mca_dump_state + set $kgm_cpu = 0 + while cpu_data_ptr[$kgm_cpu] != 0 + set $kgm_mcp = cpu_data_ptr[$kgm_cpu]->cpu_mca_state + if $kgm_mcp + printf "CPU %d:", $kgm_cpu + printf " mca_mcg_ctl: 0x%016llx", $kgm_mcp->mca_mcg_ctl + printf " mca_mcg_status: 0x%016llx\n", $kgm_mcp->mca_mcg_status.u64 + printf "bank " + printf "mca_mci_ctl " + printf "mca_mci_status " + printf "mca_mci_addr " + printf "mca_mci_misc\n" + set $kgm_bank = 0 + while $kgm_bank < mca_error_bank_count + set $kgm_bp = &$kgm_mcp->mca_error_bank[$kgm_bank] + printf " %2d:", $kgm_bank + printf " 0x%016llx", $kgm_bp->mca_mci_ctl + printf " 0x%016llx", $kgm_bp->mca_mci_status.u64 + printf " 0x%016llx", $kgm_bp->mca_mci_addr + printf " 0x%016llx\n", $kgm_bp->mca_mci_misc + set $kgm_bank = $kgm_bank + 1 + end + end + set $kgm_cpu = $kgm_cpu + 1 + end + end +end + +document showMCAstate +Syntax: showMCAstate +| Print machine-check register state after MC exception. +end + +define _pt_step + # + # Step to lower-level page table and print attributes + # $kgm_pt_paddr: current page table entry physical address + # $kgm_pt_index: current page table entry index (0..511) + # returns + # $kgm_pt_paddr: next level page table entry physical address + # or null if invalid + # $kgm_pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk + # should be aborted + # $kgm_pt_large: 1 if kgm_pt_paddr is a page frame address + # of a large page and not another page table entry + # For $kgm_pt_verbose = 0: print nothing + # 1: print basic information + # 2: print basic information and hex table dump + # + set $kgm_entryp = $kgm_pt_paddr + 8*$kgm_pt_index + readphysint $kgm_entryp 64 $kgm_lcpu_self + set $entry = $kgm_readphysint_result + if $kgm_pt_verbose >= 3 + set $kgm_pte_loop = 0 + while $kgm_pte_loop < 512 + set $kgm_pt_paddr_tmp = $kgm_pt_paddr + $kgm_pte_loop*8 + readphys64 $kgm_pt_paddr_tmp + set $kgm_pte_loop = $kgm_pte_loop + 1 + end + end + set $kgm_paddr_mask = ~((0xfffULL<<52) | 0xfffULL) + set $kgm_paddr_largemask = ~((0xfffULL<<52) | 0x1fffffULL) + if $kgm_pt_verbose < 2 + if $entry & (0x1 << 0) + set $kgm_pt_valid = 1 + if $entry & (0x1 << 7) + set $kgm_pt_large = 1 + set $kgm_pt_paddr = $entry & $kgm_paddr_largemask + else + set $kgm_pt_large = 0 + set $kgm_pt_paddr = $entry & $kgm_paddr_mask + end + else + set $kgm_pt_valid = 0 + set $kgm_pt_large = 0 + set $kgm_pt_paddr = 0 + end + else + printf "0x%016llx:\n\t0x%016llx\n\t", $kgm_entryp, $entry + if $entry & (0x1 << 0) + printf "valid" + set $kgm_pt_paddr = $entry & $kgm_paddr_mask + set $kgm_pt_valid = 1 + else + printf "invalid" + set $kgm_pt_paddr = 0 + set $kgm_pt_valid = 0 + # stop decoding other bits + set $entry = 0 + end + if $entry & (0x1 << 1) + printf " writeable" + else + printf " read-only" + end + if $entry & (0x1 << 2) + printf " user" + else + printf " supervisor" + end + if $entry & (0x1 << 3) + printf " PWT" + end + if $entry & (0x1 << 4) + printf " PCD" + end + if $entry & (0x1 << 5) + printf " accessed" + end + if $entry & (0x1 << 6) + printf " dirty" + end + if $entry & (0x1 << 7) + printf " large" + set $kgm_pt_large = 1 + else + set $kgm_pt_large = 0 + end + if $entry & (0x1 << 8) + printf " global" + end + if $entry & (0x3 << 9) + printf " avail:0x%x", ($entry >> 9) & 0x3 + end + if $entry & (0x1ULL << 63) + printf " noexec" + end + printf "\n" + end +end + +define _pml4_walk + set $kgm_pt_paddr = $arg0 + set $kgm_vaddr = $arg1 + set $kgm_pt_valid = $kgm_pt_paddr != 0 + set $kgm_pt_large = 0 + set $kgm_pframe_offset = 0 + if $kgm_pt_valid && cpu_64bit + # Look up bits 47:39 of the linear address in PML4T + set $kgm_pt_index = ($kgm_vaddr >> 39) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x7fffffffffULL + if $kgm_pt_verbose >= 2 + printf "pml4 (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid + # Look up bits 38:30 of the linear address in PDPT + set $kgm_pt_index = ($kgm_vaddr >> 30) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x3fffffffULL + if $kgm_pt_verbose >= 2 + printf "pdpt (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid && !$kgm_pt_large + # Look up bits 29:21 of the linear address in PDT + set $kgm_pt_index = ($kgm_vaddr >> 21) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x1fffffULL + if $kgm_pt_verbose >= 2 + printf "pdt (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid && !$kgm_pt_large + # Look up bits 20:21 of the linear address in PT + set $kgm_pt_index = ($kgm_vaddr >> 12) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0xfffULL + if $kgm_pt_verbose >= 2 + printf "pt (index %d):\n", $kgm_pt_index + end + _pt_step + end + + if $kgm_pt_valid + set $kgm_paddr = $kgm_pt_paddr + $kgm_pframe_offset + set $kgm_paddr_isvalid = 1 + else + set $kgm_paddr = 0 + set $kgm_paddr_isvalid = 0 + end + + if $kgm_pt_verbose >= 1 + if $kgm_paddr_isvalid + readphysint $kgm_paddr 32 $kgm_lcpu_self + set $kgm_value = $kgm_readphysint_result + printf "phys 0x%016llx: 0x%08x\n", $kgm_paddr, $kgm_value + else + printf "(no translation)\n" + end + end +end + +define _pmap_walk_x86 + set $kgm_pmap = (pmap_t) $arg0 + _pml4_walk $kgm_pmap->pm_cr3 $arg1 +end + +define _pmap_walk_arm_level1_section + set $kgm_tte_p = $arg0 + set $kgm_tte = *$kgm_tte_p + set $kgm_vaddr = $arg1 + + # Supersection or just section? + if (($kgm_tte & 0x00040000) == 0x00040000) + set $kgm_paddr = ($kgm_tte & 0xFF000000) | ($kgm_vaddr & 0x00FFFFFF) + set $kgm_paddr_isvalid = 1 + else + set $kgm_paddr = ($kgm_tte & 0xFFF00000) | ($kgm_vaddr & 0x000FFFFF) + set $kgm_paddr_isvalid = 1 + end + + if $kgm_pt_verbose >= 2 + printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_tte_p, $kgm_tte + + # bit [1:0] evaluated in _pmap_walk_arm + + # B bit 2 + set $kgm_b_bit = (($kgm_tte & 0x00000004) >> 2) + + # C bit 3 + set $kgm_c_bit = (($kgm_tte & 0x00000008) >> 3) + + # XN bit 4 + if ($kgm_tte & 0x00000010) + printf "no-execute" + else + printf "execute" + end + + # Domain bit [8:5] if not supersection + if (($kgm_tte & 0x00040000) == 0x00000000) + printf " domain(%d)", (($kgm_tte & 0x000001e0) >> 5) + end + + # IMP bit 9 + printf " imp(%d)", (($kgm_tte & 0x00000200) >> 9) + + # AP bit 15 and [11:10], merged to a single 3-bit value + set $kgm_access = (($kgm_tte & 0x00000c00) >> 10) | (($kgm_tte & 0x00008000) >> 13) + if ($kgm_access == 0x0) + printf " noaccess" + end + if ($kgm_access == 0x1) + printf " supervisor(readwrite) user(noaccess)" + end + if ($kgm_access == 0x2) + printf " supervisor(readwrite) user(readonly)" + end + if ($kgm_access == 0x3) + printf " supervisor(readwrite) user(readwrite)" + end + if ($kgm_access == 0x4) + printf " noaccess(reserved)" + end + if ($kgm_access == 0x5) + printf " supervisor(readonly) user(noaccess)" + end + if ($kgm_access == 0x6) + printf " supervisor(readonly) user(readonly)" + end + if ($kgm_access == 0x7) + printf " supervisor(readonly) user(readonly)" + end + + # TEX bit [14:12] + set $kgm_tex_bits = (($kgm_tte & 0x00007000) >> 12) + + # Print TEX, C, B all together + printf " TEX:C:B(%d%d%d:%d:%d)", ($kgm_tex_bits & 0x4 ? 1 : 0), ($kgm_tex_bits & 0x2 ? 1 : 0), ($kgm_tex_bits & 0x1 ? 1 : 0), $kgm_c_bit, $kgm_b_bit + + # S bit 16 + if ($kgm_tte & 0x00010000) + printf " shareable" + else + printf " not-shareable" + end + + # nG bit 17 + if ($kgm_tte & 0x00020000) + printf " not-global" + else + printf " global" + end + + # Supersection bit 18 + if ($kgm_tte & 0x00040000) + printf " supersection" + else + printf " section" + end + + # NS bit 19 + if ($kgm_tte & 0x00080000) + printf " no-secure" + else + printf " secure" + end + + printf "\n" + end +end + +define _pmap_walk_arm_level2 + set $kgm_tte_p = $arg0 + set $kgm_tte = *$kgm_tte_p + set $kgm_vaddr = $arg1 + + set $kgm_pte_pbase = (($kgm_tte & 0xFFFFFC00) - gPhysBase + gVirtBase) + set $kgm_pte_index = ($kgm_vaddr >> 12) & 0x000000FF + set $kgm_pte_p = &((pt_entry_t *)$kgm_pte_pbase)[$kgm_pte_index] + set $kgm_pte = *$kgm_pte_p + + # Print first level symbolically + if $kgm_pt_verbose >= 2 + printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_tte_p, $kgm_tte + + # bit [1:0] evaluated in _pmap_walk_arm + + # NS bit 3 + if ($kgm_tte & 0x00000008) + printf "no-secure" + else + printf "secure" + end + + # Domain bit [8:5] + printf " domain(%d)", (($kgm_tte & 0x000001e0) >> 5) + + # IMP bit 9 + printf " imp(%d)", (($kgm_tte & 0x00000200) >> 9) + + printf "\n" + end + + if $kgm_pt_verbose >= 2 + printf "second-level table (index %d):\n", $kgm_pte_index + end + if $kgm_pt_verbose >= 3 + set $kgm_pte_loop = 0 + while $kgm_pte_loop < 256 + set $kgm_pte_p_tmp = &((pt_entry_t *)$kgm_pte_pbase)[$kgm_pte_loop] + printf "0x%08x:\t0x%08x\n", (unsigned long)$kgm_pte_p_tmp, *$kgm_pte_p_tmp + set $kgm_pte_loop = $kgm_pte_loop + 1 + end + end + + if ($kgm_pte & 0x00000003) + set $kgm_pve_p = (pv_entry_t *)($kgm_pte_pbase + 0x100*sizeof(pt_entry_t) + $kgm_pte_index*sizeof(pv_entry_t)) + if ($kgm_pve_p->shadow != 0) + set $kgm_spte = $kgm_pve_p->shadow ^ ($kgm_vaddr & ~0xFFF) + set $kgm_paddr = ($kgm_spte & 0xFFFFF000) | ($kgm_vaddr & 0xFFF) + set $kgm_paddr_isvalid = 1 + else + set $kgm_paddr = (*$kgm_pte_p & 0xFFFFF000) | ($kgm_vaddr & 0xFFF) + set $kgm_paddr_isvalid = 1 + end + else + set $kgm_paddr = 0 + set $kgm_paddr_isvalid = 0 + end + + if $kgm_pt_verbose >= 2 + printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_pte_p, $kgm_pte + if (($kgm_pte & 0x00000003) == 0x00000000) + printf "invalid" + else + if (($kgm_pte & 0x00000003) == 0x00000001) + printf "large" + + # XN bit 15 + if ($kgm_pte & 0x00008000) == 0x00008000 + printf " no-execute" + else + printf " execute" + end + else + printf "small" + + # XN bit 0 + if ($kgm_pte & 0x00000001) == 0x00000001 + printf " no-execute" + else + printf " execute" + end + end + + # B bit 2 + set $kgm_b_bit = (($kgm_pte & 0x00000004) >> 2) + + # C bit 3 + set $kgm_c_bit = (($kgm_pte & 0x00000008) >> 3) + + # AP bit 9 and [5:4], merged to a single 3-bit value + set $kgm_access = (($kgm_pte & 0x00000030) >> 4) | (($kgm_pte & 0x00000200) >> 7) + if ($kgm_access == 0x0) + printf " noaccess" + end + if ($kgm_access == 0x1) + printf " supervisor(readwrite) user(noaccess)" + end + if ($kgm_access == 0x2) + printf " supervisor(readwrite) user(readonly)" + end + if ($kgm_access == 0x3) + printf " supervisor(readwrite) user(readwrite)" + end + if ($kgm_access == 0x4) + printf " noaccess(reserved)" + end + if ($kgm_access == 0x5) + printf " supervisor(readonly) user(noaccess)" + end + if ($kgm_access == 0x6) + printf " supervisor(readonly) user(readonly)" + end + if ($kgm_access == 0x7) + printf " supervisor(readonly) user(readonly)" + end + + # TEX bit [14:12] for large, [8:6] for small + if (($kgm_pte & 0x00000003) == 0x00000001) + set $kgm_tex_bits = (($kgm_pte & 0x00007000) >> 12) + else + set $kgm_tex_bits = (($kgm_pte & 0x000001c0) >> 6) + end + + # Print TEX, C, B all together + printf " TEX:C:B(%d%d%d:%d:%d)", ($kgm_tex_bits & 0x4 ? 1 : 0), ($kgm_tex_bits & 0x2 ? 1 : 0), ($kgm_tex_bits & 0x1 ? 1 : 0), $kgm_c_bit, $kgm_b_bit + + # S bit 10 + if ($kgm_pte & 0x00000400) + printf " shareable" + else + printf " not-shareable" + end + + # nG bit 11 + if ($kgm_pte & 0x00000800) + printf " not-global" + else + printf " global" + end + + end + printf "\n" + end +end + +# See ARM ARM Section B3.3 +define _pmap_walk_arm + set $kgm_pmap = (pmap_t) $arg0 + set $kgm_vaddr = $arg1 + set $kgm_paddr = 0 + set $kgm_paddr_isvalid = 0 + + # Shift by TTESHIFT (20) to get tte index + set $kgm_tte_index = (($kgm_vaddr - $kgm_pmap->min) >> 20) + set $kgm_tte_p = &$kgm_pmap->tte[$kgm_tte_index] + set $kgm_tte = *$kgm_tte_p + if $kgm_pt_verbose >= 2 + printf "first-level table (index %d):\n", $kgm_tte_index + end + if $kgm_pt_verbose >= 3 + set $kgm_tte_loop = 0 + while $kgm_tte_loop < 4096 + set $kgm_tte_p_tmp = &$kgm_pmap->tte[$kgm_tte_loop] + printf "0x%08x:\t0x%08x\n", (unsigned long)$kgm_tte_p_tmp, *$kgm_tte_p_tmp + set $kgm_tte_loop = $kgm_tte_loop + 1 + end + end + + if (($kgm_tte & 0x00000003) == 0x00000001) + _pmap_walk_arm_level2 $kgm_tte_p $kgm_vaddr + else + if (($kgm_tte & 0x00000003) == 0x00000002) + _pmap_walk_arm_level1_section $kgm_tte_p $kgm_vaddr + else + set $kgm_paddr = 0 + set $kgm_paddr_isvalid = 0 + if $kgm_pt_verbose >= 2 + printf "Invalid First-Level Translation Table Entry: 0x%08x\n", $kgm_tte + end + end + end + + if $kgm_pt_verbose >= 1 + if $kgm_paddr_isvalid + readphysint $kgm_paddr 32 $kgm_lcpu_self + set $kgm_value = $kgm_readphysint_result + printf "phys 0x%016llx: 0x%08x\n", $kgm_paddr, $kgm_value + else + printf "(no translation)\n" + end + end +end + +define pmap_walk + if $argc != 2 + printf "pmap_walk \n" + else + if !$kgm_pt_verbose + set $kgm_pt_verbose = 2 + else + if $kgm_pt_verbose > 3 + set $kgm_pt_verbose = 2 + end + end + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + _pmap_walk_x86 $arg0 $arg1 + else + if ($kgm_mtype == $kgm_mtype_arm) + _pmap_walk_arm $arg0 $arg1 + else + printf "Not available for current architecture.\n" + end + end + end +end + +document pmap_walk +Syntax: (gdb) pmap_walk +| Perform a page-table walk in for . +| Set: +| $kgm_pt_verbose=0 for no output, $kgm_paddr will be set +| if $kgm_paddr_isvalid is 1 +| $kgm_pt_verbose=1 for final physical address +| $kgm_pt_verbose=2 for dump of page table entry. +| $kgm_pt_verbose=3 for full hex dump of page tables. +end + +define pmap_vtop + if $argc != 2 + printf "pmap_vtop \n" + else + set $kgm_pt_verbose = 1 + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + _pmap_walk_x86 $arg0 $arg1 + else + if ($kgm_mtype == $kgm_mtype_arm) + _pmap_walk_arm $arg0 $arg1 + else + printf "Not available for current architecture.\n" + end + end + end +end + +document pmap_vtop +Syntax: (gdb) pmap_vtop +| For page-tables in translate to physical address. +end + +define zstack + set $index = $arg0 + + if (log_records == 0) + set $count = 0 + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + if ($argc == 2) + set $count = $arg1 + else + set $count = 1 + end + end + + while ($count) + printf "\n--------------- " + + if (zrecords[$index].z_opcode == 1) + printf "ALLOC " + else + printf "FREE " + end + showptr zrecords[$index].z_element + printf " : index %d : ztime %d -------------\n", $index, zrecords[$index].z_time + + set $frame = 0 + + while ($frame < 15) + set $frame_pc = zrecords[$index].z_pc[$frame] + + if ($frame_pc == 0) + loop_break + end + + x/i $frame_pc + set $frame = $frame + 1 + end + + set $index = $index + 1 + set $count = $count - 1 + end +end + +document zstack +Syntax: (gdb) zstack [] +| Zone leak debugging: print the stack trace of log element at . +| If a is supplied, it prints log elements starting at . +| +| The suggested usage is to look at indexes below zcurrent and look for common stack traces. +| The stack trace that occurs the most is probably the cause of the leak. Find the pc of the +| function calling into zalloc and use the countpcs kgmacro to find out how often that pc occurs in the log. +| The pc occuring in a high percentage of records is most likely the source of the leak. +| +| The findoldest kgmacro is also useful for leak debugging since it identifies the oldest record +| in the log, which may indicate the leaker. +end + +define findoldest + set $index = 0 + set $count = log_records + set $cur_min = 2000000000 + set $cur_index = 0 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + + while ($count) + if (zrecords[$index].z_element && zrecords[$index].z_time < $cur_min) + set $cur_index = $index + set $cur_min = zrecords[$index].z_time + end + + set $count = $count - 1 + set $index = $index + 1 + end + + printf "oldest record is at log index %d:\n", $cur_index + zstack $cur_index + end +end + +document findoldest +Syntax: (gdb) findoldest +| Zone leak debugging: find and print the oldest record in the log. Note that this command +| can take several minutes to run since it uses linear search. +| +| Once it prints a stack trace, find the pc of the caller above all the zalloc, kalloc and +| IOKit layers. Then use the countpcs kgmacro to see how often this caller has allocated +| memory. A caller with a high percentage of records in the log is probably the leaker. +end + +define countpcs + set $target_pc = $arg0 + set $index = 0 + set $count = log_records + set $found = 0 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + + while ($count) + set $frame = 0 + + if (zrecords[$index].z_element != 0) + while ($frame < 15) + if (zrecords[$index].z_pc[$frame] == $target_pc) + set $found = $found + 1 + set $frame = 15 + end + + set $frame = $frame + 1 + end + end + + set $index = $index + 1 + set $count = $count - 1 + end + + printf "occurred %d times in log (%d%c of records)\n", $found, ($found * 100) / zrecorded, '%' + end +end + +document countpcs +Syntax: (gdb) countpcs +| Zone leak debugging: search the log and print a count of all log entries that contain the given +| in the stack trace. This is useful for verifying a suspected as being the source of +| the leak. If a high percentage of the log entries contain the given , then it's most +| likely the source of the leak. Note that this command can take several minutes to run. +end + +define findelem + set $fe_index = zcurrent + set $fe_count = log_records + set $fe_elem = $arg0 + set $fe_prev_op = -1 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + end + + while ($fe_count) + if (zrecords[$fe_index].z_element == $fe_elem) + zstack $fe_index + + if (zrecords[$fe_index].z_opcode == $fe_prev_op) + printf "*************** DOUBLE OP! *********************\n" + end + + set $fe_prev_op = zrecords[$fe_index].z_opcode + end + + set $fe_count = $fe_count - 1 + set $fe_index = $fe_index + 1 + + if ($fe_index >= log_records) + set $fe_index = 0 + end + end +end + +document findelem +Syntax: (gdb) findelem +| Zone corruption debugging: search the log and print out the stack traces for all log entries that +| refer to the given zone element. When the kernel panics due to a corrupted zone element, get the +| element address and use this macro. This will show you the stack traces of all logged zalloc and +| zfree operations which tells you who touched the element in the recent past. This also makes +| double-frees readily apparent. +end + + +# This implements a shadowing scheme in kgmacros. If the +# current user data can be accessed by simply changing kdp_pmap, +# that is used. Otherwise, we copy data into a temporary buffer +# in the kernel's address space and use that instead. Don't rely on +# kdp_pmap between invocations of map/unmap. Since the shadow +# codepath uses a manual KDP packet, request no more than 128 bytes. +# Uses $kgm_lp64 for kernel address space size, and +# $kgm_readphys_use_kdp/$kgm_readphys_force_physmap to override +# how the user pages are accessed ($kgm_readphys_force_physmap +# implies walking the user task's pagetables to get a physical +# address and then shadowing data from there using the +# physical mapping of memory). +define _map_user_data_from_task + set $kgm_map_user_taskp = (task_t)$arg0 + set $kgm_map_user_map = $kgm_map_user_taskp->map + set $kgm_map_user_pmap = $kgm_map_user_map->pmap + set $kgm_map_user_task_64 = ( $kgm_map_user_taskp->taskFeatures[0] & 0x80000000) + set $kgm_map_user_window = 0 + set $kgm_map_switch_map = 0 + + if ($kgm_readphys_force_kdp != 0) + set $kgm_readphys_use_kdp = 1 + else + if ($kgm_readphys_force_physmap) + set $kgm_readphys_use_kdp = 0 + else + set $kgm_readphys_use_kdp = ( kdp->is_conn > 0 ) + end + end + + if ($kgm_readphys_use_kdp) + + if $kgm_lp64 + set $kgm_map_switch_map = 1 + else + if !$kgm_map_user_task_64 + set $kgm_map_switch_map = 1 + end + end + + if ($kgm_map_switch_map) + # switch the map safely + set $kgm_map_user_window = $arg1 + set kdp_pmap = $kgm_map_user_pmap + else + # requires shadowing/copying + + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg1 + set $kgm_pkt->nbytes = (uint32_t)$arg2 + + set kdp_pmap = $kgm_map_user_pmap + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + # Go back to kernel map so that we can access buffer directly + set kdp_pmap = 0 + + set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_map_user_window = $kgm_pkt->data + else + set $kgm_map_user_window = 0 + end + end + + else + # without the benefit of a KDP stub on the target, try to + # find the user task's physical mapping and memcpy the data. + # If it straddles a page boundary, copy in two passes + set $kgm_vaddr_range1_start = (unsigned long long)$arg1 + set $kgm_vaddr_range1_count = (unsigned long long)$arg2 + if (($kgm_vaddr_range1_start + $kgm_vaddr_range1_count) & 0xFFF) < $kgm_vaddr_range1_count + set $kgm_vaddr_range2_start = ($kgm_vaddr_range1_start + $kgm_vaddr_range1_count) & ~((unsigned long long)0xFFF) + set $kgm_vaddr_range2_count = $kgm_vaddr_range1_start + $kgm_vaddr_range1_count - $kgm_vaddr_range2_start + set $kgm_vaddr_range1_count = $kgm_vaddr_range2_start - $kgm_vaddr_range1_start + else + set $kgm_vaddr_range2_start = 0 + set $kgm_vaddr_range2_count = 0 + end + set $kgm_paddr_range1_in_kva = 0 + set $kgm_paddr_range2_in_kva = 0 + + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_pt_verbose = 0 + _pmap_walk_x86 $kgm_map_user_pmap $kgm_vaddr_range1_start + if $kgm_paddr_isvalid + set $kgm_paddr_range1_in_kva = $kgm_paddr + physmap_base + end + if $kgm_vaddr_range2_start + _pmap_walk_x86 $kgm_map_user_pmap $kgm_vaddr_range2_start + if $kgm_paddr_isvalid + set $kgm_paddr_range2_in_kva = $kgm_paddr + physmap_base + end + end + else + if ($kgm_mtype == $kgm_mtype_arm) + set $kgm_pt_verbose = 0 + _pmap_walk_arm $kgm_map_user_pmap $kgm_vaddr_range1_start + if $kgm_paddr_isvalid + set $kgm_paddr_range1_in_kva = $kgm_paddr - gPhysBase + gVirtBase + end + if $kgm_vaddr_range2_start + _pmap_walk_arm $kgm_map_user_pmap $kgm_vaddr_range2_start + if $kgm_paddr_isvalid + set $kgm_paddr_range2_in_kva = $kgm_paddr - gPhysBase + gVirtBase + end + end + else + printf "Not available for current architecture.\n" + set $kgm_paddr_isvalid = 0 + end + end + if $kgm_paddr_range1_in_kva + set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data + memcpy $kgm_pkt->data $kgm_paddr_range1_in_kva $kgm_vaddr_range1_count + if $kgm_paddr_range2_in_kva + memcpy &$kgm_pkt->data[$kgm_vaddr_range1_count] $kgm_paddr_range2_in_kva $kgm_vaddr_range2_count + end + set $kgm_map_user_window = $kgm_pkt->data + else + set $kgm_map_user_window = 0 + end + end +end + +define _unmap_user_data_from_task + set kdp_pmap = 0 +end + +# uses $kgm_taskp. Maps 32 bytes at a time and prints it +define _print_path_for_image + set $kgm_print_path_address = (unsigned long long)$arg0 + set $kgm_path_str_notdone = 1 + + if ($kgm_print_path_address == 0) + set $kgm_path_str_notdone = 0 + end + + while $kgm_path_str_notdone + _map_user_data_from_task $kgm_taskp $kgm_print_path_address 32 + + set $kgm_print_path_ptr = (char *)$kgm_map_user_window + set $kgm_path_i = 0 + while ($kgm_path_i < 32 && $kgm_print_path_ptr[$kgm_path_i] != '\0') + set $kgm_path_i = $kgm_path_i + 1 + end + printf "%.32s", $kgm_print_path_ptr + + _unmap_user_data_from_task $kgm_taskp + + # break out if we terminated on NUL + if $kgm_path_i < 32 + set $kgm_path_str_notdone = 0 + else + set $kgm_print_path_address = $kgm_print_path_address + 32 + end + end +end + +# uses $kgm_taskp and $kgm_task_64. May modify $kgm_dyld_load_path +define _print_image_info + set $kgm_mh_image_address = (unsigned long long)$arg0 + set $kgm_mh_path_address = (unsigned long long)$arg1 + + # 32 bytes enough for mach_header/mach_header_64 + _map_user_data_from_task $kgm_taskp $kgm_mh_image_address 32 + + set $kgm_mh_ptr = (unsigned int*)$kgm_map_user_window + set $kgm_mh_magic = $kgm_mh_ptr[0] + set $kgm_mh_cputype = $kgm_mh_ptr[1] + set $kgm_mh_cpusubtype = $kgm_mh_ptr[2] + set $kgm_mh_filetype = $kgm_mh_ptr[3] + set $kgm_mh_ncmds = $kgm_mh_ptr[4] + set $kgm_mh_sizeofcmds = $kgm_mh_ptr[5] + set $kgm_mh_flags = $kgm_mh_ptr[6] + + _unmap_user_data_from_task $kgm_taskp + + if $kgm_mh_magic == 0xfeedfacf + set $kgm_mh_64 = 1 + set $kgm_lc_address = $kgm_mh_image_address + 32 + else + set $kgm_mh_64 = 0 + set $kgm_lc_address = $kgm_mh_image_address + 28 + end + + set $kgm_lc_idx = 0 + set $kgm_uuid_data = 0 + while $kgm_lc_idx < $kgm_mh_ncmds + + # 24 bytes is size of uuid_command + _map_user_data_from_task $kgm_taskp $kgm_lc_address 24 + + set $kgm_lc_ptr = (unsigned int *)$kgm_map_user_window + set $kgm_lc_cmd = $kgm_lc_ptr[0] + set $kgm_lc_cmd_size = $kgm_lc_ptr[1] + set $kgm_lc_data = (unsigned char *)$kgm_lc_ptr + 8 + + if $kgm_lc_cmd == 0x1b + set $kgm_uuid_data = $kgm_lc_data + if $kgm_mh_64 + printf "0x%016llx ", $kgm_mh_image_address + else + printf "0x%08x ", $kgm_mh_image_address + end + + set $kgm_printed_type = 0 + if $kgm_mh_filetype == 0x2 + printf "MH_EXECUTE " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x6 + printf "MH_DYLIB " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x7 + printf "MH_DYLINKER " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x8 + printf "MH_BUNDLE " + set $kgm_printed_type = 1 + end + if !$kgm_printed_type + printf "UNKNOWN " + end + printf "%02.2X%02.2X%02.2X%02.2X-", $kgm_uuid_data[0], $kgm_uuid_data[1], $kgm_uuid_data[2], $kgm_uuid_data[3] + printf "%02.2X%02.2X-", $kgm_uuid_data[4], $kgm_uuid_data[5] + printf "%02.2X%02.2X-", $kgm_uuid_data[6], $kgm_uuid_data[7] + printf "%02.2X%02.2X-", $kgm_uuid_data[8], $kgm_uuid_data[9] + printf "%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X", $kgm_uuid_data[10], $kgm_uuid_data[11], $kgm_uuid_data[12], $kgm_uuid_data[13], $kgm_uuid_data[14], $kgm_uuid_data[15] + + _unmap_user_data_from_task $kgm_taskp + + printf " " + _print_path_for_image $kgm_mh_path_address + printf "\n" + + loop_break + else + if $kgm_lc_cmd == 0xe + set $kgm_load_dylinker_data = $kgm_lc_data + set $kgm_dyld_load_path = $kgm_lc_address + *((unsigned int *)$kgm_load_dylinker_data) + end + _unmap_user_data_from_task $kgm_taskp + end + + set $kgm_lc_address = $kgm_lc_address + $kgm_lc_cmd_size + set $kgm_lc_idx = $kgm_lc_idx + 1 + end + + if (!$kgm_uuid_data) + # didn't find LC_UUID, for a dylib, just print out basic info + if $kgm_mh_64 + printf "0x%016llx ", $kgm_mh_image_address + else + printf "0x%08x ", $kgm_mh_image_address + end + set $kgm_printed_type = 0 + if $kgm_mh_filetype == 0x2 + printf "MH_EXECUTE " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x6 + printf "MH_DYLIB " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x7 + printf "MH_DYLINKER " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x8 + printf "MH_BUNDLE " + set $kgm_printed_type = 1 + end + if !$kgm_printed_type + printf "UNKNOWN " + end + printf " ", + + printf " " + _print_path_for_image $kgm_mh_path_address + printf "\n" + + end + +end + +define _print_images_for_dyld_image_info + set $kgm_taskp = $arg0 + set $kgm_task_64 = $arg1 + set $kgm_dyld_all_image_infos_address = (unsigned long long)$arg2 + + _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 112 + + set $kgm_dyld_all_image_infos = (unsigned int *)$kgm_map_user_window + set $kgm_dyld_all_image_infos_version = $kgm_dyld_all_image_infos[0] + if ($kgm_dyld_all_image_infos_version > 12) + printf "Unknown dyld all_image_infos version number %d\n", $kgm_dyld_all_image_infos_version + end + set $kgm_image_info_count = $kgm_dyld_all_image_infos[1] + + set $kgm_dyld_load_path = 0 + if $kgm_task_64 + set $kgm_image_info_size = 24 + set $kgm_image_info_array_address = ((unsigned long long *)$kgm_dyld_all_image_infos)[1] + set $kgm_dyld_load_address = ((unsigned long long *)$kgm_dyld_all_image_infos)[4] + set $kgm_dyld_all_image_infos_address_from_struct = ((unsigned long long *)$kgm_dyld_all_image_infos)[13] + else + set $kgm_image_info_size = 12 + set $kgm_image_info_array_address = ((unsigned int *)$kgm_dyld_all_image_infos)[2] + set $kgm_dyld_load_address = ((unsigned int *)$kgm_dyld_all_image_infos)[5] + set $kgm_dyld_all_image_infos_address_from_struct = ((unsigned int *)$kgm_dyld_all_image_infos)[14] + end + + _unmap_user_data_from_task $kgm_taskp + + # Account for ASLR slide before dyld can fix the structure + set $kgm_dyld_load_address = $kgm_dyld_load_address + ($kgm_dyld_all_image_infos_address - $kgm_dyld_all_image_infos_address_from_struct) + + set $kgm_image_info_i = 0 + while $kgm_image_info_i < $kgm_image_info_count + + set $kgm_image_info_address = $kgm_image_info_array_address + $kgm_image_info_size*$kgm_image_info_i + + _map_user_data_from_task $kgm_taskp $kgm_image_info_address $kgm_image_info_size + if $kgm_task_64 + set $kgm_image_info_addr = ((unsigned long long *)$kgm_map_user_window)[0] + set $kgm_image_info_path = ((unsigned long long *)$kgm_map_user_window)[1] + else + set $kgm_image_info_addr = ((unsigned int *)$kgm_map_user_window)[0] + set $kgm_image_info_path = ((unsigned int *)$kgm_map_user_window)[1] + end + _unmap_user_data_from_task $kgm_taskp + + # printf "[%d] = image address %llx path address %llx\n", $kgm_image_info_i, $kgm_image_info_addr, $kgm_image_info_path + _print_image_info $kgm_image_info_addr $kgm_image_info_path + + set $kgm_image_info_i = $kgm_image_info_i + 1 + end + + # $kgm_dyld_load_path may get set when the main executable is processed + # printf "[dyld] = image address %llx path address %llx\n", $kgm_dyld_load_address, $kgm_dyld_load_path + _print_image_info $kgm_dyld_load_address $kgm_dyld_load_path + +end + +define showuserlibraries + set $kgm_taskp = (task_t)$arg0 + set $kgm_dyld_image_info = $kgm_taskp->all_image_info_addr + + set $kgm_map = $kgm_taskp->map + set $kgm_task_64 = ( $kgm_taskp->taskFeatures[0] & 0x80000000) + + if ($kgm_dyld_image_info != 0) + printf "address " + if $kgm_task_64 + printf " " + end + printf " type " + printf " uuid " + printf "path\n" + + _print_images_for_dyld_image_info $kgm_taskp $kgm_task_64 $kgm_dyld_image_info + else + printf "No dyld shared library information available for task\n" + end +end +document showuserlibraries +Syntax: (gdb) showuserlibraries +| For a given user task, inspect the dyld shared library state and print +| information about all Mach-O images. +end + +define showuserdyldinfo + set $kgm_taskp = (task_t)$arg0 + set $kgm_dyld_all_image_infos_address = (unsigned long long)$kgm_taskp->all_image_info_addr + + set $kgm_map = $kgm_taskp->map + set $kgm_task_64 = ( $kgm_taskp->taskFeatures[0] & 0x80000000) + + if ($kgm_dyld_all_image_infos_address != 0) + + _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 112 + + set $kgm_dyld_all_image_infos = (unsigned char *)$kgm_map_user_window + set $kgm_dyld_all_image_infos_version = ((unsigned int *)$kgm_dyld_all_image_infos)[0] + if ($kgm_dyld_all_image_infos_version > 12) + printf "Unknown dyld all_image_infos version number %d\n", $kgm_dyld_all_image_infos_version + end + + # Find fields by byte offset. We assume at least version 9 is supported + if $kgm_task_64 + set $kgm_dyld_all_image_infos_infoArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[4]) + set $kgm_dyld_all_image_infos_infoArray = *(unsigned long long *)(&$kgm_dyld_all_image_infos[8]) + set $kgm_dyld_all_image_infos_notification = *(unsigned long long *)(&$kgm_dyld_all_image_infos[16]) + set $kgm_dyld_all_image_infos_processDetachedFromSharedRegion = *(unsigned char *)(&$kgm_dyld_all_image_infos[24]) + set $kgm_dyld_all_image_infos_libSystemInitialized = *(unsigned char *)(&$kgm_dyld_all_image_infos[25]) + set $kgm_dyld_all_image_infos_dyldImageLoadAddress = *(unsigned long long *)(&$kgm_dyld_all_image_infos[32]) + set $kgm_dyld_all_image_infos_jitInfo = *(unsigned long long *)(&$kgm_dyld_all_image_infos[40]) + set $kgm_dyld_all_image_infos_dyldVersion = *(unsigned long long *)(&$kgm_dyld_all_image_infos[48]) + set $kgm_dyld_all_image_infos_errorMessage = *(unsigned long long *)(&$kgm_dyld_all_image_infos[56]) + set $kgm_dyld_all_image_infos_terminationFlags = *(unsigned long long *)(&$kgm_dyld_all_image_infos[64]) + set $kgm_dyld_all_image_infos_coreSymbolicationShmPage = *(unsigned long long *)(&$kgm_dyld_all_image_infos[72]) + set $kgm_dyld_all_image_infos_systemOrderFlag = *(unsigned long long *)(&$kgm_dyld_all_image_infos[80]) + set $kgm_dyld_all_image_infos_uuidArrayCount = *(unsigned long long *)(&$kgm_dyld_all_image_infos[88]) + set $kgm_dyld_all_image_infos_uuidArray = *(unsigned long long *)(&$kgm_dyld_all_image_infos[96]) + set $kgm_dyld_all_image_infos_dyldAllImageInfosAddress = *(unsigned long long *)(&$kgm_dyld_all_image_infos[104]) + else + set $kgm_dyld_all_image_infos_infoArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[4]) + set $kgm_dyld_all_image_infos_infoArray = *(unsigned int *)(&$kgm_dyld_all_image_infos[8]) + set $kgm_dyld_all_image_infos_notification = *(unsigned int *)(&$kgm_dyld_all_image_infos[12]) + set $kgm_dyld_all_image_infos_processDetachedFromSharedRegion = *(unsigned char *)(&$kgm_dyld_all_image_infos[16]) + set $kgm_dyld_all_image_infos_libSystemInitialized = *(unsigned char *)(&$kgm_dyld_all_image_infos[17]) + set $kgm_dyld_all_image_infos_dyldImageLoadAddress = *(unsigned int *)(&$kgm_dyld_all_image_infos[20]) + set $kgm_dyld_all_image_infos_jitInfo = *(unsigned int *)(&$kgm_dyld_all_image_infos[24]) + set $kgm_dyld_all_image_infos_dyldVersion = *(unsigned int *)(&$kgm_dyld_all_image_infos[28]) + set $kgm_dyld_all_image_infos_errorMessage = *(unsigned int *)(&$kgm_dyld_all_image_infos[32]) + set $kgm_dyld_all_image_infos_terminationFlags = *(unsigned int *)(&$kgm_dyld_all_image_infos[36]) + set $kgm_dyld_all_image_infos_coreSymbolicationShmPage = *(unsigned int *)(&$kgm_dyld_all_image_infos[40]) + set $kgm_dyld_all_image_infos_systemOrderFlag = *(unsigned int *)(&$kgm_dyld_all_image_infos[44]) + set $kgm_dyld_all_image_infos_uuidArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[48]) + set $kgm_dyld_all_image_infos_uuidArray = *(unsigned int *)(&$kgm_dyld_all_image_infos[52]) + set $kgm_dyld_all_image_infos_dyldAllImageInfosAddress = *(unsigned int *)(&$kgm_dyld_all_image_infos[56]) + end + + _unmap_user_data_from_task $kgm_taskp + + set $kgm_dyld_all_imfo_infos_slide = ( $kgm_dyld_all_image_infos_address - $kgm_dyld_all_image_infos_dyldAllImageInfosAddress ) + set $kgm_dyld_all_image_infos_dyldVersion_postslide = ( $kgm_dyld_all_image_infos_dyldVersion + $kgm_dyld_all_imfo_infos_slide ) + + printf " version %u\n", $kgm_dyld_all_image_infos_version + printf " infoArrayCount %u\n", $kgm_dyld_all_image_infos_infoArrayCount + printf " infoArray " + showuserptr $kgm_dyld_all_image_infos_infoArray + printf "\n" + printf " notification " + showuserptr $kgm_dyld_all_image_infos_notification + printf "\n" + printf "processDetachedFromSharedRegion %d\n", $kgm_dyld_all_image_infos_processDetachedFromSharedRegion + printf " libSystemInitialized %d\n", $kgm_dyld_all_image_infos_libSystemInitialized + printf " dyldImageLoadAddress " + showuserptr $kgm_dyld_all_image_infos_dyldImageLoadAddress + printf "\n" + printf " jitInfo " + showuserptr $kgm_dyld_all_image_infos_jitInfo + printf "\n" + printf " dyldVersion " + showuserptr $kgm_dyld_all_image_infos_dyldVersion + printf "\n" + printf " " + _print_path_for_image $kgm_dyld_all_image_infos_dyldVersion_postslide + if ($kgm_dyld_all_imfo_infos_slide != 0) + printf " (currently " + showuserptr $kgm_dyld_all_image_infos_dyldVersion_postslide + printf ")" + end + printf "\n" + + printf " errorMessage " + showuserptr $kgm_dyld_all_image_infos_errorMessage + printf "\n" + if $kgm_dyld_all_image_infos_errorMessage != 0 + printf " " + _print_path_for_image $kgm_dyld_all_image_infos_errorMessage + printf "\n" + end + + printf " terminationFlags " + showuserptr $kgm_dyld_all_image_infos_terminationFlags + printf "\n" + printf " coreSymbolicationShmPage " + showuserptr $kgm_dyld_all_image_infos_coreSymbolicationShmPage + printf "\n" + printf " systemOrderFlag " + showuserptr $kgm_dyld_all_image_infos_systemOrderFlag + printf "\n" + printf " uuidArrayCount " + showuserptr $kgm_dyld_all_image_infos_uuidArrayCount + printf "\n" + printf " uuidArray " + showuserptr $kgm_dyld_all_image_infos_uuidArray + printf "\n" + printf " dyldAllImageInfosAddress " + showuserptr $kgm_dyld_all_image_infos_dyldAllImageInfosAddress + printf "\n" + printf " (currently " + showuserptr $kgm_dyld_all_image_infos_address + printf ")\n" + + if $kgm_task_64 + set $kgm_dyld_all_image_infos_address = $kgm_dyld_all_image_infos_address + 112 + _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 64 + set $kgm_dyld_all_image_infos_v10 = (unsigned char *)$kgm_map_user_window + set $kgm_dyld_all_image_infos_initialImageCount = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[112-112]) + set $kgm_dyld_all_image_infos_errorKind = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[120-112]) + set $kgm_dyld_all_image_infos_errorClientOfDylibPath = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[128-112]) + set $kgm_dyld_all_image_infos_errorTargetDylibPath = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[136-112]) + set $kgm_dyld_all_image_infos_errorSymbol = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[144-112]) + set $kgm_dyld_all_image_infos_sharedCacheSlide = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[152-112]) + + _unmap_user_data_from_task $kgm_taskp + else + set $kgm_dyld_all_image_infos_address = $kgm_dyld_all_image_infos_address + 60 + _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 64 + set $kgm_dyld_all_image_infos_v10 = (unsigned char *)$kgm_map_user_window + set $kgm_dyld_all_image_infos_initialImageCount = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[60-60]) + set $kgm_dyld_all_image_infos_errorKind = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[64-60]) + set $kgm_dyld_all_image_infos_errorClientOfDylibPath = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[68-60]) + set $kgm_dyld_all_image_infos_errorTargetDylibPath = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[72-60]) + set $kgm_dyld_all_image_infos_errorSymbol = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[76-60]) + set $kgm_dyld_all_image_infos_sharedCacheSlide = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[80-60]) + _unmap_user_data_from_task $kgm_taskp + end + + if $kgm_dyld_all_image_infos_version >= 10 + printf " initialImageCount " + showuserptr $kgm_dyld_all_image_infos_initialImageCount + printf "\n" + end + + if $kgm_dyld_all_image_infos_version >= 11 + printf " errorKind " + showuserptr $kgm_dyld_all_image_infos_errorKind + printf "\n" + printf " errorClientOfDylibPath " + showuserptr $kgm_dyld_all_image_infos_errorClientOfDylibPath + printf "\n" + if $kgm_dyld_all_image_infos_errorClientOfDylibPath != 0 + printf " " + _print_path_for_image $kgm_dyld_all_image_infos_errorClientOfDylibPath + printf "\n" + end + printf " errorTargetDylibPath " + showuserptr $kgm_dyld_all_image_infos_errorTargetDylibPath + printf "\n" + if $kgm_dyld_all_image_infos_errorTargetDylibPath != 0 + printf " " + _print_path_for_image $kgm_dyld_all_image_infos_errorTargetDylibPath + printf "\n" + end + printf " errorSymbol " + showuserptr $kgm_dyld_all_image_infos_errorSymbol + printf "\n" + if $kgm_dyld_all_image_infos_errorSymbol != 0 + printf " " + _print_path_for_image $kgm_dyld_all_image_infos_errorSymbol + printf "\n" + end + end + + if $kgm_dyld_all_image_infos_version >= 12 + printf " sharedCacheSlide " + showuserptr $kgm_dyld_all_image_infos_sharedCacheSlide + printf "\n" + end + + else + printf "No dyld information available for task\n" + end +end +document showuserdyldinfo +Syntax: (gdb) showuserdyldinfo +| For a given user task, inspect the dyld global info and print +| out all fields, including error messages. +end + +define showkerneldebugheader + printf "kd_buf " + showptrhdrpad + printf "CPU Thread " + showptrhdrpad + printf "Timestamp S/E Class Sub Code Code Specific Info\n" +end + +define _printevflags + if $arg0 & 1 + printf "EV_RE " + end + if $arg0 & 2 + printf "EV_WR " + end + if $arg0 & 4 + printf "EV_EX " + end + if $arg0 & 8 + printf "EV_RM " + end + + if $arg0 & 0x00100 + printf "EV_RBYTES " + end + if $arg0 & 0x00200 + printf "EV_WBYTES " + end + if $arg0 & 0x00400 + printf "EV_RCLOSED " + end + if $arg0 & 0x00800 + printf "EV_RCONN " + end + if $arg0 & 0x01000 + printf "EV_WCLOSED " + end + if $arg0 & 0x02000 + printf "EV_WCONN " + end + if $arg0 & 0x04000 + printf "EV_OOB " + end + if $arg0 & 0x08000 + printf "EV_FIN " + end + if $arg0 & 0x10000 + printf "EV_RESET " + end + if $arg0 & 0x20000 + printf "EV_TIMEOUT " + end +end + +define showkerneldebugbufferentry + set $kgm_kdebug_entry = (kd_buf *) $arg0 + + set $kgm_debugid = $kgm_kdebug_entry->debugid + set $kgm_kdebug_arg1 = $kgm_kdebug_entry->arg1 + set $kgm_kdebug_arg2 = $kgm_kdebug_entry->arg2 + set $kgm_kdebug_arg3 = $kgm_kdebug_entry->arg3 + set $kgm_kdebug_arg4 = $kgm_kdebug_entry->arg4 + + if $kgm_lp64 + set $kgm_kdebug_cpu = $kgm_kdebug_entry->cpuid + set $kgm_ts_hi = ($kgm_kdebug_entry->timestamp >> 32) & 0xFFFFFFFF + set $kgm_ts_lo = $kgm_kdebug_entry->timestamp & 0xFFFFFFFF + else + set $kgm_kdebug_cpu = ($kgm_kdebug_entry->timestamp >> 56) + set $kgm_ts_hi = ($kgm_kdebug_entry->timestamp >> 32) & 0x00FFFFFF + set $kgm_ts_lo = $kgm_kdebug_entry->timestamp & 0xFFFFFFFF + end + + set $kgm_kdebug_class = ($kgm_debugid >> 24) & 0x000FF + set $kgm_kdebug_subclass = ($kgm_debugid >> 16) & 0x000FF + set $kgm_kdebug_code = ($kgm_debugid >> 2) & 0x03FFF + set $kgm_kdebug_qual = ($kgm_debugid ) & 0x00003 + + if $kgm_kdebug_qual == 0 + set $kgm_kdebug_qual = '-' + else + if $kgm_kdebug_qual == 1 + set $kgm_kdebug_qual = 'S' + else + if $kgm_kdebug_qual == 2 + set $kgm_kdebug_qual = 'E' + else + if $kgm_kdebug_qual == 3 + set $kgm_kdebug_qual = '?' + end + end + end + end + + # preamble and qual + + showptr $kgm_kdebug_entry + printf " %d ", $kgm_kdebug_cpu + showptr $kgm_kdebug_entry->arg5 + printf " 0x%08X%08X %c ", $kgm_ts_hi, $kgm_ts_lo, $kgm_kdebug_qual + + # class + + if $kgm_kdebug_class == 1 + printf "MACH" + else + if $kgm_kdebug_class == 2 + printf "NET " + else + if $kgm_kdebug_class == 3 + printf "FS " + else + if $kgm_kdebug_class == 4 + printf "BSD " + else + if $kgm_kdebug_class == 5 + printf "IOK " + else + if $kgm_kdebug_class == 6 + printf "DRVR" + else + if $kgm_kdebug_class == 7 + printf "TRAC" + else + if $kgm_kdebug_class == 8 + printf "DLIL" + else + if $kgm_kdebug_class == 8 + printf "SEC " + else + if $kgm_kdebug_class == 20 + printf "MISC" + else + if $kgm_kdebug_class == 31 + printf "DYLD" + else + if $kgm_kdebug_class == 32 + printf "QT " + else + if $kgm_kdebug_class == 33 + printf "APPS" + else + if $kgm_kdebug_class == 255 + printf "MIG " + else + printf "0x%02X", $kgm_kdebug_class + end + end + end + end + end + end + end + end + end + end + end + end + end + end + + # subclass and code + + printf " 0x%02X %5d ", $kgm_kdebug_subclass, $kgm_kdebug_code + + # space for debugid-specific processing + + # EVPROC from bsd/kern/sys_generic.c + + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT) + if $kgm_debugid == 0x14100048 + printf "waitevent " + if $kgm_kdebug_arg1 == 1 + printf "before sleep" + else + if $kgm_kdebug_arg1 == 2 + printf "after sleep" + else + printf "????????????" + end + end + printf " chan=0x%08X ", $kgm_kdebug_arg2 + else + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_START) + if $kgm_debugid == 0x14100049 + printf "waitevent " + else + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_END) + if $kgm_debugid == 0x1410004a + printf "waitevent error=%d ", $kgm_kdebug_arg1 + printf "eqp=0x%08X ", $kgm_kdebug_arg4 + _printevflags $kgm_kdebug_arg3 + printf "er_handle=%d ", $kgm_kdebug_arg2 + else + # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_START) + if $kgm_debugid == 0x14100059 + printf "evprocdeque proc=0x%08X ", $kgm_kdebug_arg1 + if $kgm_kdebug_arg2 == 0 + printf "remove first " + else + printf "remove 0x%08X ", $kgm_kdebug_arg2 + end + else + # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_END) + if $kgm_debugid == 0x1410005a + printf "evprocdeque " + if $kgm_kdebug_arg1 == 0 + printf "result=NULL " + else + printf "result=0x%08X ", $kgm_kdebug_arg1 + end + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_START) + if $kgm_debugid == 0x14100041 + printf "postevent " + _printevflags $kgm_kdebug_arg1 + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST) + if $kgm_debugid == 0x14100040 + printf "postevent " + printf "evq=0x%08X ", $kgm_kdebug_arg1 + printf "er_eventbits=" + _printevflags $kgm_kdebug_arg2 + printf "mask=" + _printevflags $kgm_kdebug_arg3 + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_END) + if $kgm_debugid == 0x14100042 + printf "postevent " + else + # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_START) + if $kgm_debugid == 0x14100055 + printf "evprocenque eqp=0x%08d ", $kgm_kdebug_arg1 + if $kgm_kdebug_arg2 & 1 + printf "EV_QUEUED " + end + _printevflags $kgm_kdebug_arg3 + else + + # MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP) + if $kgm_debugid == 0x14100050 + printf "evprocenque before wakeup eqp=0x%08d ", $kgm_kdebug_arg4 + else + # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_END) + if $kgm_debugid == 0x14100056 + printf "evprocenque " + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_START) + if $kgm_debugid == 0x1410004d + printf "modwatch " + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD) + if $kgm_debugid == 0x1410004c + printf "modwatch er_handle=%d ", $kgm_kdebug_arg1 + _printevflags $kgm_kdebug_arg2 + printf "evq=0x%08X ", $kgm_kdebug_arg3 + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_END) + if $kgm_debugid == 0x1410004e + printf "modwatch er_handle=%d ", $kgm_kdebug_arg1 + printf "ee_eventmask=" + _printevflags $kgm_kdebug_arg2 + printf "sp=0x%08X ", $kgm_kdebug_arg3 + printf "flag=" + _printevflags $kgm_kdebug_arg4 + else + printf "arg1=0x%08X ", $kgm_kdebug_arg1 + printf "arg2=0x%08X ", $kgm_kdebug_arg2 + printf "arg3=0x%08X ", $kgm_kdebug_arg3 + printf "arg4=0x%08X ", $kgm_kdebug_arg4 + end + end + end + end + end + end + end + end + end + end + end + end + end + end + + # finish up + + printf "\n" +end + +define showkerneldebugbuffercpu + set $kgm_cpu_number = (int) $arg0 + set $kgm_entry_count = (int) $arg1 + set $kgm_debugentriesfound = 0 + # 0x80000000 == KDBG_BFINIT + if (kd_ctrl_page.kdebug_flags & 0x80000000) + showkerneldebugheader + + if $kgm_entry_count == 0 + printf " is 0, dumping 50 entries\n" + set $kgm_entry_count = 50 + end + + if $kgm_cpu_number >= kd_cpus + printf "cpu number too big\n" + else + set $kgm_kdbp = &kdbip[$kgm_cpu_number] + set $kgm_kdsp = $kgm_kdbp->kd_list_head + while (($kgm_kdsp.raw != 0) && ($kgm_entry_count > 0)) + set $kgm_kdsp_actual = &kd_bufs[$kgm_kdsp.buffer_index].kdsb_addr[$kgm_kdsp.offset] + if $kgm_kdsp_actual->kds_readlast != $kgm_kdsp_actual->kds_bufindx + set $kgm_kds_bufptr = &$kgm_kdsp_actual->kds_records[$kgm_kdsp_actual->kds_bufindx] + while (($kgm_kds_bufptr > &$kgm_kdsp_actual->kds_records[$kgm_kdsp_actual->kds_readlast]) && ($kgm_entry_count > 0)) + set $kgm_kds_bufptr = $kgm_kds_bufptr - 1 + set $kgm_entry_count = $kgm_entry_count - 1 + showkerneldebugbufferentry $kgm_kds_bufptr + end + end + set $kgm_kdsp = $kgm_kdsp_actual->kds_next + end + end + else + printf "Trace buffer not enabled\n" + end +end + +document showkerneldebugbuffercpu +Syntax: showkerneldebugbuffercpu +| Prints the last N entries in the kernel debug buffer for CPU x. +end + +define showkerneldebugbuffer + # 0x80000000 == KDBG_BFINIT + if (kd_ctrl_page.kdebug_flags & 0x80000000) + + set $kgm_entrycount = (int) $arg0 + + if $kgm_entrycount == 0 + printf " is 0, dumping 50 entries per cpu\n" + set $kgm_entrycount = 50 + end + + set $kgm_cpu = (int) 0 + + while $kgm_cpu < kd_cpus + showkerneldebugbuffercpu $kgm_cpu $kgm_entrycount + set $kgm_cpu = $kgm_cpu + 1 + end + else + printf "Trace buffer not enabled\n" + end +end + +document showkerneldebugbuffer +Syntax: showkerneldebugbuffer +| Prints the last N entries in the kernel debug buffer per cpu. i.e. showkerneldebugbuffer 50 will +| display the last 50 entries in each CPU's debug buffer. +end + +define showallvmstats + printf " pid command #ents wired vsize rsize max rsize\n" + printf " (pages) (pages) (pages) (pages)\n" + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_procp = (struct proc *)($kgm_taskp->bsd_info) + set $kgm_mapp = (struct _vm_map *)($kgm_taskp->map) + printf "%8d %17s %8d %15d %15d %15d %15d\n", $kgm_procp->p_pid, $kgm_procp->p_comm, $kgm_mapp->hdr.nentries, $kgm_mapp->pmap->stats.wired_count, $kgm_mapp->size >> 12, $kgm_mapp->pmap->stats.resident_count, $kgm_mapp->pmap->stats.resident_max + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end + +document showallvmstats +Syntax: showallvmstats +| prints a summary of vm statistics in a table format +end + +define memstats + if ($kgm_mtype == $kgm_mtype_arm) + printf "kern_memorystatus_level: %8d\n", kern_memorystatus_level + end + printf "vm_page_throttled_count: %8d\n", vm_page_throttled_count + printf "vm_page_active_count: %8d\n", vm_page_active_count + printf "vm_page_inactive_count: %8d\n", vm_page_inactive_count + printf "vm_page_wire_count: %8d\n", vm_page_wire_count + printf "vm_page_free_count: %8d\n", vm_page_free_count + printf "vm_page_purgeable_count: %8d\n", vm_page_purgeable_count + printf "vm_page_inactive_target: %8d\n", vm_page_inactive_target + printf "vm_page_free_target: %8d\n", vm_page_free_target + printf "inuse_ptepages_count: %8d\n", inuse_ptepages_count + printf "vm_page_free_reserved: %8d\n", vm_page_free_reserved +end + +document memstats +Syntax: (gdb) memstats +| Prints out a summary of various memory statistics. In particular vm_page_wire_count should +| be greater than 2K or you are under memory pressure. +end + +define show_user_registers + showuserregisters $arg0 +end + +document show_user_registers +Syntax: show_user_registers +| Display user registers associated with a kernel thread +| properly displays the 32 bit or 64 bit registers for intel architecture +end + +define _cmp + set $cmp0 = $arg0 + set $cmp1 = $arg1 + + # check for end of string. cmp0 can be longer than cmp1. it + # can't be shorter. + if $cmp1 == '\0' + set $kgm_strcmp_result = 0 + set $kgm_strcmp_done = 1 + end + + if !$kgm_strcmp_done && $cmp0 == '\0' + set $kgm_strcmp_result = -1 + set $kgm_strcmp_done = 1 + end + + # do they match? + if !$kgm_strcmp_done + set $kgm_strcmp_result = (uint8_t) $cmp0 - (uint8_t) $cmp1 + if $kgm_strcmp_result != 0 + set $kgm_strcmp_done = 1 + end + end +end + +define _cmp_arg64 + set $cmp = $arg1 + set $masked = $cmp & 0xFF + _cmp $arg0[0] $masked + + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[1] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[2] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[3] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[4] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[5] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[6] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[7] $masked + end +end + +define strcmp_arg_pack64 + set $kgm_strcmp_arg = ((((((((((((((uint64_t) $arg7 << 8) | $arg6) << 8) | $arg5) << 8) | $arg4) << 8) | $arg3) << 8) | $arg2) << 8) | $arg1) << 8) | $arg0 +end + +document strcmp_arg_pack64 +Syntax: strcmp_arg_pack64 +| Packs a string given as 8 character arguments into a 64-bit int stored in +| $kgm_strcmp_arg. Use 0 or '\0' for unused arguments. The encoded string +| is suitable for use by strcmp_nomalloc and setfindregistrystr. +| e.g., strcmp_arg_pack64 'H' 'e' 'l' 'l' 'o' 0 0 0 +| packs "Hello" into $kgm_strcmp_arg. +| +end + +define strcmp_nomalloc + set $str = $arg0 + set $count = $argc - 1 + + set $kgm_strcmp_result = 0 + set $kgm_strcmp_done = 0 + + if $count > 0 + _cmp_arg64 $str $arg1 + end + if !$kgm_strcmp_done && $count > 1 + set $str = $str + 8 + _cmp_arg64 $str $arg2 + end + if !$kgm_strcmp_done && $count > 2 + set $str = $str + 8 + _cmp_arg64 $str $arg3 + end + if !$kgm_strcmp_done && $count > 3 + set $str = $str + 8 + _cmp_arg64 $str $arg4 + end + if !$kgm_strcmp_done && $count > 4 + set $str = $str + 8 + _cmp_arg64 $str $arg5 + end + if !$kgm_strcmp_done && $count > 5 + set $str = $str + 8 + _cmp_arg64 $str $arg6 + end + if !$kgm_strcmp_done && $count > 6 + set $str = $str + 8 + _cmp_arg64 $str $arg7 + end + if !$kgm_strcmp_done && $count > 7 + set $str = $str + 8 + _cmp_arg64 $str $arg8 + end + if !$kgm_strcmp_done && $count > 8 + set $str = $str + 8 + _cmp_arg64 $str $arg9 + end +end + +document strcmp_nomalloc +Syntax: strcmp_nomalloc [b] [c] [d] [e] [f] [g] [h] [i] +| Given a pre-allocated , perform a string compare with the +| encoded string stored in arguments a - i. The result is stored in +| $kgm_strcmp_result. +| +| For example, the following will result in $kgm_strcmp_result == 0: +| strcmp_arg_pack64 'D' 'a' 'r' 'w' 'i' 'n' ' ' 'K' +| strcmp_nomalloc version $kgm_strcmp_arg +end + +define memcpy + set $kgm_dst = (unsigned char *)$arg0 + set $kgm_src = (unsigned char *)$arg1 + set $kgm_count = $arg2 + + # printf "src %p dst %p len %d\n", $kgm_src, $kgm_dst, $kgm_count + + while ($kgm_count >= 8) + set *(unsigned long long *)$kgm_dst = *(unsigned long long *)$kgm_src + + set $kgm_dst = $kgm_dst + 8 + set $kgm_src = $kgm_src + 8 + set $kgm_count = $kgm_count - 8 + end + while ($kgm_count > 0) + set *$kgm_dst = *$kgm_src + + set $kgm_dst = $kgm_dst + 1 + set $kgm_src = $kgm_src + 1 + set $kgm_count = $kgm_count - 1 + end +end + +document memcpy +Syntax: memcpy +| Given two addresses that are accessible by the debugger, perform +| a memory copy of bytes from to +end + +# _pci_cfg_addr_value $addr $size +define _pci_cfg_addr_value + readphysint $arg0 $arg1 $kgm_lcpu_self + set $kgm_pci_cfg_value = $kgm_readphysint_result +end + + +set $kgm_pci_cfg_init = 0 +define _pci_cfg_init + # get this from the registry if it exists there + if $kgm_pci_cfg_init == 0 + strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P' + set $AppleACP = $kgm_strcmp_arg + strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r' + set $IPlatfor = $kgm_strcmp_arg + strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0 + set $mExpert = $kgm_strcmp_arg + setfindregistrystr $AppleACP $IPlatfor $mExpert + + set $olddepth = $kgm_reg_depth_max + set $kgm_reg_depth_max = 2 + _findregistryentry + set $kgm_reg_depth_max = $olddepth + + if $kgm_registry_entry + strcmp_arg_pack64 'a' 'c' 'p' 'i' '-' 'm' 'm' 'c' + set $acpi_mmc = $kgm_strcmp_arg + strcmp_arg_pack64 'f' 'g' '-' 's' 'e' 'g' '0' 0 + set $fg_seg0 = $kgm_strcmp_arg + setfindregistrystr $acpi_mmc $fg_seg0 + + _findregistryprop $kgm_registry_entry + if $kgm_registry_value + set $kgm_pci_cfg_base = ((OSNumber *) $kgm_registry_value)->value + set $kgm_pci_cfg_init = 1 + end + end + end + + # search for 0:0:0 in likely places if the above fails + if $kgm_pci_cfg_init == 0 + set $kgm_pci_cfg_base = 0xF0000000 + while $kgm_pci_cfg_init == 0 && $kgm_pci_cfg_base > 0xA0000000 + _pci_cfg_addr_value $kgm_pci_cfg_base 8 + if $kgm_pci_cfg_value > 0x0 && $kgm_pci_cfg_value < 0xFF + set $kgm_pci_cfg_init = 1 + else + set $kgm_pci_cfg_base = $kgm_pci_cfg_base - 0x10000000 + end + end + end +end + +# _pci_cfg_addr $bus $dev $fcn $off +define _pci_cfg_addr + set $bus = $arg0 + set $dev = $arg1 + set $fcn = $arg2 + set $off = $arg3 + + _pci_cfg_init + set $kgm_pci_cfg_addr = $kgm_pci_cfg_base | ($bus << 20) | ($dev << 15) | ($fcn << 12) | $off +end + +define _pci_cfg_value + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + _pci_cfg_addr_value $kgm_pci_cfg_addr $arg4 +end + +define pci_cfg_read8 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 8 + printf "%08X: %02X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +define pci_cfg_read16 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 16 + printf "%08X: %04X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +define pci_cfg_read32 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 32 + printf "%08X: %08X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +document pci_cfg_read8 +Syntax: (gdb) pci_cfg_read8 +| read 8 bits for the given of the pci device located at +| ::. +end + +document pci_cfg_read16 +Syntax: (gdb) pci_cfg_read +| read 16 bits for the given of the pci device located at +| ::. +end + +document pci_cfg_read32 +Syntax: (gdb) pci_cfg_read +| read 32 bits for the given of the pci device located at +| ::. +end + +define pci_cfg_write8 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 8 $arg4 $kgm_lcpu_self +end + +define pci_cfg_write16 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 16 $arg4 $kgm_lcpu_self +end + +define pci_cfg_write32 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 32 $arg4 $kgm_lcpu_self +end + +document pci_cfg_write8 +Syntax: (gdb) pci_cfg_write8 +| write an 8-bit into the given of the pci device located at +| ::. +end + +document pci_cfg_write16 +Syntax: (gdb) pci_cfg_write16 +| write a 16-bit into the given of the pci device located at +| ::. +end + +document pci_cfg_write32 +Syntax: (gdb) pci_cfg_write32 +| write a 32-bit into the given of the pci device located at +| ::. +end + + +define pci_cfg_dump + set $bus = $arg0 + set $dev = $arg1 + set $fcn = $arg2 + set $off = 0 + + # check for a valid pci device + _pci_cfg_value $bus $dev $fcn $off 8 + if $kgm_pci_cfg_value > 0x0 && $kgm_pci_cfg_value < 0xff + printf " address: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" + printf "---------------------------------------------------------" + + while $off < 256 + _pci_cfg_value $bus $dev $fcn $off 32 + if ($off & 0xF) == 0 + printf "\n%08X: ", $kgm_pci_cfg_addr + end + printf "%02X %02X %02X %02X ", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF + set $off = $off + 4 + end + printf "\n" + + # check for pcie extended capability config space + _pci_cfg_value $bus $dev $fcn $off 8 + if $kgm_pci_cfg_value < 0xff + while $off < 4096 + _pci_cfg_value $bus $dev $fcn $off 32 + if ($off & 0xF) == 0 + printf "\n%08X: ", $kgm_pci_cfg_addr + end + printf "%02X %02X %02X %02X ", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF + set $off = $off + 4 + end + printf "\n" + end + end +end + +document pci_cfg_dump +Syntax: (gdb) pci_cfg_dump +| dump config space for the pci device located at :: +| if you specify an invalid/inaccessible pci device, nothing will be +| printed out. +end + +set $kgm_pci_cfg_bus_start = 0 +set $kgm_pci_cfg_bus_max = 8 +set $kgm_pci_cfg_device_max = 32 +set $kgm_pci_cfg_function_max = 8 +define _pci_cfg_scan + set $dump = $arg0 + + set $bus = $kgm_pci_cfg_bus_start + while $bus < $kgm_pci_cfg_bus_max + # check for bus:0:0 to see if we should + # probe this bus further + _pci_cfg_value $bus 0x0 0x0 0x0 32 + if $kgm_pci_cfg_value > 0 && $kgm_pci_cfg_value < 0xFFFFFFFF + + set $dev = 0 + while $dev < $kgm_pci_cfg_device_max + + set $fcn = 0 + while $fcn < $kgm_pci_cfg_function_max + _pci_cfg_value $bus $dev $fcn 0x0 32 + if $kgm_pci_cfg_value > 0 && $kgm_pci_cfg_value < 0xFFFFFFFF + if $dump == 0 + printf "%03X:%03X:%03X: %02X%02X %02X%02X", $bus, $dev, $fcn, ($kgm_pci_cfg_value >> 8) & 0xFF, $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF + _pci_cfg_value $bus $dev $fcn 0x8 32 + printf " %02X | %02X%02X%02X\n", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF + else + printf " device: %03X:%03X:%03X\n", $bus, $dev, $fcn + pci_cfg_dump $bus $dev $fcn + printf "\n" + end + end + set $fcn = $fcn + 1 + end + set $dev = $dev + 1 + end + end + set $bus = $bus + 1 + end +end + +define pci_cfg_dump_all + _pci_cfg_scan 1 +end + +document pci_cfg_dump_all +Syntax: (gdb) pci_cfg_dump_all +| dump config spaces for scanned pci devices. the number of busses to scan +| is stored in $kgm_pci_cfg_bus_max. the default for that is 8. you can also +| specify the starting bus with $kgm_pci_cfg_bus_start. +end + +define pci_cfg_scan + printf "bus:dev:fcn: vendor device rev | class\n" + printf "---------------------------------------\n" + _pci_cfg_scan 0 +end + +document pci_cfg_scan +Syntax: (gdb) pci_cfg_scan +| scan for pci devices. the number of busses to scan is stored in +| $kgm_pci_cfg_bus_max. the default for that is 8. you can also specify the +| starting bus with $kgm_pci_cfg_bus_start. +end + +define readioportint + set $kgm_readioportint_result = 0xBAD10AD + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readioport_req_t) + set $kgm_pkt = (kdp_readioport_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READIOPORT + set $kgm_pkt->hdr.len = sizeof(kdp_readioport_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint16_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = (uint16_t)$arg2 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readioport_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + if $arg1 == 8 + set $kgm_readioportint_result = *((uint8_t *) $kgm_pkt->data) + end + if $arg1 == 16 + set $kgm_readioportint_result = *((uint16_t *) $kgm_pkt->data) + end + if $arg1 == 32 + set $kgm_readioportint_result = *((uint32_t *) $kgm_pkt->data) + end + end +end + +define readioport8 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 8 $lcpu + output /a $arg0 + printf ":\t0x%02hhx\n", $kgm_readioportint_result +end + +define readioport16 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 16 $lcpu + output /a $arg0 + printf ":\t0x%04hx\n", $kgm_readioportint_result +end + +define readioport32 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 32 $lcpu + output /a $arg0 + printf ":\t0x%08x\n", $kgm_readioportint_result +end + +document readioport8 +| See readioport32. +end + +document readioport16 +| See readioport32. +end + +document readioport32 +Syntax: (gdb) readioport32 [lcpu (kernel's numbering convention)] +| Read value stored in the specified IO port. The CPU can be optionally +| specified as well. +end + +define writeioportint + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writeioport_req_t) + set $kgm_pkt = (kdp_writeioport_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEIOPORT + set $kgm_pkt->hdr.len = sizeof(kdp_writeioport_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint16_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = (uint16_t)$arg3 + if $arg1 == 8 + set *(uint8_t *)$kgm_pkt->data = (uint8_t)$arg2 + end + if $arg1 == 16 + set *(uint16_t *)$kgm_pkt->data = (uint16_t)$arg2 + end + if $arg1 == 32 + set *(uint32_t *)$kgm_pkt->data = (uint32_t)$arg2 + end + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writeioport_reply_t *)&manual_pkt.data + set $kgm_writeioportint_result = $kgm_pkt->error +end + +define writeioport8 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 8 $arg1 $lcpu +end + +define writeioport16 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 16 $arg1 $lcpu +end + +define writeioport32 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 32 $arg1 $lcpu +end + +document writeioport8 +| See writeioport32. +end + +document writeioport16 +| See writeioport32. +end + +document writeioport32 +Syntax: (gdb) writeioport32 [lcpu (kernel's numbering convention)] +| Write the value to the specified IO port. The size of the value is +| determined by the name of the command. The CPU used can be optionally +| specified. +end + +define readmsr64int + set $kgm_readmsr64int_result = 0xBAD10AD + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmsr64_req_t) + set $kgm_pkt = (kdp_readmsr64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMSR64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmsr64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint32_t)$arg0 + set $kgm_pkt->lcpu = (uint16_t)$arg1 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readmsr64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_readmsr64int_result = *((uint64_t *) $kgm_pkt->data) + end +end + +define readmsr64 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readmsr64int $arg0 $lcpu + output /a $arg0 + printf ":\t0x%016llx\n", $kgm_readmsr64int_result +end + +define writemsr64int + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writemsr64_req_t) + set $kgm_pkt = (kdp_writemsr64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEMSR64 + set $kgm_pkt->hdr.len = sizeof(kdp_writemsr64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint32_t)$arg0 + set $kgm_pkt->lcpu = (uint16_t)$arg2 + set *(uint64_t *)$kgm_pkt->data = (uint64_t)$arg1 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writemsr64_reply_t *)&manual_pkt.data + set $kgm_writemsr64int_result = $kgm_pkt->error +end + +define writemsr64 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writemsr64int $arg0 $arg1 $lcpu +end + +document writemsr64 +Syntax: (gdb) writemsr64 [lcpu (kernel's numbering convention)] +| Write to the specified MSR. The CPU can be optionally specified. +end + +document readmsr64 +Syntax: (gdb) readmsr64 [lcpu (kernel's numbering convention)] +| Read the specified MSR. The CPU can be optionally specified. +end + +# default if we can't find a registry entry +set $kgm_ioapic_addr = 0xFEC00000 +set $kgm_ioapic_init = 0 + +set $_ioapic_index_off = 0x00 +set $_ioapic_data_off = 0x10 +set $_ioapic_eoi_off = 0x40 + +set $_ioapic_index_id = 0x00 +set $_ioapic_index_ver = 0x01 +set $_ioapic_index_redir_base = 0x10 + +set $_apic_vector_mask = 0xFF +set $_apic_timer_tsc_deadline = 0x40000 +set $_apic_timer_periodic = 0x20000 +set $_apic_masked = 0x10000 +set $_apic_trigger_level = 0x08000 +set $_apic_polarity_high = 0x02000 +set $_apic_pending = 0x01000 + +define _ioapic_init + if $kgm_ioapic_init == 0 + strcmp_arg_pack64 'i' 'o' '-' 'a' 'p' 'i' 'c' 0 + setfindregistrystr $kgm_strcmp_arg + + set $olddepth = $kgm_reg_depth_max + set $kgm_reg_depth_max = 3 + _findregistryentry + set $kgm_reg_depth_max = $olddepth + + if $kgm_registry_entry + strcmp_arg_pack64 'P' 'h' 'y' 's' 'i' 'c' 'a' 'l' + set $Physical = $kgm_strcmp_arg + strcmp_arg_pack64 ' ' 'A' 'd' 'd' 'r' 'e' 's' 's' + set $_Address = $kgm_strcmp_arg + setfindregistrystr $Physical $_Address + + _findregistryprop $kgm_registry_entry + if $kgm_registry_value + set $kgm_ioapic_addr = ((OSNumber *) $kgm_registry_value)->value + end + end + set $kgm_ioapic_index_addr = $kgm_ioapic_addr + $_ioapic_index_off + set $kgm_ioapic_data_addr = $kgm_ioapic_addr + $_ioapic_data_off + set $kgm_ioapic_init = 1 + end +end + +define _ioapic_addr_value + _ioapic_init + writephysint $kgm_ioapic_index_addr 8 $arg0 $kgm_lcpu_self + if $argc > 1 + writephysint $kgm_ioapic_data_addr 32 $arg1 $kgm_lcpu_self + else + readphysint $kgm_ioapic_data_addr 32 $kgm_lcpu_self + set $kgm_ioapic_value = $kgm_readphysint_result + end +end + +define _apic_print + set $value = $arg0 + + printf "[VEC=%3d", $value & $_apic_vector_mask + if $value & $_apic_masked + printf " MASK=yes" + else + printf " MASK=no " + end + + if $value & $_apic_trigger_level + printf " TRIG=level" + else + printf " TRIG=edge " + end + + if $value & $_apic_polarity_high + printf " POL=high" + else + printf " POL=low " + end + + if $value & $_apic_pending + printf " PEND=yes" + else + printf " PEND=no " + end + + if $value & $_apic_timer_periodic + printf " PERIODIC" + end + if $value & $_apic_timer_tsc_deadline + printf " TSC_DEADLINE" + end + + printf "]\n" +end + +define ioapic_read32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_read32 not supported on this architecture.\n" + else + _ioapic_addr_value $arg0 + printf "IOAPIC[0x%02X]: 0x%08X\n", $arg0, $kgm_ioapic_value + end +end + +document ioapic_read32 +Syntax: (gdb) ioapic_read +| Read the IOAPIC register at the offset specified. +end + +define ioapic_write32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_write32 not supported on this architecture.\n" + else + _ioapic_addr_value $arg0 $arg1 + end +end + +document ioapic_write32 +Syntax: (gdb) ioapic_write32 +| Write the IOAPIC register at the offset specified. +end + +define ioapic_dump + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_dump not supported on this architecture.\n" + else + # id + _ioapic_addr_value $_ioapic_index_id + printf "IOAPIC[0x%02X] ID: 0x%08X\n", $_ioapic_index_id, $kgm_ioapic_value + + # version + _ioapic_addr_value $_ioapic_index_ver + set $maxredir = (($kgm_ioapic_value & 0xFF0000) >> 16) + 1 + + printf "IOAPIC[0x%02X] VERSION: 0x%08X [", $_ioapic_index_ver, $kgm_ioapic_value + printf "MAXREDIR=%02d PRQ=%d VERSION=0x%02X]\n", $maxredir, ($kgm_ioapic_value >> 15) & 0x1, $kgm_ioapic_value & 0xFF + + # all the redir entries + set $i = 0 + while $i < $maxredir + set $addr0 = $_ioapic_index_redir_base + ($i << 1) + set $addr1 = $addr0 + 1 + _ioapic_addr_value $addr1 + printf "IOAPIC[0x%02X] IOREDIR%02d: 0x%08X", $addr0, $i, $kgm_ioapic_value + + _ioapic_addr_value $addr0 + printf "%08X ", $kgm_ioapic_value + _apic_print $kgm_ioapic_value + set $i = $i + 1 + end + end +end + +document ioapic_dump +Syntax: (gdb) ioapic_dump +| Dump all the IOAPIC entries. +end + + +set $_lapic_base_addr = 0xFEE00000 +set $_lapic_id = 0x20 +set $_lapic_version = 0x30 +set $_lapic_tpr = 0x80 +set $_lapic_apr = 0x90 +set $_lapic_ppr = 0xA0 +set $_lapic_eoi = 0xB0 +set $_lapic_ldr = 0xD0 +set $_lapic_dfr = 0xE0 +set $_lapic_sivr = 0xF0 + +set $_lapic_isr_size = 0x10 +set $_lapic_isr_num = 8 +set $_lapic_isr0 = 0x100 +set $_lapic_tmr0 = 0x180 +set $_lapic_irr0 = 0x200 + +set $_lapic_esr = 0x280 +set $_lapic_esr_register = 0x80 +set $_lapic_esr_recv_vect = 0x40 +set $_lapic_esr_send_vect = 0x20 + +set $_lapic_icr0 = 0x300 +set $_lapic_icr1 = 0x310 + +set $_lapic_lvt_timer = 0x320 +set $_lapic_lvt_thermal = 0x330 +set $_lapic_lvt_pmcr = 0x340 +set $_lapic_lvt_lint0 = 0x350 +set $_lapic_lvt_lint1 = 0x360 +set $_lapic_lvt_error = 0x370 + +set $_lapic_icr = 0x380 +set $_lapic_ccr = 0x390 +set $_lapic_dcr = 0x3E0 + +set $_apic_cfg_msr = 0x1B +set $_apic_cfg_msr_x2EN = 0x00000C00 +set $_x2apic_enabled = -1 + +# _lapic_addr $offset returns the actual address to use +define _lapic_addr + if $_x2apic_enabled < 0 + readmsr64int $_apic_cfg_msr $kgm_lcpu_self + if ($kgm_readmsr64int_result & $_apic_cfg_msr_x2EN) == $_apic_cfg_msr_x2EN + set $_x2apic_enabled = 1 + else + set $_x2apic_enabled = 0 + end + end + + if $_x2apic_enabled + # x2APIC addresses are MSRs that use xAPIC offsets that + # are 4-bit shifted + set $kgm_lapic_addr = $arg0 >> 4 + else + set $kgm_lapic_addr = $_lapic_base_addr + $arg0 + end +end + +# _lapic_addr_value $offset $lcpu +define _lapic_addr_value + _lapic_addr $arg0 + if $_x2apic_enabled + readmsr64int $kgm_lapic_addr $arg1 + set $kgm_lapic_value = $kgm_readmsr64int_result + else + readphysint $kgm_lapic_addr 32 $arg1 + set $kgm_lapic_value = $kgm_readphysint_result + end +end + +# lapic_read32 $offset [$lcpu] +define lapic_read32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_read32 not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + _lapic_addr_value $arg0 $lcpu + printf "LAPIC[0x%03X]: 0x%08X\n", $arg0, $kgm_lapic_value + end +end + +document lapic_read32 +Syntax: (gdb) apic_read32_cpu [lcpu (kernel's numbering convention)] +| Read the LAPIC register at the offset specified. The CPU can be optionally +| specified. +end + +# lapic_write32 $offset $value [$lcpu] +define lapic_write32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_write32_cpu not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + + _lapic_addr $arg0 + if $_x2apic_enabled + writemsr64int $kgm_lapic_addr $arg1 $lcpu + else + writephysint $kgm_lapic_addr 32 $arg1 $lcpu + end + end +end + +document lapic_write32 +Syntax: (gdb) lapic_write32 [lcpu (kernel's numbering convention)] +| Write the LAPIC register at the offset specified. The CPU can be optionally +| specified. +end + +# lapic_dump [lcpu] +define lapic_dump + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_dump not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 0 + set $lcpu = $arg0 + end + + _lapic_addr_value $_lapic_id $lcpu + + # the above also figures out if we're using an xAPIC or an x2APIC + printf "LAPIC operating mode: " + if $_x2apic_enabled + printf " x2APIC\n" + else + printf " xAPIC\n" + end + + printf "LAPIC[0x%03X] ID: 0x%08X\n", $_lapic_id, $kgm_lapic_value + + _lapic_addr_value $_lapic_version $lcpu + set $lvt_num = ($kgm_lapic_value >> 16) + 1 + printf "LAPIC[0x%03X] VERSION: 0x%08X [VERSION=%d MaxLVT=%d]\n", $_lapic_version, $kgm_lapic_value, $kgm_lapic_value & 0xFF, $lvt_num + + _lapic_addr_value $_lapic_tpr $lcpu + printf "LAPIC[0x%03X] TASK PRIORITY: 0x%08X\n", $_lapic_tpr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ppr $lcpu + printf "LAPIC[0x%03X] PROCESSOR PRIORITY: 0x%08X\n", $_lapic_ppr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ldr $lcpu + printf "LAPIC[0x%03X] LOGICAL DEST: 0x%08X\n", $_lapic_ldr, $kgm_lapic_value + + _lapic_addr_value $_lapic_dfr $lcpu + printf "LAPIC[0x%03X] DEST FORMAT: 0x%08X\n", $_lapic_dfr, $kgm_lapic_value + + _lapic_addr_value $_lapic_sivr $lcpu + printf "LAPIC[0x%03X] SPURIOUS VECTOR: 0x%08X [VEC=%3d ENABLED=%d]\n", $_lapic_sivr, $kgm_lapic_value, $kgm_lapic_value & $_apic_vector_mask, ($kgm_lapic_value & 0x100) >> 8, + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_isr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] ISR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_tmr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] TMR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_irr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] IRR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + _lapic_addr_value $_lapic_esr $lcpu + printf "LAPIC[0x%03X] ERROR STATUS: 0x%08X ", $_lapic_esr, $kgm_lapic_value + if $kgm_lapic_value + printf "[" + end + if $kgm_lapic_value & $_lapic_esr_register + printf "Register " + end + if $kgm_lapic_value & $_lapic_esr_recv_vect + printf "Received Vector " + end + if $kgm_lapic_value & $_lapic_esr_send_vect + printf "Send Vector" + end + if $kgm_lapic_value + printf "]" + end + printf "\n" + + _lapic_addr_value $_lapic_icr1 $lcpu + printf "LAPIC[0x%03X] Interrupt Command: 0x%08X [DEST=%d]\n", $_lapic_icr0, $kgm_lapic_value, $kgm_lapic_value >> 24 + _lapic_addr_value $_lapic_icr0 $lcpu + printf " 0x%08X ", $kgm_lapic_value + _apic_print $kgm_lapic_value + + if $lvt_num > 0 + _lapic_addr_value $_lapic_lvt_timer $lcpu + printf "LAPIC[0x%03X] LVT Timer: 0x%08X ", $_lapic_lvt_timer, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 1 + _lapic_addr_value $_lapic_lvt_lint0 $lcpu + printf "LAPIC[0x%03X] LVT LINT0: 0x%08X ", $_lapic_lvt_lint0, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 2 + _lapic_addr_value $_lapic_lvt_lint1 $lcpu + printf "LAPIC[0x%03X] LVT LINT1: 0x%08X ", $_lapic_lvt_lint1, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 3 + _lapic_addr_value $_lapic_lvt_error $lcpu + printf "LAPIC[0x%03X] LVT Error: 0x%08X ", $_lapic_lvt_error, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 4 + _lapic_addr_value $_lapic_lvt_pmcr $lcpu + printf "LAPIC[0x%03X] LVT PerfMon: 0x%08X ", $_lapic_lvt_pmcr, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 5 + _lapic_addr_value $_lapic_lvt_thermal $lcpu + printf "LAPIC[0x%03X] LVT Thermal: 0x%08X ", $_lapic_lvt_thermal, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + _lapic_addr_value $_lapic_dcr $lcpu + printf "LAPIC[0x%03X] Timer Divide: 0x%08X [Divide by ", $_lapic_dcr, $kgm_lapic_value + set $kgm_lapic_value = ($kgm_lapic_value & 0x8) >> 1 | $kgm_lapic_value & 0x3 + if $kgm_lapic_value == 0x7 + printf "1]\n" + else + printf "%d]\n", 2 << $kgm_lapic_value + end + + _lapic_addr_value $_lapic_icr $lcpu + printf "LAPIC[0x%03X] Timer Init Count: 0x%08X\n", $_lapic_icr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ccr $lcpu + printf "LAPIC[0x%03X] Timer Cur Count: 0x%08X\n", $_lapic_ccr, $kgm_lapic_value + end +end + +document lapic_dump +Syntax: (gdb) lapic_dump [lcpu (kernel's numbering convention)] +| Dump all the LAPIC entries. The CPU can be optionally specified. +end + +define showknoteheader + printf " knote filter ident kn_ptr status\n" +end + +define showknoteint + set $kgm_knotep = ((struct knote *) $arg0) + printf " " + showptr $kgm_knotep + printf " " + set $kgm_filt = -$kgm_knotep->kn_kevent.filter + if ($kgm_filt == 1) + printf "EVFILT_READ " + end + if ($kgm_filt == 2) + printf "EVFILT_WRITE " + end + if ($kgm_filt == 3) + printf "EVFILT_AIO " + end + if ($kgm_filt == 4) + printf "EVFILT_VNODE " + end + if ($kgm_filt == 5) + printf "EVFILT_PROC " + end + if ($kgm_filt == 6) + printf "EVFILT_SIGNAL " + end + if ($kgm_filt == 7) + printf "EVFILT_TIMER " + end + if ($kgm_filt == 8) + printf "EVFILT_MACHPORT" + end + if ($kgm_filt == 9) + printf "EVFILT_FS " + end + if ($kgm_filt == 10) + printf "EVFILT_USER " + end + if ($kgm_filt == 11) + printf "EVFILT_SESSION " + end + printf "%7d ", $kgm_knotep->kn_kevent.ident + showptr $kgm_knotep->kn_ptr.p_fp + printf " " + if ($kgm_knotep->kn_status == 0) + printf "-" + else + if ($kgm_knotep->kn_status & 0x01) + printf "A" + end + if ($kgm_knotep->kn_status & 0x02) + printf "Q" + end + if ($kgm_knotep->kn_status & 0x04) + printf "Dis" + end + if ($kgm_knotep->kn_status & 0x08) + printf "Dr" + end + if ($kgm_knotep->kn_status & 0x10) + printf "Uw" + end + if ($kgm_knotep->kn_status & 0x20) + printf "Att" + end + if ($kgm_knotep->kn_status & 0x40) + printf "Stq" + end + end + printf "\n" +end + +define showprocknotes + showknoteheader + set $kgm_fdp = ((proc_t)$arg0)->p_fd + set $kgm_knlist = $kgm_fdp->fd_knlist + set $i = 0 + while (($i < $kgm_fdp->fd_knlistsize) && ($kgm_knlist != 0)) + set $kgm_kn = ((struct knote *)$kgm_knlist[$i].slh_first) + while ($kgm_kn != 0) + showknoteint $kgm_kn + set $kgm_kn = ((struct knote *)$kgm_kn->kn_link.sle_next) + end + set $i = $i + 1 + end + set $kgm_knhash = $kgm_fdp->fd_knhash + set $i = 0 + while (($i < $kgm_fdp->fd_knhashmask + 1) && ($kgm_knhash != 0)) + set $kgm_kn = ((struct knote *)$kgm_knhash[$i].slh_first) + while ($kgm_kn != 0) + showknoteint $kgm_kn + set $kgm_kn = ((struct knote *)$kgm_kn->kn_link.sle_next) + end + set $i = $i + 1 + end +end + +define showallknotes + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + showprocknotes $kgm_taskp->bsd_info + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showprocknotes +Syntax: showprocknotes +| Displays filter and status information for every kevent registered for +| the process. +end + +# +# Device node related debug macros +# + +define _showtty + set $kgm_tty = (struct tty *) $arg0 + printf "tty struct at " + showptr $kgm_tty + printf "\n" + printf "-last input to raw queue:\n" + p $kgm_tty->t_rawq->c_cs + printf "-last input to canonical queue:\n" + p $kgm_tty->t_canq->c_cs + printf "-last output data:\n" + p $kgm_tty->t_outq->c_cs + printf "state:\n" + if ($kgm_tty->t_state & 0x00000001) + printf " TS_SO_OLOWAT (Wake up when output <= low water)\n" + end + if ($kgm_tty->t_state & 0x00000002) + printf " TS_ASYNC (async I/O mode)\n" + else + printf " - (synchronous I/O mode)\n" + end + if ($kgm_tty->t_state & 0x00000004) + printf " TS_BUSY (Draining output)\n" + end + if ($kgm_tty->t_state & 0x00000008) + printf " TS_CARR_ON (Carrier is present)\n" + else + printf " - (Carrier is NOT present)\n" + end + if ($kgm_tty->t_state & 0x00000010) + printf " TS_FLUSH (Outq has been flushed during DMA)\n" + end + if ($kgm_tty->t_state & 0x00000020) + printf " TS_ISOPEN (Open has completed)\n" + else + printf " - (Open has NOT completed)\n" + end + if ($kgm_tty->t_state & 0x00000040) + printf " TS_TBLOCK (Further input blocked)\n" + end + if ($kgm_tty->t_state & 0x00000080) + printf " TS_TIMEOUT (Wait for output char processing)\n" + end + if ($kgm_tty->t_state & 0x00000100) + printf " TS_TTSTOP (Output paused)\n" + end + if ($kgm_tty->t_state & 0x00000200) + printf " TS_WOPEN (Open in progress)\n" + end + if ($kgm_tty->t_state & 0x00000400) + printf " TS_XCLUDE (Tty requires exclusivity)\n" + end + if ($kgm_tty->t_state & 0x00000800) + printf " TS_BKSL (State for lowercase \\ work)\n" + end + if ($kgm_tty->t_state & 0x00001000) + printf " TS_CNTTB (Counting tab width, ignore FLUSHO)\n" + end + if ($kgm_tty->t_state & 0x00002000) + printf " TS_ERASE (Within a \\.../ for PRTRUB)\n" + end + if ($kgm_tty->t_state & 0x00004000) + printf " TS_LNCH (Next character is literal)\n" + end + if ($kgm_tty->t_state & 0x00008000) + printf " TS_TYPEN (Retyping suspended input (PENDIN))\n" + end + if ($kgm_tty->t_state & 0x00010000) + printf " TS_CAN_BYPASS_L_RINT (Device in "raw" mode)\n" + end + if ($kgm_tty->t_state & 0x00020000) + printf " TS_CONNECTED (Connection open)\n" + else + printf " - (Connection NOT open)\n" + end + if ($kgm_tty->t_state & 0x00040000) + printf " TS_SNOOP (Device is being snooped on)\n" + end + if ($kgm_tty->t_state & 0x80000) + printf " TS_SO_OCOMPLETE (Wake up when output completes)\n" + end + if ($kgm_tty->t_state & 0x00100000) + printf " TS_ZOMBIE (Connection lost)\n" + end + if ($kgm_tty->t_state & 0x00200000) + printf " TS_CAR_OFLOW (For MDMBUF - handle in driver)\n" + end + if ($kgm_tty->t_state & 0x00400000) + printf " TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)\n" + end + if ($kgm_tty->t_state & 0x00800000) + printf " TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)\n" + end + # xxx todo: do we care about decoding flags? + printf "flags: 0x%08x\n", $kgm_tty->t_flags + printf "foreground process group: " + showptr $kgm_tty->t_pgrp + printf "\n" + printf "enclosing session: " + showptr $kgm_tty->t_session + printf "\n" + printf "Termios:\n" + # XXX todo: decode these flags, someday + printf " Input flags: 0x%08x\n", $kgm_tty->t_termios.c_iflag + printf " Output flags: 0x%08x\n", $kgm_tty->t_termios.c_oflag + printf " Control flags: 0x%08x\n", $kgm_tty->t_termios.c_cflag + printf " Local flags: 0x%08x\n", $kgm_tty->t_termios.c_lflag + printf " Input speed: %d\n", $kgm_tty->t_termios.c_ispeed + printf " Output speed: %d\n", $kgm_tty->t_termios.c_ospeed + # XXX todo: useful to decode t_winsize? t_iokit? c_cc? anything else? + printf "high watermark: %d bytes\n", $kgm_tty->t_hiwat + printf "low watermark: %d bytes\n", $kgm_tty->t_lowat +end + +define _showwhohas + # _showwhohas + printf "fd " + printf "fileglob " +showptrhdrpad + printf "vnode " +showptrhdrpad + printf "process " +showptrhdrpad + printf "name\n" + + set $kgm_swh_devnode_dev = (((int) $arg0) << 24) | (int) $arg1 + # iterate all tasks to iterate all processes to iterate all + # open files in each process to see who has a given major/minor + # device open + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_procp = (proc_t) $kgm_taskp->bsd_info + set $kgm_spf_filedesc = $kgm_procp->p_fd + set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile + set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles + set $kgm_spf_count = 0 + while (($kgm_spf_ofiles != 0) && ($kgm_spf_count <= $kgm_spf_last)) + # only files currently open + if ($kgm_spf_ofiles[$kgm_spf_count] != 0) + set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob + if ($kgm_spf_fg->fg_type == 1) + # display fd #, fileglob & vnode address, proc name + set $kgm_swh_m_vnode = (vnode_t) $kgm_spf_fg->fg_data + set $kgm_swh_m_vtype = (enum vtype) $kgm_swh_m_vnode->v_type + if (($kgm_swh_m_vtype == VBLK) || ($kgm_swh_m_vtype == VCHR)) && ((((devnode_t *)$kgm_swh_m_vnode->v_data)->dn_typeinfo.dev) == $kgm_swh_devnode_dev) + printf "%-5d ", $kgm_spf_count + showptr $kgm_spf_fg + printf " " + showptr $kgm_swh_m_vnode + printf " " + showptr $kgm_procp + printf " %s\n", $kgm_procp->p_comm + end + end + end + set $kgm_spf_count = $kgm_spf_count + 1 + end + + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end + +define _showvnodedev_cpty + set $kgm_ptmx_major = (int) $arg0 + set $kgm_ptmx_minor = (int) $arg1 + set $kgm_ptmx_ioctl = _state.pis_ioctl_list[$kgm_ptmx_minor] + set $kgm_ptmx_ioctl = _state.pis_ioctl_list[$kgm_ptmx_minor] + printf " ptmx_ioctl struct at " + showptr $kgm_ptmx_ioctl + printf "\n" + printf " flags:\n" + if ($kgm_ptmx_ioctl->pt_flags & 0x0008) + printf " PF_PKT (packet mode)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0010) + printf " PF_STOPPED (user told stopped)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0020) + printf " PF_REMOTE (remote and flow controlled input)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0040) + printf " PF_NOSTOP" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0080) + printf " PF_UCNTL (user control mode)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0100) + printf " PF_UNLOCKED (slave unlock - master open resets)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0200) + printf " PF_OPEN_M (master is open)\n" + # XXX we should search for who has the master open, but + # XXX each master gets the same minor, even though it + # XXX gets a different vnode. we chold probably change + # XXX this, but to do it we would need some way of + # XXX expressing the information in the vnode structure + # XXX somewhere. If we *did* change it, it would buy us + # XXX the ability to determine who has the corresponding + # XXX master end of the pty open + else + printf " PF_OPEN_M (master is closed)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0400) + printf " PF_OPEN_S (slave is open)\n" + printf "---vvvvv--- fds open on this device ---vvvvv---\n" + _showwhohas ($kgm_ptmx_major) ($kgm_ptmx_minor) + printf "---^^^^^--- fds open on this device ---^^^^^---\n" + else + printf " - (slave is closed)\n" + end + printf "TTY Specific Information\n" + _showtty $kgm_ptmx_ioctl->pt_tty +end + +define showvnodedev + if ($argc == 1) + set $kgm_vnode = (vnode_t) $arg0 + set $kgm_vtype = (enum vtype) $kgm_vnode->v_type + if (($kgm_vtype == VBLK) || ($kgm_vtype == VCHR)) + set $kgm_devnode = (devnode_t *) $kgm_vnode->v_data + set $kgm_devnode_dev = $kgm_devnode->dn_typeinfo.dev + set $kgm_devnode_major = ($kgm_devnode_dev >> 24) & 0xff + set $kgm_devnode_minor = $kgm_devnode_dev & 0x00ffffff + + # boilerplate device information for a vnode + printf "Device Info:\n" + printf " vnode: " + showptr $kgm_vnode + printf "\n" + printf " type: " + if ($kgm_vtype == VBLK) + printf "VBLK " + end + if ($kgm_vtype == VCHR) + printf "VCHR" + end + printf "\n" + printf " name: %s\n", $kgm_vnode->v_name + printf " major, minor: %d, %d\n", $kgm_devnode_major, $kgm_devnode_minor + printf " mode 0%o\n", $kgm_devnode->dn_mode + printf " owner (u,g): %d %d", $kgm_devnode->dn_uid, $kgm_devnode->dn_gid + printf "\n" + + # decode device specific data + printf "Device Specific Information: " + if ($kgm_vtype == VBLK) + printf " Sorry, I do not know how to decode block devices yet!\n" + printf " Maybe you can write me!" + end + if ($kgm_vtype == VCHR) + # Device information; this is scanty + # range check + if ($kgm_devnode_major > 42) || ($kgm_devnode_major < 0) + printf "Invalid major #\n" + else + # static assignments in conf + if ($kgm_devnode_major == 0) + printf "Console mux device\n" + else + if ($kgm_devnode_major == 2) + printf "Current tty alias\n" + else + if ($kgm_devnode_major == 3) + printf "NULL device\n" + else + if ($kgm_devnode_major == 4) + printf "Old pty slave\n" + else + if ($kgm_devnode_major == 5) + printf "Old pty master\n" + else + if ($kgm_devnode_major == 6) + printf "Kernel log\n" + else + if ($kgm_devnode_major == 12) + printf "Memory devices\n" + else + # Statically linked dynamic assignments + if cdevsw[$kgm_devnode_major].d_open == ptmx_open + printf "Cloning pty master\n" + _showvnodedev_cpty ($kgm_devnode_major) ($kgm_devnode_minor) + else + if cdevsw[$kgm_devnode_major].d_open == ptsd_open + printf "Cloning pty slave\n" + _showvnodedev_cpty ($kgm_devnode_major) ($kgm_devnode_minor) + else + printf "RESERVED SLOT\n" + end + end + end + end + end + end + end + end + end + end + end + else + showptr $kgm_vnode + printf " is not a device\n" + end + else + printf "| Usage:\n|\n" + help showvnodedev + end +end +document showvnodedev +Syntax: (gdb) showvnodedev +| showvnodedev Display information about a device vnode +end + +define showtty + if ($argc == 1) + _showtty $arg0 + else + printf "| Usage:\n|\n" + help showtty + end +end +document showtty +Syntax: (gdb) showtty +| showtty Display information about a struct tty +end + +define showeventsourceobject + set $kgm_vt = *((void **) $arg1) + if $kgm_lp64 + set $kgm_vt = $kgm_vt - 16 + end + pcprint $kgm_vt +end +document showeventsourceobject +Syntax: (gdb) showeventsourceobject +| Routine to display information about an IOEventSource subclass. +end + +define showworkloopallocator + set $kgm_workloop = (struct IOWorkLoop*)$arg0 + set $kgm_bt = (void**)$kgm_workloop->reserved->allocationBacktrace + set $kgm_bt_count = 0 + while $kgm_bt_count != (sizeof(IOWorkLoop::ExpansionData.allocationBacktrace) / sizeof(IOWorkLoop::ExpansionData.allocationBacktrace[0])) + set $kgm_frame_address = (void*)$kgm_bt[$kgm_bt_count] + if $kgm_frame_address != 0 + if (((unsigned long) $kgm_frame_address < (unsigned long) &_mh_execute_header || \ + (unsigned long) $kgm_frame_address >= (unsigned long) &last_kernel_symbol ) \ + && ($kgm_show_kmod_syms == 0)) + showkmodaddr $kgm_frame_address + else + output /a $kgm_frame_address + end + printf "\n" + end + set $kgm_bt_count = $kgm_bt_count + 1 + end +end +document showworkloopallocator +Syntax: (gdb) showworkloopallocator +| Routine to display the backtrace of the thread which allocated the workloop in question. Only +| valid on DEBUG kernels. +end + +define showworkloopeventsources + set $kgm_eventsource = (struct IOEventSource*)$arg0 + while $kgm_eventsource != 0 + printf " " + printf "EventSource:\t" + showptr $kgm_eventsource + printf " Description: " + showeventsourceobject _ $kgm_eventsource + printf "\n" + if $kgm_eventsource->action != 0 + printf " " + printf "Action: \t" + pcprint $kgm_eventsource->action + printf "\n" + end + if $kgm_eventsource->owner != 0 + printf " " + printf "Owner: \t" + showptr $kgm_eventsource->owner + printf " Description: " + showeventsourceobject _ $kgm_eventsource->owner + printf "\n" + end + set $kgm_eventsource = $kgm_eventsource->eventChainNext + printf "\n" + end +end +document showworkloopeventsources +Syntax: (gdb) showworkloopeventsources +| Routine to walk an IOEventSource chain associated with an IOWorkLoop and print information +| about each event source in the chain. +end + +define showworkloopheader + printf "thread " + showptrhdrpad + printf " workloop " + showptrhdrpad + printf " pri state\tLockGroupName\n" +end +document showworkloopheader +Syntax: (gdb) showworkloopheader +| Routine to print out header info about an IOKit workloop. +end + +define showworkloop + set $kgm_workloopthread = (struct thread*)$arg0 + set $kgm_workloop = (struct IOWorkLoop*)$arg1 + showptr $kgm_workloopthread + printf " " + showptr $kgm_workloop + printf " %3d ", $kgm_workloopthread.sched_pri + set $kgm_state = $kgm_workloopthread.state + if $kgm_state & 0x80 + printf "I" + end + if $kgm_state & 0x40 + printf "P" + end + if $kgm_state & 0x20 + printf "A" + end + if $kgm_state & 0x10 + printf "H" + end + if $kgm_state & 0x08 + printf "U" + end + if $kgm_state & 0x04 + printf "R" + end + if $kgm_state & 0x02 + printf "S" + end + if $kgm_state & 0x01 + printf "W" + end + printf "\t\t" + set $kgm_gateLock = ( struct _IORecursiveLock *)$kgm_workloop->gateLock + if $kgm_gateLock != 0 + set $kgm_lockGroup = (struct _lck_grp_*)($kgm_gateLock->group) + printf "%s", $kgm_lockGroup->lck_grp_name + else + printf "No WorkLoop Lock found" + end + printf "\n\n" + + #Allocation backtrace is only valid on DEBUG kernels. + #printf "Allocation path:\n\n" + #showworkloopallocator $kgm_workloop + #printf "\n\n" + + if $kgm_workloop->eventChain != 0 + printf "Active event sources:\n\n" + showworkloopeventsources $kgm_workloop->eventChain + end + if $kgm_workloop->reserved->passiveEventChain != 0 + printf "Passive event sources:\n" + showworkloopeventsources $kgm_workloop->reserved->passiveEventChain + end +end +document showworkloop +Syntax: (gdb) showworkloop +| Routine to print out info about an IOKit workloop. +end + +define showallworkloopthreads + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + if ($kgm_actp->continuation == _ZN10IOWorkLoop10threadMainEv) + showworkloopheader + showworkloop $kgm_actp $kgm_actp->parameter + else + if ($kgm_actp->kernel_stack != 0) + if ($kgm_mtype == $kgm_mtype_x86_64) + #Warning: Grokking stack looking for hopeful workloops until we squirrel some info in thread_t. + set $kgm_workloop = *((struct IOWorkLoop **)($kgm_actp->kernel_stack + kernel_stack_size - 0xB8)) + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_workloop = *((struct IOWorkLoop **)($kgm_actp->kernel_stack + kernel_stack_size - 0x3C)) + end + end + if ($kgm_workloop != 0) + set $kgm_vt = *((void **) $kgm_workloop) + if $kgm_lp64 + set $kgm_vt = $kgm_vt - 16 + end + if ($kgm_vt == &_ZTV10IOWorkLoop) + showworkloopheader + showworkloop $kgm_actp $kgm_workloop + end + end + end + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" +end +document showallworkloopthreads +Syntax: (gdb) showallworkloopthreads +| Routine to print out info about all IOKit workloop threads in the system. This macro will find +| all IOWorkLoop threads blocked in continuations and on i386 and x86_64 systems will make a +| best-effort guess to find any workloops that are actually not blocked in a continuation. For a +| complete list, it is best to compare the output of this macro against the output of 'showallstacks'. +end + +define showthreadfortid + set $kgm_id_found = 0 + + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + set $kgm_thread = *(struct thread *)$kgm_actp + set $kgm_thread_id = $kgm_thread.thread_id + if ($kgm_thread_id == $arg0) + showptr $kgm_actp + printf "\n" + set $kgm_id_found = 1 + loop_break + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + if ($kgm_id_found == 1) + loop_break + end + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + if ($kgm_id_found == 0) + printf "Not a valid thread_id\n" + end +end + +document showthreadfortid +Syntax: showthreadfortid +|The thread structure contains a unique thread_id value for each thread. +|This command is used to retrieve the address of the thread structure(thread_t) +|corresponding to a given thread_id. +end + +define showtaskbusyportsint + set $kgm_isp = ((task_t)$arg0)->itk_space + set $kgm_iindex = 0 + while ( $kgm_iindex < $kgm_isp->is_table_size ) + set $kgm_iep = &($kgm_isp->is_table[$kgm_iindex]) + if $kgm_iep->ie_bits & 0x00020000 + set $kgm_port = ((ipc_port_t)$kgm_iep->ie_object) + if $kgm_port->ip_messages.data.port.msgcount > 0 + showport $kgm_port + end + end + set $kgm_iindex = $kgm_iindex + 1 + end +end + +define showtaskbusyports + showtaskbusyportsint $arg0 +end + +document showtaskbusyports +Syntax: showtaskbusyports +|Routine to print information about receive rights belonging to this task that +|have enqueued messages. This is often a sign of a blocked or hung process. +end + +define showallbusyports + set $kgm_head_taskp = &tasks + set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_cur_taskp != $kgm_head_taskp + showtaskbusyportsint $kgm_cur_taskp + set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) + end +end + +document showallbusyports +Syntax: showallbusyports +|Routine to print information about all receive rights on the system that +|have enqueued messages. +end + +define showallproviders + set $kgm_providerp = dtrace_provider + while $kgm_providerp + p *(dtrace_provider_t *)$kgm_providerp + printf "\n" + set $kgm_providerp = (dtrace_provider_t *)($kgm_providerp->dtpv_next) + end +end + +document showallproviders +Syntax: showallproviders +| Display summary listing of all dtrace_providers +end + +define showmodctlheader + printf "modctl " + showptrhdrpad + printf " stale " + showptrhdrpad + printf " symbols " + showptrhdrpad + printf " address " + showptrhdrpad + printf " size " + showptrhdrpad + printf " loadid loaded nenabled flags name\n" +end + +define showmodctlint + set $kgm_modctlp = (struct modctl *)$arg0 + showptr $kgm_modctlp + printf " " + showptr $kgm_modctlp->mod_stale + printf " " + showptr $kgm_modctlp->mod_user_symbols + printf " " + showptr $kgm_modctlp->mod_address + printf " " + showptr $kgm_modctlp->mod_size + printf " " + printf "%6d ", $kgm_modctlp->mod_loadcnt + printf "%6d ", $kgm_modctlp->mod_loaded + printf "%6d ", $kgm_modctlp->mod_nenabled + printf " 0x%x ", $kgm_modctlp->mod_flags + printf "%s\n", $kgm_modctlp->mod_modname +end + +define showmodctl + showmodctlheader + showmodctlint $arg0 +end +document showmodctl +Syntax: (gdb) showmodctl +| Display info about a dtrace modctl +end + +define showallmodctls + showmodctlheader + set $kgm_modctlp = (struct modctl *)dtrace_modctl_list + while $kgm_modctlp + showmodctlint $kgm_modctlp + set $kgm_modctlp = $kgm_modctlp->mod_next + end +end +document showallmodctls +Syntax: (gdb) showallmodctls +| Display summary listing of all dtrace modctls +end + +define showfbtprobe + printf "Be very patient, this traverses a large list \n" + set $kgm_indx = 0 + set $kgm_found = 0 + set $kgm_depth = 0 + while $kgm_indx < fbt_probetab_size && !$kgm_found + set $kgm_fbt_probep = (struct fbt_probe *)fbt_probetab[$kgm_indx] + set $kgm_depth = 0 + if $kgm_fbt_probep + set $kgm_probeid = (struct fbt_probe *)$kgm_fbt_probep->fbtp_id + if $kgm_probeid == $arg0 + set $kgm_found = 1 + loop_break + else + set $kgm_fbt_probep = $kgm_fbt_probep->fbtp_hashnext + while $kgm_fbt_probep + set $kgm_depth++ + set $kgm_probeid = (struct fbt_probe *)$kgm_fbt_probep->fbtp_id + if $kgm_probeid == $arg0 + set $kgm_found = 1 + loop_break + else + set $kgm_fbt_probep = $kgm_fbt_probep->fbtp_hashnext + end + end + end + end + if !$kgm_found + set $kgm_indx++ + else + printf "fbt_probetab[index=%d], depth=%d, 0x%x\n", $kgm_indx, $kgm_depth, $kgm_fbt_probep + printf "(gdb) p *(struct fbt_probe *)0x%x\n", $kgm_fbt_probep + p *(struct fbt_probe *)$kgm_fbt_probep + set $kgm_fbtp_ctl = (struct fbt_probe *)$kgm_fbt_probep->fbtp_ctl + showmodctl $kgm_fbtp_ctl + loop_break + end + end +end +document showfbtprobe +Syntax: (gdb) showfbtprobe +| Display info about an fbt probe given an id. +| Traverses fbt_probetab and matches with fbtp_id. +| The is found using dtrace -l +end + +define showzstacktrace + set $kgm_trace = (void*)$arg0 + if ($argc == 1) + set $kgm_trace_size = 15 + end + if ($argc == 2) + set $kgm_trace_size = $arg1 + end + set $kgm_trace_current = 0 + while ($kgm_trace_current < $kgm_trace_size) + set $kgm_trace_addr = (void**)$kgm_trace + $kgm_trace_current + set $kgm_trace_value = *((void**)$kgm_trace_addr) + #printf "\t\t" + output /a $kgm_trace_value + set $kgm_trace_current = $kgm_trace_current + 1 + printf "\n" + end +end + +document showzstacktrace +Syntax: showzstacktrace [size] +| Routine to print a stacktrace stored by OSBacktrace. +| size is optional, defaults to 15. +end + +define showzalloc + set $kgm_zallocation = zallocations[$arg0] + print $kgm_zallocation + showztrace $kgm_zallocation->za_trace_index +end + +document showzalloc +Syntax: showzalloc +| Prints a zallocation from the zallocations array based off its index, +| and prints the associated symbolicated backtrace. +end + +define showztrace + set $kgm_ztrace = &ztraces[$arg0] + showztraceaddr $kgm_ztrace +end + +document showztrace +Syntax: showztrace +| Prints the backtrace from the ztraces array at index +end + +define showztraceaddr + print *$arg0 + showzstacktrace $arg0->zt_stack ($arg0)->zt_depth +end + +document showztraceaddr +Syntax: showztraceaddr +| Prints the struct ztrace passed in +end + +#TODO: Iterate through the hash table, or make top_ztrace accurate in the face of deallocations (better idea). +define showtopztrace + set $kgm_top_ztrace = top_ztrace + printf "Index: %d\n", (top_ztrace - ztraces) + showztraceaddr $kgm_top_ztrace +end + +document showtopztrace +Syntax: showtopztrace +| Shows the ztrace with the biggest size. (according to top_ztrace, not by iterating through the hash table) +end + +define showzallocs + set $kgm_zallocation_current_index = 0 + set $kgm_zallocations_count = 0 + set $kgm_max_zallocation = zleak_alloc_buckets + printf "INDEX ADDRESS " + if $kgm_lp64 + printf " " + end + printf "TRACE SIZE\n" + while ($kgm_zallocation_current_index < $kgm_max_zallocation) + set $kgm_zallocation_current = zallocations[$kgm_zallocation_current_index] + if ($kgm_zallocation_current->element != 0) + printf "%5d %p ", $kgm_zallocation_current_index, $kgm_zallocation_current->za_element + printf "%5d %6lu\n", $kgm_zallocation_current->za_trace_index, $kgm_zallocation_current->za_size + set $kgm_zallocations_count = $kgm_zallocations_count + 1 + end + set $kgm_zallocation_current_index = $kgm_zallocation_current_index + 1 + end + printf "Total allocations: %d\n", $kgm_zallocations_count +end + +document showzallocs +Syntax: showzallocs +| Prints all allocations in the zallocations table +end + +define showzallocsfortrace + set $kgm_zallocation_current_index = 0 + set $kgm_zallocations_count = 0 + set $kgm_max_zallocation = zleak_alloc_buckets + printf "INDEX ADDRESS " + if $kgm_lp64 + printf " " + end + printf "SIZE\n" + while ($kgm_zallocation_current_index < $kgm_max_zallocation) + set $kgm_zallocation_current = zallocations[$kgm_zallocation_current_index] + if ($kgm_zallocation_current->element != 0 && $kgm_zallocation_current->za_trace_index == $arg0) + printf "%5d %p ", $kgm_zallocation_current_index, $kgm_zallocation_current->za_element + printf "%6lu\n", $kgm_zallocation_current->size + set $kgm_zallocations_count = $kgm_zallocations_count + 1 + end + set $kgm_zallocation_current_index = $kgm_zallocation_current_index + 1 + end + printf "Total allocations: %d\n", $kgm_zallocations_count +end + +document showzallocsfortrace +Syntax: showzallocsfortrace +| Prints all allocations pointing to the passed in trace's index into ztraces by looking through zallocations table +end + +define showztraces + showztracesabove 0 +end + +document showztraces +Syntax: showztraces +| Prints all traces with size > 0 +end + +define showztracesabove + set $kgm_ztrace_current_index = 0 + set $kgm_ztrace_count = 0 + set $kgm_max_ztrace = zleak_trace_buckets + printf "INDEX SIZE\n" + while ($kgm_ztrace_current_index < $kgm_max_ztrace) + set $kgm_ztrace_current = ztraces[$kgm_ztrace_current_index] + if ($kgm_ztrace_current->zt_size > $arg0) + printf "%5d %6lu\n", $kgm_ztrace_current_index, $kgm_ztrace_current->zt_size + set $kgm_ztrace_count = $kgm_ztrace_count + 1 + end + set $kgm_ztrace_current_index = $kgm_ztrace_current_index + 1 + end + printf "Total traces: %d\n", $kgm_ztrace_count +end + +document showztracesabove +Syntax: showztracesabove +| Prints all traces with size greater than X +end + +define showztracehistogram + set $kgm_ztrace_current_index = 0 + set $kgm_ztrace_count = 0 + set $kgm_max_ztrace = zleak_trace_buckets + printf "INDEX HIT_COUNT COLLISIONS\n" + while ($kgm_ztrace_current_index < $kgm_max_ztrace) + set $kgm_ztrace_current = ztraces[$kgm_ztrace_current_index] + if ($kgm_ztrace_current->zt_hit_count != 0) + printf "%5d %5d %5d\n", $kgm_ztrace_current_index, $kgm_ztrace_current->zt_hit_count, $kgm_ztrace_current->zt_collisions + set $kgm_ztrace_count = $kgm_ztrace_count + 1 + end + set $kgm_ztrace_current_index = $kgm_ztrace_current_index + 1 + end + printf "Total traces: %d\n", $kgm_ztrace_count +end + +document showztracehistogram +Syntax: showztracehistogram +| Prints the histogram of the ztrace table +end + +define showzallochistogram + set $kgm_zallocation_current_index = 0 + set $kgm_zallocations_count = 0 + set $kgm_max_zallocation = zleak_alloc_buckets + printf "INDEX HIT_COUNT\n" + while ($kgm_zallocation_current_index < $kgm_max_zallocation) + set $kgm_zallocation_current = zallocations[$kgm_zallocation_current_index] + if ($kgm_zallocation_current->za_hit_count != 0) + printf "%5d %5d\n", $kgm_zallocation_current_index, $kgm_zallocation_current->za_hit_count + set $kgm_zallocations_count = $kgm_zallocations_count + 1 + end + set $kgm_zallocation_current_index = $kgm_zallocation_current_index + 1 + end + printf "Total allocations: %d\n", $kgm_zallocations_count +end + +document showzallochistogram +Syntax: showzallochistogram +| Prints the histogram for the zalloc table +end + +define showzstats + printf "z_alloc_collisions: %u, z_trace_collisions: %u\n", z_alloc_collisions, z_trace_collisions + printf "z_alloc_overwrites: %u, z_trace_overwrites: %u\n", z_alloc_overwrites, z_trace_overwrites + printf "z_alloc_recorded: %u, z_trace_recorded: %u\n", z_alloc_recorded, z_trace_recorded +end + +document showzstats +Syntax: showzstats +| Prints the zone leak detection stats +end + + +set $kgm_au_sentry_hash_table_size = 97 + +define showsession1 + set $p = (struct au_sentry *)$arg0 + showptr $p + printf " 0x%08x 0x%08x 0x%016x", $p->se_auinfo.ai_asid, $p->se_auinfo.ai_auid, $p->se_auinfo.ai_flags + printf " %3ld %3ld", $p->se_refcnt, $p->se_procnt + printf "\n" +end + +define showsessionhdr + printf "au_sentry " + showptrhdrpad + printf " ASID AUID FLAGS C P\n" +end + +define showsession + showsessionhdr + showsession1 $arg0 +end + +document showsession +Syntax: showsession +| Display info about a specified audit session +end + +define showallsessions + showsessionhdr + set $kgm_au_sentry_hash_table = au_sentry_bucket + set $i = $kgm_au_sentry_hash_table_size - 1 + while $i >= 0 + set $p = $kgm_au_sentry_hash_table[$i].lh_first + while $p != 0 + showsession1 $p + set $p = $p->se_link.le_next + end + set $i = $i - 1 + end +end + +document showallsessions +Syntax: showallsessions +| Prints the audit sessions in the global hash table +end + +define showauhistorystack + set $ii = $arg0 + set $pp = (void **)$arg1 + while $ii > 0 + printf " " + x/i $pp[$ii-1] + set $ii = $ii - 1 + end +end + +define showauhistory1 + set $p = (struct au_history *)$arg0 + set $stack_depth = $p->stack_depth + set $stack = $p->stack + showptr $p->ptr + if $p->event == 1 + printf " REF" + end + if $p->event == 2 + printf " UNREF" + end + if $p->event == 3 + printf " BIRTH" + end + if $p->event == 4 + printf " DEATH" + end + if $p->event == 5 + printf " FIND" + end + set $p = &$p->se + printf " 0x%08x 0x%08x 0x%016x", $p->se_auinfo.ai_asid, $p->se_auinfo.ai_auid, $p->se_auinfo.ai_flags + printf " %3ld %3ld", $p->se_refcnt, $p->se_procnt + printf "\n" + showauhistorystack $stack_depth $stack +end + +define showauhistory + set $i = (au_history_index-1) % au_history_size + if au_history_index >= au_history_size + set $n = au_history_size + else + set $n = au_history_index + end + while $n > 0 + if au_history[$i].ptr != 0 && (0 == $arg0 || au_history[$i].ptr == $arg0) + printf "[% 4d] ", $i + showauhistory1 &au_history[$i] + end + set $n = $n - 1 + set $i = ($i - 1) % au_history_size + end +end + +define showallauhistory + showauhistory 0 +end + +define showkwqheader + printf " kwq " + showptrhdrpad + printf " kwqaddr " + showptrhdrpad + printf " inqueue fakecount highseq lowseq flags lastunlock p_rwwc" + printf "\n " +end + +define showkwqint + printf " " + set $kgm_kwq = (ksyn_wait_queue_t)$arg0 + showptr $kgm_kwq + printf " " + showptr $kgm_kwq->kw_addr + printf " " + printf " %d ", $kgm_kwq->kw_inqueue + printf " %d ", $kgm_kwq->kw_fakecount + printf " 0x%x ", $kgm_kwq->kw_highseq + printf " 0x%x ", $kgm_kwq->kw_lowseq + printf " 0x%x ", $kgm_kwq->kw_flags + printf " 0x%x ", $kgm_kwq->kw_lastunlockseq + printf " 0x%x ", $kgm_kwq->kw_pre_rwwc + printf "\n" +end + +define show_kwq + showkwqheader + showkwqint $arg0 +end + +document show_kwq +Syntax: (gdb) show_kwq +| Display info about one ksyn_wait_queue +end + +# Internal routine used by "showpthread_mutex" to abstract possible loads from +# user space +define _loadfrommutex + if (kdp_pmap == 0) + set $kgm_loadval = *(uintptr_t *)$arg0 + else + if ($kgm_x86_abi == 0xe) + set $kgm_loadval = *(uint32_t *)$arg0 + else + if ($kgm_x86_abi == 0xf) + if ($kgm_mtype == $kgm_mtype_i386) + _loadk32m64 $arg0 + set $kgm_loadval = $kgm_k32read64 + else + set $kgm_loadval = *(uint32_t *)$arg0 + end + end + end +end +end + +define show_pthreadmutex + set $newact = (struct thread *) $arg0 + set $ourtask = (struct task *)($newact->task) + set $our_user_is64 = ($ourtask->taskFeatures[0] & 0x80000000) + _kgm_flush_loop + set $mutex = (void *)$arg1 + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + set $newiss = (x86_saved_state_t *) ($newact->machine.pcb->iss) + set $kgm_x86_abi = $newiss.flavor + if ($our_user_is64 != 0) + printf "\tUser 64Bit\n " + printf "\tSignature: " + set $nextval = $mutex + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tflags: " + set $nextval = $mutex + 12 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tSeqs: " + set $nextval = $mutex + 20 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $mutex + 24 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $mutex + 28 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\ttid[0]: " + set $nextval = $mutex + 32 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\ttid[1]: " + set $nextval = $mutex + 36 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + else + printf "\tUser 32Bit\n " + printf "\tSignature: " + set $nextval = $mutex + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tflags: " + set $nextval = $mutex + 8 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tSeqs: " + set $nextval = $mutex + 16 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $mutex + 20 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $mutex + 24 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\ttid[0]: " + set $nextval = $mutex + 32 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\ttid[1]: " + set $nextval = $mutex + 36 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + end + printf "\n" + resetstacks +end + + +document show_pthreadmutex +Syntax: (gdb) show_pthreadmutex +| Display the mutex contents from userspace. +end + + +define show_pthreadcondition + set $newact = (struct thread *) $arg0 + set $ourtask = (struct task *)($newact->task) + set $our_user_is64 = ($ourtask->taskFeatures[0] & 0x80000000) + _kgm_flush_loop + set $cond = (void *)$arg1 + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + set $newiss = (x86_saved_state_t *) ($newact->machine.pcb->iss) + set $kgm_x86_abi = $newiss.flavor + if ($our_user_is64 != 0) + printf "\tUser 64Bit\n " + printf "\tSignature: " + set $nextval = $cond + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tflags: " + set $nextval = $cond + 12 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tSeqs: " + set $nextval = $cond + 24 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $cond + 28 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $cond + 32 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tMutex lowaddr: " + set $nextval = $cond + 16 + _loadfrommutex $nextval + printf "0x%08x\n",$kgm_loadval + printf "\tMutex highaddr: " + set $nextval = $cond + 20 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + else + printf "\tUser 32Bit\n " + printf "\tSignature: " + set $nextval = $cond + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tflags: " + set $nextval = $cond + 8 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tSeqs: " + set $nextval = $cond + 16 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $cond + 20 + _loadfrommutex $nextval + printf "0x%x ",$kgm_loadval + set $nextval = $cond + 24 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + printf "\tMutex addr: " + set $nextval = $cond + 12 + _loadfrommutex $nextval + printf "0x%x\n",$kgm_loadval + end + printf "\n" + resetstacks +end + + +document show_pthreadcondition +Syntax: (gdb) show_pthreadcondition +| Display the condition variable contents from userspace. +end + +define processortimers + set $kgm_p = processor_list + printf "Processor\t\t\t Last dispatch\t\t Next deadline\t\t difference\n" + while $kgm_p + printf "Processor %d: %p\t", $kgm_p->cpu_id, $kgm_p + printf " 0x%016llx\t", $kgm_p->last_dispatch + set $kgm_rt_timer = &(cpu_data_ptr[$kgm_p->cpu_id].rtclock_timer) + printf " 0x%016llx \t", $kgm_rt_timer->deadline + set $kgm_rt_diff = ((long long)$kgm_p->last_dispatch) - ((long long)$kgm_rt_timer->deadline) + printf " 0x%016llx ", $kgm_rt_diff +# normally the $kgm_rt_diff will be close to the last dispatch time, or negative +# When it isn't, mark the result as bad. This is a suggestion, not an absolute + if ( ($kgm_rt_diff > 0) && ((long long)$kgm_p->last_dispatch) - ($kgm_rt_diff + 1) > 0 ) + printf "probably BAD\n" + else + printf "(ok)\n" + end + # dump the call entries (Intel only) + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + printf "Next deadline set at: 0x%016llx. Timer call list:", $kgm_rt_timer->when_set + set $kgm_entry = (queue_t *)$kgm_rt_timer->queue + if ($kgm_entry == $kgm_rt_timer) + printf " (empty)\n" + else + printf "\n entry: " + showptrhdrpad + printf "deadline soft_deadline delta (*func)(param0,param1)\n" + while $kgm_entry != $kgm_rt_timer + set $kgm_timer_call = (timer_call_t) $kgm_entry + set $kgm_call_entry = (struct call_entry *) $kgm_entry + printf " " + showptr $kgm_entry + printf ": 0x%016llx 0x%016llx 0x%08x (%p)(%p,%p)\n", \ + $kgm_call_entry->deadline, \ + $kgm_timer_call->soft_deadline, \ + ($kgm_call_entry->deadline - $kgm_timer_call->soft_deadline), \ + $kgm_call_entry->func, \ + $kgm_call_entry->param0, $kgm_call_entry->param1 + set $kgm_entry = $kgm_entry->next + end + end + end + set $kgm_p = $kgm_p->processor_list + end + printf "\n" +end + +document processortimers +Syntax: (gdb) processortimers +| Print details of processor timers, noting any timer which might be suspicious +end + +define maplocalcache + if ($kgm_mtype == $kgm_mtype_arm) + mem 0x80000000 0xefffffff cache + set dcache-linesize-power 9 + printf "GDB memory caching enabled. Be sure to disable by calling flushlocalcache before detaching or connecting to a new device\n" + end +end + +document maplocalcache +Syntax: (gdb) maplocalcache +| Sets up memory regions for GDB to cache on read. Significantly increases debug speed over KDP +end + +define flushlocalcache + if ($kgm_mtype == $kgm_mtype_arm) + delete mem + printf "GDB memory caching disabled.\n" + end +end + +document flushlocalcache +Syntax: (gdb) flushlocalcache +| Clears all memory regions +end diff --git a/.gdb/libstdcxx/__init__.py b/.gdb/libstdcxx/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.gdb/libstdcxx/__init__.py @@ -0,0 +1 @@ + diff --git a/.gdb/libstdcxx/v6/__init__.py b/.gdb/libstdcxx/v6/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.gdb/libstdcxx/v6/__init__.py @@ -0,0 +1 @@ + diff --git a/.gdb/libstdcxx/v6/printers.py b/.gdb/libstdcxx/v6/printers.py new file mode 100644 index 0000000..623a815 --- /dev/null +++ b/.gdb/libstdcxx/v6/printers.py @@ -0,0 +1,1112 @@ +# Pretty-printers for libstc++. + +# Copyright (C) 2008-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import gdb +import itertools +import re + +# Try to use the new-style pretty-printing if available. +_use_gdb_pp = True +try: + import gdb.printing +except ImportError: + _use_gdb_pp = False + +# Try to install type-printers. +_use_type_printing = False +try: + import gdb.types + if hasattr(gdb.types, 'TypePrinter'): + _use_type_printing = True +except ImportError: + pass + +# Starting with the type ORIG, search for the member type NAME. This +# handles searching upward through superclasses. This is needed to +# work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615. +def find_type(orig, name): + typ = orig.strip_typedefs() + while True: + search = str(typ) + '::' + name + try: + return gdb.lookup_type(search) + except RuntimeError: + pass + # The type was not found, so try the superclass. We only need + # to check the first superclass, so we don't bother with + # anything fancier here. + field = typ.fields()[0] + if not field.is_base_class: + raise ValueError("Cannot find type %s::%s" % (str(orig), name)) + typ = field.type + +class SharedPointerPrinter: + "Print a shared_ptr or weak_ptr" + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def to_string (self): + state = 'empty' + refcounts = self.val['_M_refcount']['_M_pi'] + if refcounts != 0: + usecount = refcounts['_M_use_count'] + weakcount = refcounts['_M_weak_count'] + if usecount == 0: + state = 'expired, weak %d' % weakcount + else: + state = 'count %d, weak %d' % (usecount, weakcount - 1) + return '%s (%s) %s' % (self.typename, state, self.val['_M_ptr']) + +class UniquePointerPrinter: + "Print a unique_ptr" + + def __init__ (self, typename, val): + self.val = val + + def to_string (self): + v = self.val['_M_t']['_M_head_impl'] + return ('std::unique_ptr<%s> containing %s' % (str(v.type.target()), + str(v))) + +class StdListPrinter: + "Print a std::list" + + class _iterator: + def __init__(self, nodetype, head): + self.nodetype = nodetype + self.base = head['_M_next'] + self.head = head.address + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.base == self.head: + raise StopIteration + elt = self.base.cast(self.nodetype).dereference() + self.base = elt['_M_next'] + count = self.count + self.count = self.count + 1 + return ('[%d]' % count, elt['_M_data']) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + return self._iterator(nodetype, self.val['_M_impl']['_M_node']) + + def to_string(self): + if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: + return 'empty %s' % (self.typename) + return '%s' % (self.typename) + +class StdListIteratorPrinter: + "Print std::list::iterator" + + def __init__(self, typename, val): + self.val = val + self.typename = typename + + def to_string(self): + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] + +class StdSlistPrinter: + "Print a __gnu_cxx::slist" + + class _iterator: + def __init__(self, nodetype, head): + self.nodetype = nodetype + self.base = head['_M_head']['_M_next'] + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.base == 0: + raise StopIteration + elt = self.base.cast(self.nodetype).dereference() + self.base = elt['_M_next'] + count = self.count + self.count = self.count + 1 + return ('[%d]' % count, elt['_M_data']) + + def __init__(self, typename, val): + self.val = val + + def children(self): + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + return self._iterator(nodetype, self.val) + + def to_string(self): + if self.val['_M_head']['_M_next'] == 0: + return 'empty __gnu_cxx::slist' + return '__gnu_cxx::slist' + +class StdSlistIteratorPrinter: + "Print __gnu_cxx::slist::iterator" + + def __init__(self, typename, val): + self.val = val + + def to_string(self): + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] + +class StdVectorPrinter: + "Print a std::vector" + + class _iterator: + def __init__ (self, start, finish, bitvec): + self.bitvec = bitvec + if bitvec: + self.item = start['_M_p'] + self.so = start['_M_offset'] + self.finish = finish['_M_p'] + self.fo = finish['_M_offset'] + itype = self.item.dereference().type + self.isize = 8 * itype.sizeof + else: + self.item = start + self.finish = finish + self.count = 0 + + def __iter__(self): + return self + + def next(self): + count = self.count + self.count = self.count + 1 + if self.bitvec: + if self.item == self.finish and self.so >= self.fo: + raise StopIteration + elt = self.item.dereference() + if elt & (1 << self.so): + obit = 1 + else: + obit = 0 + self.so = self.so + 1 + if self.so >= self.isize: + self.item = self.item + 1 + self.so = 0 + return ('[%d]' % count, obit) + else: + if self.item == self.finish: + raise StopIteration + elt = self.item.dereference() + self.item = self.item + 1 + return ('[%d]' % count, elt) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL + + def children(self): + return self._iterator(self.val['_M_impl']['_M_start'], + self.val['_M_impl']['_M_finish'], + self.is_bool) + + def to_string(self): + start = self.val['_M_impl']['_M_start'] + finish = self.val['_M_impl']['_M_finish'] + end = self.val['_M_impl']['_M_end_of_storage'] + if self.is_bool: + start = self.val['_M_impl']['_M_start']['_M_p'] + so = self.val['_M_impl']['_M_start']['_M_offset'] + finish = self.val['_M_impl']['_M_finish']['_M_p'] + fo = self.val['_M_impl']['_M_finish']['_M_offset'] + itype = start.dereference().type + bl = 8 * itype.sizeof + length = (bl - so) + bl * ((finish - start) - 1) + fo + capacity = bl * (end - start) + return ('%s of length %d, capacity %d' + % (self.typename, int (length), int (capacity))) + else: + return ('%s of length %d, capacity %d' + % (self.typename, int (finish - start), int (end - start))) + + def display_hint(self): + return 'array' + +class StdVectorIteratorPrinter: + "Print std::vector::iterator" + + def __init__(self, typename, val): + self.val = val + + def to_string(self): + return self.val['_M_current'].dereference() + +class StdTuplePrinter: + "Print a std::tuple" + + class _iterator: + def __init__ (self, head): + self.head = head + + # Set the base class as the initial head of the + # tuple. + nodes = self.head.type.fields () + if len (nodes) == 1: + # Set the actual head to the first pair. + self.head = self.head.cast (nodes[0].type) + elif len (nodes) != 0: + raise ValueError("Top of tuple tree does not consist of a single node.") + self.count = 0 + + def __iter__ (self): + return self + + def next (self): + nodes = self.head.type.fields () + # Check for further recursions in the inheritance tree. + if len (nodes) == 0: + raise StopIteration + # Check that this iteration has an expected structure. + if len (nodes) != 2: + raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") + + # - Left node is the next recursion parent. + # - Right node is the actual class contained in the tuple. + + # Process right node. + impl = self.head.cast (nodes[1].type) + + # Process left node and set it as head. + self.head = self.head.cast (nodes[0].type) + self.count = self.count + 1 + + # Finally, check the implementation. If it is + # wrapped in _M_head_impl return that, otherwise return + # the value "as is". + fields = impl.type.fields () + if len (fields) < 1 or fields[0].name != "_M_head_impl": + return ('[%d]' % self.count, impl) + else: + return ('[%d]' % self.count, impl['_M_head_impl']) + + def __init__ (self, typename, val): + self.typename = typename + self.val = val; + + def children (self): + return self._iterator (self.val) + + def to_string (self): + if len (self.val.type.fields ()) == 0: + return 'empty %s' % (self.typename) + return '%s containing' % (self.typename) + +class StdStackOrQueuePrinter: + "Print a std::stack or std::queue" + + def __init__ (self, typename, val): + self.typename = typename + self.visualizer = gdb.default_visualizer(val['c']) + + def children (self): + return self.visualizer.children() + + def to_string (self): + return '%s wrapping: %s' % (self.typename, + self.visualizer.to_string()) + + def display_hint (self): + if hasattr (self.visualizer, 'display_hint'): + return self.visualizer.display_hint () + return None + +class RbtreeIterator: + def __init__(self, rbtree): + self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] + self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] + self.count = 0 + + def __iter__(self): + return self + + def __len__(self): + return int (self.size) + + def next(self): + if self.count == self.size: + raise StopIteration + result = self.node + self.count = self.count + 1 + if self.count < self.size: + # Compute the next node. + node = self.node + if node.dereference()['_M_right']: + node = node.dereference()['_M_right'] + while node.dereference()['_M_left']: + node = node.dereference()['_M_left'] + else: + parent = node.dereference()['_M_parent'] + while node == parent.dereference()['_M_right']: + node = parent + parent = parent.dereference()['_M_parent'] + if node.dereference()['_M_right'] != parent: + node = parent + self.node = node + return result + +def get_value_from_Rb_tree_node(node): + """Returns the value held in an _Rb_tree_node<_Val>""" + try: + member = node.type.fields()[1].name + if member == '_M_value_field': + # C++03 implementation, node contains the value as a member + return node['_M_value_field'] + elif member == '_M_storage': + # C++11 implementation, node stores value in __aligned_buffer + p = node['_M_storage']['_M_storage'].address + p = p.cast(node.type.template_argument(0).pointer()) + return p.dereference() + except: + pass + raise ValueError("Unsupported implementation for %s" % str(node.type)) + +# This is a pretty printer for std::_Rb_tree_iterator (which is +# std::map::iterator), and has nothing to do with the RbtreeIterator +# class above. +class StdRbtreeIteratorPrinter: + "Print std::map::iterator" + + def __init__ (self, typename, val): + self.val = val + + def to_string (self): + typename = str(self.val.type.strip_typedefs()) + '::_Link_type' + nodetype = gdb.lookup_type(typename).strip_typedefs() + node = self.val.cast(nodetype).dereference() + return get_value_from_Rb_tree_node(node) + +class StdDebugIteratorPrinter: + "Print a debug enabled version of an iterator" + + def __init__ (self, typename, val): + self.val = val + + # Just strip away the encapsulating __gnu_debug::_Safe_iterator + # and return the wrapped iterator value. + def to_string (self): + itype = self.val.type.template_argument(0) + return self.val['_M_current'].cast(itype) + +class StdMapPrinter: + "Print a std::map or std::multimap" + + # Turn an RbtreeIterator into a pretty-print iterator. + class _iter: + def __init__(self, rbiter, type): + self.rbiter = rbiter + self.count = 0 + self.type = type + + def __iter__(self): + return self + + def next(self): + if self.count % 2 == 0: + n = self.rbiter.next() + n = n.cast(self.type).dereference() + n = get_value_from_Rb_tree_node(n) + self.pair = n + item = n['first'] + else: + item = self.pair['second'] + result = ('[%d]' % self.count, item) + self.count = self.count + 1 + return result + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def to_string (self): + return '%s with %d elements' % (self.typename, + len (RbtreeIterator (self.val))) + + def children (self): + rep_type = find_type(self.val.type, '_Rep_type') + node = find_type(rep_type, '_Link_type') + node = node.strip_typedefs() + return self._iter (RbtreeIterator (self.val), node) + + def display_hint (self): + return 'map' + +class StdSetPrinter: + "Print a std::set or std::multiset" + + # Turn an RbtreeIterator into a pretty-print iterator. + class _iter: + def __init__(self, rbiter, type): + self.rbiter = rbiter + self.count = 0 + self.type = type + + def __iter__(self): + return self + + def next(self): + item = self.rbiter.next() + item = item.cast(self.type).dereference() + item = get_value_from_Rb_tree_node(item) + # FIXME: this is weird ... what to do? + # Maybe a 'set' display hint? + result = ('[%d]' % self.count, item) + self.count = self.count + 1 + return result + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def to_string (self): + return '%s with %d elements' % (self.typename, + len (RbtreeIterator (self.val))) + + def children (self): + rep_type = find_type(self.val.type, '_Rep_type') + node = find_type(rep_type, '_Link_type') + node = node.strip_typedefs() + return self._iter (RbtreeIterator (self.val), node) + +class StdBitsetPrinter: + "Print a std::bitset" + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def to_string (self): + # If template_argument handled values, we could print the + # size. Or we could use a regexp on the type. + return '%s' % (self.typename) + + def children (self): + words = self.val['_M_w'] + wtype = words.type + + # The _M_w member can be either an unsigned long, or an + # array. This depends on the template specialization used. + # If it is a single long, convert to a single element list. + if wtype.code == gdb.TYPE_CODE_ARRAY: + tsize = wtype.target ().sizeof + else: + words = [words] + tsize = wtype.sizeof + + nwords = wtype.sizeof / tsize + result = [] + byte = 0 + while byte < nwords: + w = words[byte] + bit = 0 + while w != 0: + if (w & 1) != 0: + # Another spot where we could use 'set'? + result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) + bit = bit + 1 + w = w >> 1 + byte = byte + 1 + return result + +class StdDequePrinter: + "Print a std::deque" + + class _iter: + def __init__(self, node, start, end, last, buffer_size): + self.node = node + self.p = start + self.end = end + self.last = last + self.buffer_size = buffer_size + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.p == self.last: + raise StopIteration + + result = ('[%d]' % self.count, self.p.dereference()) + self.count = self.count + 1 + + # Advance the 'cur' pointer. + self.p = self.p + 1 + if self.p == self.end: + # If we got to the end of this bucket, move to the + # next bucket. + self.node = self.node + 1 + self.p = self.node[0] + self.end = self.p + self.buffer_size + + return result + + def __init__(self, typename, val): + self.typename = typename + self.val = val + self.elttype = val.type.template_argument(0) + size = self.elttype.sizeof + if size < 512: + self.buffer_size = int (512 / size) + else: + self.buffer_size = 1 + + def to_string(self): + start = self.val['_M_impl']['_M_start'] + end = self.val['_M_impl']['_M_finish'] + + delta_n = end['_M_node'] - start['_M_node'] - 1 + delta_s = start['_M_last'] - start['_M_cur'] + delta_e = end['_M_cur'] - end['_M_first'] + + size = self.buffer_size * delta_n + delta_s + delta_e + + return '%s with %d elements' % (self.typename, long (size)) + + def children(self): + start = self.val['_M_impl']['_M_start'] + end = self.val['_M_impl']['_M_finish'] + return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], + end['_M_cur'], self.buffer_size) + + def display_hint (self): + return 'array' + +class StdDequeIteratorPrinter: + "Print std::deque::iterator" + + def __init__(self, typename, val): + self.val = val + + def to_string(self): + return self.val['_M_cur'].dereference() + +class StdStringPrinter: + "Print a std::basic_string of some kind" + + def __init__(self, typename, val): + self.val = val + + def to_string(self): + # Make sure &string works, too. + type = self.val.type + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Calculate the length of the string so that to_string returns + # the string according to length, not according to first null + # encountered. + ptr = self.val ['_M_dataplus']['_M_p'] + realtype = type.unqualified ().strip_typedefs () + reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () + header = ptr.cast(reptype) - 1 + len = header.dereference ()['_M_length'] + if hasattr(ptr, "lazy_string"): + return ptr.lazy_string (length = len) + return ptr.string (length = len) + + def display_hint (self): + return 'string' + +class Tr1HashtableIterator: + def __init__ (self, hash): + self.buckets = hash['_M_buckets'] + self.bucket = 0 + self.bucket_count = hash['_M_bucket_count'] + self.node_type = find_type(hash.type, '_Node').pointer() + self.node = 0 + while self.bucket != self.bucket_count: + self.node = self.buckets[self.bucket] + if self.node: + break + self.bucket = self.bucket + 1 + + def __iter__ (self): + return self + + def next (self): + if self.node == 0: + raise StopIteration + node = self.node.cast(self.node_type) + result = node.dereference()['_M_v'] + self.node = node.dereference()['_M_next']; + if self.node == 0: + self.bucket = self.bucket + 1 + while self.bucket != self.bucket_count: + self.node = self.buckets[self.bucket] + if self.node: + break + self.bucket = self.bucket + 1 + return result + +class StdHashtableIterator: + def __init__(self, hash): + self.node = hash['_M_before_begin']['_M_nxt'] + self.node_type = find_type(hash.type, '__node_type').pointer() + + def __iter__(self): + return self + + def next(self): + if self.node == 0: + raise StopIteration + elt = self.node.cast(self.node_type).dereference() + self.node = elt['_M_nxt'] + valptr = elt['_M_storage'].address + valptr = valptr.cast(elt.type.template_argument(0).pointer()) + return valptr.dereference() + +class Tr1UnorderedSetPrinter: + "Print a tr1::unordered_set" + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def hashtable (self): + if self.typename.startswith('std::tr1'): + return self.val + return self.val['_M_h'] + + def to_string (self): + return '%s with %d elements' % (self.typename, self.hashtable()['_M_element_count']) + + @staticmethod + def format_count (i): + return '[%d]' % i + + def children (self): + counter = itertools.imap (self.format_count, itertools.count()) + if self.typename.startswith('std::tr1'): + return itertools.izip (counter, Tr1HashtableIterator (self.hashtable())) + return itertools.izip (counter, StdHashtableIterator (self.hashtable())) + +class Tr1UnorderedMapPrinter: + "Print a tr1::unordered_map" + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def hashtable (self): + if self.typename.startswith('std::tr1'): + return self.val + return self.val['_M_h'] + + def to_string (self): + return '%s with %d elements' % (self.typename, self.hashtable()['_M_element_count']) + + @staticmethod + def flatten (list): + for elt in list: + for i in elt: + yield i + + @staticmethod + def format_one (elt): + return (elt['first'], elt['second']) + + @staticmethod + def format_count (i): + return '[%d]' % i + + def children (self): + counter = itertools.imap (self.format_count, itertools.count()) + # Map over the hash table and flatten the result. + if self.typename.startswith('std::tr1'): + data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) + # Zip the two iterators together. + return itertools.izip (counter, data) + data = self.flatten (itertools.imap (self.format_one, StdHashtableIterator (self.hashtable()))) + # Zip the two iterators together. + return itertools.izip (counter, data) + + + def display_hint (self): + return 'map' + +class StdForwardListPrinter: + "Print a std::forward_list" + + class _iterator: + def __init__(self, nodetype, head): + self.nodetype = nodetype + self.base = head['_M_next'] + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.base == 0: + raise StopIteration + elt = self.base.cast(self.nodetype).dereference() + self.base = elt['_M_next'] + count = self.count + self.count = self.count + 1 + valptr = elt['_M_storage'].address + valptr = valptr.cast(elt.type.template_argument(0).pointer()) + return ('[%d]' % count, valptr.dereference()) + + def __init__(self, typename, val): + self.val = val + self.typename = typename + + def children(self): + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + return self._iterator(nodetype, self.val['_M_impl']['_M_head']) + + def to_string(self): + if self.val['_M_impl']['_M_head']['_M_next'] == 0: + return 'empty %s' % (self.typename) + return '%s' % (self.typename) + + +# A "regular expression" printer which conforms to the +# "SubPrettyPrinter" protocol from gdb.printing. +class RxPrinter(object): + def __init__(self, name, function): + super(RxPrinter, self).__init__() + self.name = name + self.function = function + self.enabled = True + + def invoke(self, value): + if not self.enabled: + return None + + if value.type.code == gdb.TYPE_CODE_REF: + if hasattr(gdb.Value,"referenced_value"): + value = value.referenced_value() + + return self.function(self.name, value) + +# A pretty-printer that conforms to the "PrettyPrinter" protocol from +# gdb.printing. It can also be used directly as an old-style printer. +class Printer(object): + def __init__(self, name): + super(Printer, self).__init__() + self.name = name + self.subprinters = [] + self.lookup = {} + self.enabled = True + self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') + + def add(self, name, function): + # A small sanity check. + # FIXME + if not self.compiled_rx.match(name + '<>'): + raise ValueError('libstdc++ programming error: "%s" does not match' % name) + printer = RxPrinter(name, function) + self.subprinters.append(printer) + self.lookup[name] = printer + + # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. + def add_version(self, base, name, function): + self.add(base + name, function) + self.add(base + '__7::' + name, function) + + # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. + def add_container(self, base, name, function): + self.add_version(base, name, function) + self.add_version(base + '__cxx1998::', name, function) + + @staticmethod + def get_basic_type(type): + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + return type.tag + + def __call__(self, val): + typename = self.get_basic_type(val.type) + if not typename: + return None + + # All the types we match are template types, so we can use a + # dictionary. + match = self.compiled_rx.match(typename) + if not match: + return None + + basename = match.group(1) + + if val.type.code == gdb.TYPE_CODE_REF: + if hasattr(gdb.Value,"referenced_value"): + val = val.referenced_value() + + if basename in self.lookup: + return self.lookup[basename].invoke(val) + + # Cannot find a pretty printer. Return None. + return None + +libstdcxx_printer = None + +class FilteringTypePrinter(object): + def __init__(self, match, name): + self.match = match + self.name = name + self.enabled = True + + class _recognizer(object): + def __init__(self, match, name): + self.match = match + self.name = name + self.type_obj = None + + def recognize(self, type_obj): + if type_obj.tag is None: + return None + + if self.type_obj is None: + if not self.match in type_obj.tag: + # Filter didn't match. + return None + try: + self.type_obj = gdb.lookup_type(self.name).strip_typedefs() + except: + pass + if self.type_obj == type_obj: + return self.name + return None + + def instantiate(self): + return self._recognizer(self.match, self.name) + +def add_one_type_printer(obj, match, name): + printer = FilteringTypePrinter(match, 'std::' + name) + gdb.types.register_type_printer(obj, printer) + +def register_type_printers(obj): + global _use_type_printing + + if not _use_type_printing: + return + + for pfx in ('', 'w'): + add_one_type_printer(obj, 'basic_string', pfx + 'string') + add_one_type_printer(obj, 'basic_ios', pfx + 'ios') + add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf') + add_one_type_printer(obj, 'basic_istream', pfx + 'istream') + add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream') + add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream') + add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf') + add_one_type_printer(obj, 'basic_istringstream', + pfx + 'istringstream') + add_one_type_printer(obj, 'basic_ostringstream', + pfx + 'ostringstream') + add_one_type_printer(obj, 'basic_stringstream', + pfx + 'stringstream') + add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf') + add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream') + add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream') + add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream') + add_one_type_printer(obj, 'basic_regex', pfx + 'regex') + add_one_type_printer(obj, 'sub_match', pfx + 'csub_match') + add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match') + add_one_type_printer(obj, 'match_results', pfx + 'cmatch') + add_one_type_printer(obj, 'match_results', pfx + 'smatch') + add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator') + add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator') + add_one_type_printer(obj, 'regex_token_iterator', + pfx + 'cregex_token_iterator') + add_one_type_printer(obj, 'regex_token_iterator', + pfx + 'sregex_token_iterator') + + # Note that we can't have a printer for std::wstreampos, because + # it shares the same underlying type as std::streampos. + add_one_type_printer(obj, 'fpos', 'streampos') + add_one_type_printer(obj, 'basic_string', 'u16string') + add_one_type_printer(obj, 'basic_string', 'u32string') + + for dur in ('nanoseconds', 'microseconds', 'milliseconds', + 'seconds', 'minutes', 'hours'): + add_one_type_printer(obj, 'duration', dur) + + add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') + add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand') + add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937') + add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64') + add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base') + add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base') + add_one_type_printer(obj, 'discard_block_engine', 'ranlux24') + add_one_type_printer(obj, 'discard_block_engine', 'ranlux48') + add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b') + +def register_libstdcxx_printers (obj): + "Register libstdc++ pretty-printers with objfile Obj." + + global _use_gdb_pp + global libstdcxx_printer + + if _use_gdb_pp: + gdb.printing.register_pretty_printer(obj, libstdcxx_printer) + else: + if obj is None: + obj = gdb + obj.pretty_printers.append(libstdcxx_printer) + + register_type_printers(obj) + +def build_libstdcxx_dictionary (): + global libstdcxx_printer + + libstdcxx_printer = Printer("libstdc++-v6") + + # For _GLIBCXX_BEGIN_NAMESPACE_VERSION. + vers = '(__7::)?' + # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. + container = '(__cxx1998::' + vers + ')?' + + # libstdc++ objects requiring pretty-printing. + # In order from: + # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html + libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) + libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) + libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) + libstdcxx_printer.add_container('std::', 'list', StdListPrinter) + libstdcxx_printer.add_container('std::', 'map', StdMapPrinter) + libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter) + libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter) + libstdcxx_printer.add_version('std::', 'priority_queue', + StdStackOrQueuePrinter) + libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter) + libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter) + libstdcxx_printer.add_container('std::', 'set', StdSetPrinter) + libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter) + libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) + libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) + # vector + + # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. + libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) + libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) + libstdcxx_printer.add('std::__debug::list', StdListPrinter) + libstdcxx_printer.add('std::__debug::map', StdMapPrinter) + libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) + libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) + libstdcxx_printer.add('std::__debug::priority_queue', + StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::set', StdSetPrinter) + libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) + libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) + + # These are the TR1 and C++0x printers. + # For array - the default GDB pretty-printer seems reasonable. + libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter) + libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter) + libstdcxx_printer.add_container('std::', 'unordered_map', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add_container('std::', 'unordered_set', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add_container('std::', 'unordered_multimap', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add_container('std::', 'unordered_multiset', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add_container('std::', 'forward_list', + StdForwardListPrinter) + + libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) + libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) + libstdcxx_printer.add_version('std::tr1::', 'unordered_map', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add_version('std::tr1::', 'unordered_set', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', + Tr1UnorderedSetPrinter) + + # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. + # The tr1 namespace printers do not seem to have any debug + # equivalents, so do no register them. + libstdcxx_printer.add('std::__debug::unordered_map', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::__debug::unordered_set', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add('std::__debug::unordered_multimap', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::__debug::unordered_multiset', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add('std::__debug::forward_list', + StdForwardListPrinter) + + + # Extensions. + libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) + + if True: + # These shouldn't be necessary, if GDB "print *i" worked. + # But it often doesn't, so here they are. + libstdcxx_printer.add_container('std::', '_List_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add_container('std::', '_List_const_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add_version('std::', '_Rb_tree_iterator', + StdRbtreeIteratorPrinter) + libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator', + StdRbtreeIteratorPrinter) + libstdcxx_printer.add_container('std::', '_Deque_iterator', + StdDequeIteratorPrinter) + libstdcxx_printer.add_container('std::', '_Deque_const_iterator', + StdDequeIteratorPrinter) + libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', + StdVectorIteratorPrinter) + libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', + StdSlistIteratorPrinter) + + # Debug (compiled with -D_GLIBCXX_DEBUG) printer + # registrations. The Rb_tree debug iterator when unwrapped + # from the encapsulating __gnu_debug::_Safe_iterator does not + # have the __norm namespace. Just use the existing printer + # registration for that. + libstdcxx_printer.add('__gnu_debug::_Safe_iterator', + StdDebugIteratorPrinter) + libstdcxx_printer.add('std::__norm::_List_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add('std::__norm::_List_const_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add('std::__norm::_Deque_const_iterator', + StdDequeIteratorPrinter) + libstdcxx_printer.add('std::__norm::_Deque_iterator', + StdDequeIteratorPrinter) + +build_libstdcxx_dictionary () diff --git a/.gdb/macsbug.gdb b/.gdb/macsbug.gdb new file mode 100644 index 0000000..7125c84 --- /dev/null +++ b/.gdb/macsbug.gdb @@ -0,0 +1,4147 @@ +################################################################################# +# # +# gdbinit-MacsBug-without-plugin # +# # +# Macsbug-style gdb command definitions # +# # +# Ira L. Ruben # +# Copyright Apple Computer, Inc. 2000-2001 # +# # +################################################################################# + +# This file can be either sourced'ed in by .gdbinit or explicitly to define a set +# of gdb commands that simulate a subset of MacsBug commands. It is as faithful +# a simulation as possible within the limits of the gdb command language. There +# may also be an extension or two where it makes sense in the context of the +# debugging paradigm imposed by gdb. + +# See MACSBUG_HELP below (or execute it) for summary documentation of the +# supported MacsBug commands. See individual help documentation for more +# details and any MacsBug restrictions imposed on the commands. + +# NOTE: The expression syntax used in these functions is written using C +# syntax so this script is only applicable for debugging C/C++. If +# you are trying to debug any other language, you're probably +# screwed! + +# The author has endeavored to produce as complete a set of MacsBug commands as +# feasible within the restrictions imposed by the rather limited gdb command +# language. But others may have additional ideas. So contributions and +# embellishments are welcome, particularly to the types supported by the DM +# command. The only restrictions are that to be placed in this particular +# universe of commands (i.e., this file), they must be variants of *EXISTING* +# MacsBug commands. Any other "flavors" do not belong here. + +# Revision history +# +# 1-Sep-2000 ILR Initial creation. +# 2-Sep-2000 ILR Added basic type support to DM. +# Fixed DB and DW decimal display bug. +# Changed __print_char to bold octals and handle more +# known escape letters. +# Fixed argument handling to not cause possible +# reevaluation of their values in private +# functions. +# Prefixed all "local" internal function variables +# with double underbars to minimize potential +# name conflicts with their callers. Damn gdb! +# More tutorial info in MACSBUG_HELP. +# 3-Sep-2000 ILR Added ES, FIND, FB, FW, FL, and FILL commands. +# Allow SB, SW, SL, SM to have string values using +# the same machinery created for FIND and FILL. +# 4-Sept-2000 ILR Fixed size checking in SM and set. +# Add __lower_case function. +# Set $dot in DM for addr n case and let DM call +# __lower_case instead of doing it in DM command. +# Added GT, DMA, BRM, DX, MSET, and Rn commands. +# Enhanced DMA and __hexdump to check for repeated +# lines under the MSET DITTO state switch. +# Polished everything up for initial "release", +# whatever that means. +# 5-Sept-2000 ILR Added PC command. +# Made memory and disassembly displays contiguous +# when possible (i.e., removed the gdb prompt). +# 9-Sept-2000 ILR Changed MacsBug S to SI since it's a superset of +# gdb's S but essentially the same action. This +# free's up S to be gdb's S which executes single +# statements including stepping into called functions. +# I prefer to back the MacsBug compatibilty with S +# to preserve gdb's S. +# Changed T command to call SO to emphasize their +# same-ness and to have the actual code in one +# place just like I do for other aliased commands. +# 12-Sept-2000 ILR Added 2nd argument to T, SO and SI to disassemble m +# lines (default 4) instead of just 1. +# Removed a debugging printf from IP that I forgot +# to previously remove when I was debugging it. +# T was not missing in the MACSBUG_HELP display. +# ID's "Disassembly from" format string was missing +# a '%' causing a gdb error report. +# 25-Sept-2000 ILR Added __branch_taken to determine if a conditional +# branch at $pc will be taken or not. +# Added routines to display the registers in various +# ways along with disassembly. Only added, it's +# work in progress, and not yet hooked in. +# 9-Oct-2000 ILR Call __display_registers_h from __disasmN so that +# all disassemblies cause a register display at a +# fixed place at the top to the screen. This is +# brain dead version, i.e., no split screen scrolling. +# SM of log values was missing 3rd byte. +# 10-Oct-2000 ILR MSET UNMANGLE used as toggle was not setting gdb. +# 13-Oct-2000 ILR Fix DM so that repeated DM commands even with +# arguments (i.e., just hitting return to repeat the +# DM) causes a contiguous hexdump display. +# Similar fix for DMA. +# 11-Nov-2000 ILR __save_all_regs_h now saves compare and count portions +# of $xer. +# __display_registers_h changed to display compare and +# count portions of $xer. +# TD fixed to correct shift value of $xer to get compare +# field. +# 16-Nov-2000 ILR Added test to __branch_taken to not consider "branch +# always" branches as conditional branches. +# Changed __disasmN to use the vertical register display +# instead of the horizontal since the horizontal form +# screws up the scroll back. Vertical has less impact. +# 25-Nov-2000 ILR DM did not default to displaying the amount of the +# immediately preceeding DM. +# __display_registers_h and __display_registers_v changed +# to use red and normal/off color instead of red and +# black since black is not necessarily the same as +# normal on some terminal color schemes. +# ------------------------------------------------------------------------------- +# 12-Dec-2000 ILR Minor tweaks to various commands. +# Added RA command ("run again"). +# +# This script now deprecated. For the Mac it has been replaced with a version +# that works in conjunction with the Mac gdb plugin support. Not only does it +# do all the stuff this script does, it does so much more efficiently (i.e, +# it's faster), genaralized many of the functions becuase they are not limited +# by the gdb command language, and also has a MacsBug-like UI! +# +################################################################################### +################################################################################### + +# Current highest command identifier value for $__lastcmd__ is 41 + +# In each command assign $__lastcmd__ to a unique command number for each new +# command where applicable and update the above comment to make it easier to +# remember what to assign to future commands. + +# $__lastcmd__ is not just "noise". Some MacsBug simulated commands need to +# know what the previous command was to perform the required MacsBug semantics. + +################################################################################### +################################################################################### +# +# MACSBUG_HELP - List of supported commands. +# +define MACSBUG_HELP + # 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + printf "\n" + printf "BRC [addr] Clear all breakpoints or one breakpoint at addr\n" + printf "BRD Show all breakpoints (or breakpoint n)\n" + printf "BRM regex Set breakpoints at all functs matching regular expr\n" + printf "BRP [gdb-spec [expr]] Break at gdb-spec (under specified condition)\n" + printf "DB addr Display in hex the byte at addr (or $dot)\n" + printf "DL [addr] Display in hex the 4 bytes at addr (or $dot)\n" + printf "DM [addr [n | basicType]] Display memory from addr for n bytes or as a basic type\n" + printf "DMA [addr [n]] Display memory as ASCII from addr for n (default 512) bytes\n" + printf "DP [addr] Display 128 bytes at addr (or $dot)\n" + printf "DW [addr] Display in hex the two bytes at addr (or $dot)\n" + printf "DX [ON|OFF|NOW|SHOW] Temporarily enable/disable/toggle breakpoints\n" + printf "ES Exit to shell (unconditionally quit gdb)\n" + printf "FB addr n expr|\"string\" Search from addr to addr+n-1 for the byte\n" + printf "FILL addr n expr|\"string\" Fill from addr to addr+n-1 with expr or string\n" + printf "FIND addr n expr Search from addr to addr+n-1 for the pattern\n" + printf "FL addr n expr|\"string\" Search from addr to addr+n-1 for the 4-byte long\n" + printf "FW addr n expr|\"string\" Search from addr to addr+n-1 for the 2-byte word\n" + printf "G [addr] Continue execution (at addr if supplied)\n" + printf "GT gdb-spec Go (continue) until the gdb-spec is reached\n" + printf "ID [addr] Disassemble 1 line starting at addr (or pc)\n" + printf "IDP [addr] Same as ID\n" + printf "IL [addr [n]] Disassemble n (default 20) lines from the addr (or pc)\n" + printf "ILP [addr [n]] Same as IL\n" + printf "IP [addr] Disassemble 20 lines centered around the addr (or pc)\n" + printf "MR Return from current frame\n" + printf "MSET opt [ON|OFF|NOW|SHOW] Temporarially change the specified behavior\n" + printf "PC Display the value of the PC\n" + printf "Rn (n = 0, ... ,31) Display the value of register Rn\n" + printf "SB addr value1 [... value9] Assign up to 9 values to bytes starting at addr\n" + printf "SC Display back trace (stack crawl)\n" + printf "SC6 Same as SC\n" + printf "SC7 Same as SC\n" + printf "SI [n] [m] Step n (or 1) instruction(s), disassmble m lines\n" + printf "SL addr value1 [... value9] Assign up to 9 values to (4-byte) longs starting at addr\n" + printf "SM addr value1 [... value9] Assign up to 9 values to memory starting at addr\n" + printf "SO [n] [m] Step over n instructions, disassmble m lines\n" + printf "SW addr value1 [... value9] Assign up to 9 values to (2-byte) words starting at addr\n" + printf "T [n] [m] Same as SO\n" + printf "TD Display integer and machine registers\n" + printf "TF Display the floating point registers\n" + printf "TV Display the vector registers (not yet supported)\n" + printf "\n" + printf "The $dot gdb variable is the last address referenced by certain commands.\n" + printf "For instance, SM sets $dot to the first address that was changed. The\n" + printf "default for many commands is to use $dot as their address argument. Typing\n" + printf "DM will display the memory just set and set the last command to DM. A\n" + printf "return after the parameterless DM command will use the $dot set by it to\n" + printf "display then next block of memory in sequence.\n\n" + printf "This isn't quite like MacsBug but its as close an approximation as\n" + printf "possible in the gdb environment.\n" + printf "\n" + printf "Other differences between the gdb MacsBug commands and MacsBug itself:\n" + printf "\n" + printf " 1. Only C/C++ can be debugged since the gdb commands use C/C++ syntax\n" + printf " for their implementation (restriction imposed by gdb).\n\n" + printf " 2. Arguments are written using C/C++ syntax (e.g., use -> instead of\n" + printf " ^, != instead of <>, etc.).\n" + printf "\n" + printf " 3. Only one command per line allowed (gdb restriction).\n" + printf "\n" + printf " 4. Return executes previous command (gdb convention). This works\n" + printf " like MacsBug after a parameterless version of the command is entered\n" + printf " following a parameterized version (like the SM/DM example mentioned\n" + printf " above).\n" + printf "\n" + printf " 5. $dot instead of '.'.\n" + printf "\n" + printf " 6. Some restrictions on the commands that are supported. Do help on\n" + printf " individual commands for details.\n" + printf "\n" + printf " 7. Decimal values are shown without leading '#' and hex is shown with\n" + printf " a '0x' prefix.\n" + printf "\n" + printf " 8. The input radix is as defined by the gdb 'set input-radix' command.\n" + printf " The default is decimal unlike MacsBug which is hex. Use the gdb\n" + printf " command 'show input-radix' to verify the input radix.\n" + printf "\n" + printf " 9. Most of the MacsBug commands will cause gdb error reports until there\n" + printf " is a thread to debug (sometimes the error messages are rather cryptic).\n" + printf " So unlike MacsBug where you can issue commands as soon as you enter\n" + printf " MacsBug, you will need to start a debugging thread before issuing many\n" + printf " of the gdb MacsBug commands.\n" + printf "\n" + printf " 10. MSET is a subset of the macsBug SET command (gdb SET already exists).\n" + printf "\n" + printf " 11. SI is defined as the MacsBug S command (gdb S already exists).\n" + printf "\n" +end +document MACSBUG_HELP +MACSBUG_HELP <------- Summarize just the MacsBug commands ------- +end + +#printf "Type MACSBUG_HELP for help on the MacsBug commands.\n" + +################################################################################### +################################################################################### +# +# BRC [addr] +# +define BRC + if ($argc == 0) + delete + else + clear $arg0 + end + + set $__lastcmd__ = 1 +end +document BRC +BRC [addr] -- Clear all breakpoints or one breakpoint at addr. +See also gdb's DELETE command (clears breakpoints by number), and DISABLE. +end + +################################################################################### +# +# BRD [n] +# +define BRD + if ($argc == 0) + info breakpoints + else + info breakpoints $arg0 + end + + set $__lastcmd__ = 2 +end +document BRD +BRD -- Show all breakpoints (or breakpoint n). +end + +################################################################################### +# +# BRM regex +# +define BRM + if ($argc == 0) + printf "usage: BRM regex (regex expected)\n" + else + if ($argc == 1) + rbreak $arg0 + else + if ($argc == 2) + rbreak $arg0 $arg1 + else + if ($argc == 3) + rbreak $arg0 $arg1 $arg2 + else + if ($argc == 4) + rbreak $arg0 $arg1 $arg2 $arg3 + else + if ($argc == 5) + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 + else + if ($argc == 6) + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 + else + if ($argc == 7) + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 + else + if ($argc == 8) + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 + else + if ($argc == 9) + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 + else + # gdb will report error if > 10 args + rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 $arg9 + end + end + end + end + end + end + end + end + end + end + + set $__lastcmd__ = 38 +end +document BRM +BRM regex -- Set breakpoints at all functions matching regular expression. +This sets unconditional breakpoints on all matches, printing a list of all +breakpoints set. +Ê +Note, due to gdb function limitations there can be no more than 10 "words" +in the BRM regular expression, where a word is a sequence of non-blanks +characters. +end + +################################################################################### +# +# BRP [gdb-spec [expr]] +# +define BRP + if ($argc == 0) + br + else + if ($argc == 1) + br $arg0 + else + if ($argc == 2) + br $arg0 if $arg1 + else + if ($argc == 3) + br $arg0 if $arg1 $arg2 + else + if ($argc == 4) + br $arg0 if $arg1 $arg2 $arg3 + else + if ($argc == 5) + br $arg0 if $arg1 $arg2 $arg3 $arg4 + else + if ($argc == 6) + br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 + else + if ($argc == 7) + br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 + else + if ($argc == 8) + br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 + else + if ($argc == 9) + br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 + else + # gdb will report error if > 10 args + br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 $arg9 + end + end + end + end + end + end + end + end + end + end + + set $__lastcmd__ = 33 +end +document BRP +BRP [gdb-spec [expr]] -- Break at gdb-spec (under specified condition). +This implements the gdb "BREAK gdb-spec [if condition]". See gdb BREAK +documentation for further details. +Ê +Note, due to gdb function limitations there can be no more than 8 "words" +in the BRP condition expr, where a word is a sequence of non-blanks +characters. +Ê +Macsbug features not supported: Interation count. +Ê No semicolon before the command. +Ê Command is not enclosed in quotes. +Ê Only a single command is allowed. +end + +################################################################################### +# +# DB [addr] +# +define DB + if ($argc == 0) + if ($__lastcmd__ == 3) + set $dot = (unsigned char *)$dot + 1 + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + end + else + set $dot = $arg0 + end + + set $value = *(unsigned char *)$dot + + printf "Byte at %.8X = 0x%.2X %u %d ", $dot, $value, $value, (char)$value + __print_1 $value + printf "\n" + + set $__lastcmd__ = 3 +end +document DB +DB addr -- Display in hex the byte at addr (or $dot). +end + +################################################################################### +# +# DL [addr] +# +define DL + if ($argc == 0) + if ($__lastcmd__ == 4) + set $dot = (unsigned char *)$dot + 4 + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + end + else + set $dot = $arg0 + end + + set $addr = $dot + + set $value = *(unsigned char *)$addr + set $addr = (unsigned char *)$addr + 1 + + set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr + set $addr = (unsigned char *)$addr + 1 + + set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr + set $addr = (unsigned char *)$addr + 1 + + set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr + + printf "Four bytes at %.8X = 0x%.8X %u %d ", $dot, $value, $value, $value + __print_4 $value + printf "\n" + + set $__lastcmd__ = 4 +end +document DL +DL [addr] -- Display in hex the 4 bytes at addr (or $dot). +end + +# This is written assuming no alignment requiremnts. However, most machines +# actuall allow unaligned access. We could actually get away with set +# $value = *(unsigned long *)$addr. But I'll leave it the way it is since +# that way never has alignement concerns. + +################################################################################### +# +# DM [addr [n | basic type]] +# +define DM + if ($argc == 0) + if ($__lastcmd__ == 5) + set $dot = (unsigned char *)$dot + $__prev_dm_n__ + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + printf "Displaying memory from %.8X\n", $dot + set $__prev_dm_n__ = 16 + end + __hexdump $dot + set $__next_addr__ = (unsigned char *)$dot + 16 + set $__lastcmd__ = 5 + else + if ($argc == 1) + if (0 && $__lastcmd__ == 5 && $__next_addr__ == (unsigned char *)$dot + $__prev_dm_n__) + set $dot = (unsigned char *)$dot + $__prev_dm_n__ + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + set $dot = (unsigned char *)$arg0 + printf "Displaying memory from %.8X\n", $dot + set $__prev_dm_n__ = 16 + end + __hexdump $dot + set $__next_addr__ = (unsigned char *)$dot + 16 + set $__lastcmd__ = 5 + else + set $addr0 = (unsigned char *)$arg0 + set $n = (char *)"$arg1" + if ($n[0] >= '0' && $n[0] <= '9') + if (0 && $__lastcmd__ == 5 && $__next_addr__ == (unsigned char *)$dot + $__prev_dm_n__) + set $addr0 = (unsigned char *)$dot + $__prev_dm_n__ + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + printf "Displaying memory from %.8X\n", $addr0 + end + set $dot = $addr0 + set $__prev_dm_n__ = $arg1 + __hexdump $dot $__prev_dm_n__ + set $__next_addr__ = (unsigned char *)$dot + $__prev_dm_n__ + set $__lastcmd__ = 5 + else + # Basic types displays have no effect on $dot and invalidate the + # previous command ($__lastcmd__) state for all other commands forcing + # them to use the current $dot value as their default. + + set $__lastcmd__ = -5 + + # Handle the types specified by MacsBug (or at least trhy to where we can). + + # The types are: Byte, Word, Long, SignedByte, SignedWord, SignedLong, + # UnsignedByte, UnsignedWord, UnsignedLong, PString, + # CString, Boolean, Text, Pointer, Handle, IORefNum, + # VRefNum, Seconds, ATrapWord, Binary8, Binary16, Binary32, + # OSType, AbsTicks, TickInterval, RgnHandle, IOTrapWord, + # Version, RGBColor, Fixed, ShortFixed, UnsignedFixed, + # Fract, Rect, and Region. Who knows what else? These, + # (actually except for Region) are the only ones + # documented in MacsBug help command. + + # Because of gdb's brain-dead command language this leads to the mother + # of all nested if statements! To avoid overly indenting this turkey and + # to at least give the taste of a switch statement each "case" is not + # indented. Of course this means all the 'end's for the if's pile up at + # the end of this "switch". And NO, gdb won't let me comment them either + # to indicate which 'end' goes with which 'if'. Trust me, I tried. I + # also tried "else if". Like I said, gdb's command language is brain + # dead :-( + + __lower_case $arg1 + + set $unsupported = 0 + + __strcmp $lower_case "byte" + if ($strcmp) + printf "Displaying Byte\n" + printf " %.8X: %.2X\n", $addr0, *(unsigned char *)$addr0 & 0xFF + else + __strcmp $lower_case "word" + if ($strcmp) + printf "Displaying Word\n" + printf " %.8X: %.4X\n", $addr0, *(unsigned short *)$addr0 & 0xFFFF + else + __strcmp $lower_case "long" + if ($strcmp) + printf "Displaying Long\n" + printf " %.8X: %.8X\n", $addr0, *(unsigned long *)$addr0 + else + __strcmp $lower_case "signedbyte" + if ($strcmp) + printf "Displaying SignedByte\n" + printf " %.8X: %d\n", $addr0, *(char *)$addr0 + else + __strcmp $lower_case "signedword" + if ($strcmp) + printf "Displaying SignedWord\n" + printf " %.8X: %d\n", $addr0, *(short *)$addr0 + else + __strcmp $lower_case "signedlong" + if ($strcmp) + printf "Displaying SignedLong\n" + printf " %.8X: %d\n", $addr0, *(long *)$addr0 + else + __strcmp $lower_case "unsignedbyte" + if ($strcmp) + printf "Displaying UnsignedByte\n" + printf " %.8X: %u\n", $addr0, *(unsigned char *)$addr0 + else + __strcmp $lower_case "unsignedword" + if ($strcmp) + printf "Displaying UnsignedWord\n" + printf " %.8X: %u\n", $addr0, *(unsigned short *)$addr0 + else + __strcmp $lower_case "unsignedlong" + if ($strcmp) + printf "Displaying UnsignedLong\n" + printf " %.8X: %u\n", $addr0, *(unsigned long *)$addr0 + else + __strcmp $lower_case "pstring" + if ($strcmp) + printf "Displaying PString\n" + set $len = *((unsigned char *)$addr0)++ + printf " %.8X: (%d) \"", $addr0, $len + while ($len--) + set $c = *((unsigned char *)$addr0)++ + __print_char $c 1 + end + printf "\"\n" + else + __strcmp $lower_case "cstring" + if ($strcmp) + printf "Displaying CString\n" + printf " %.8X: \"", $addr0 + set $c = *((unsigned char *)$addr0)++ + while ($c) + __print_char $c 1 + set $c = *((unsigned char *)$addr0)++ + end + printf "\"\n" + else + __strcmp $lower_case "boolean" + if ($strcmp) + printf "Displaying Boolean\n" + if (*(unsigned char *)$addr0) + printf " %.8X: true\n", $addr0 + else + printf " %.8X: false\n", $addr0 + end + else + __strcmp $lower_case "binary8" + if ($strcmp) + printf "Displaying Binary8\n" + set $value = *(unsigned char *)$addr0 + printf " %.8X: %.2X = ", $addr0, $value & 0xFF + __binary ($value>>4&15) 4 + printf " " + __binary ($value&15) 4 + printf "\n" + else + __strcmp $lower_case "binary16" + if ($strcmp) + printf "Displaying Binary16\n" + set $value = *(unsigned short *)$addr0 + printf " %.8X: %.4X = ", $addr0, $value & 0xFFFF + __binary ($value>>12&15) 4 + printf " " + __binary ($value>>8&15) 4 + printf " " + __binary ($value>>4&15) 4 + printf " " + __binary ($value&15) 4 + printf "\n" + else + __strcmp $lower_case "binary32" + if ($strcmp) + printf "Displaying Binary32\n" + set $value = *(unsigned long *)$addr0 + printf " %.8X: %.8X = ", $addr0, $value + __binary ($value>>28&15) 4 + printf " " + __binary ($value>>24&15) 4 + printf " " + __binary ($value>>20&15) 4 + printf " " + __binary ($value>>16&15) 4 + printf " " + __binary ($value>>12&15) 4 + printf " " + __binary ($value>>8&15) 4 + printf " " + __binary ($value>>4&15) 4 + printf " " + __binary ($value&15) 4 + printf "\n" + else + __strcmp $lower_case "ostype" + if ($strcmp) + printf "Displaying OSType\n" + set $value = *(unsigned long *)$addr0 + printf " %.8X: %.8X = ", $addr0, $value + __print_4 $value + printf "\n" + else + __strcmp $lower_case "rect" + if ($strcmp) + printf "Displaying Rect\n" + set $addr = $addr0 + set $top = *((unsigned short *)$addr)++ + set $left = *((unsigned short *)$addr)++ + set $bottom = *((unsigned short *)$addr)++ + set $right = *((unsigned short *)$addr) + printf " %.8X: %d %d %d %d (t,l,b,r) %d %d (w,h)\n", $addr0, \ + $top, $left, $bottom, $right, $right-$left, $bottom-$top + else + __strcmp $lower_case "pointer" + if ($strcmp) + set $unsupported = "Pointer" + else + __strcmp $lower_case "handle" + if ($strcmp) + set $unsupported = "Handle" + else + __strcmp $lower_case "region" + if ($strcmp) + set $unsupported = "Region" + else + __strcmp $lower_case "rgnhandle" + if ($strcmp) + set $unsupported = "RgnHandle" + else + __strcmp $lower_case "fixed" + if ($strcmp) + set $unsupported = "Fixed" + else + __strcmp $lower_case "shortfixed" + if ($strcmp) + set $unsupported = "ShortFixed" + else + __strcmp $lower_case "unsignedfixed" + if ($strcmp) + set $unsupported = "UnsignedFixed" + else + __strcmp $lower_case "fract" + if ($strcmp) + set $unsupported = "Fract" + else + __strcmp $lower_case "rgbcolor" + if ($strcmp) + set $unsupported = "RGBColor" + else + __strcmp $lower_case "text" + if ($strcmp) + set $unsupported = "Text" + else + __strcmp $lower_case "iorefnum" + if ($strcmp) + set $unsupported = "IORefNum" + else + __strcmp $lower_case "vrefnum" + if ($strcmp) + set $unsupported = "VRefNum" + else + __strcmp $lower_case "seconds" + if ($strcmp) + set $unsupported = "Seconds" + else + __strcmp $lower_case "atrapword" + if ($strcmp) + set $unsupported = "ATrapWord" + else + __strcmp $lower_case "absticks" + if ($strcmp) + set $unsupported = "AbsTicks" + else + __strcmp $lower_case "tickinterval" + if ($strcmp) + set $unsupported = "TickInterval" + else + __strcmp $lower_case "iotrapword" + if ($strcmp) + set $unsupported = "IOTrapWord" + else + __strcmp $lower_case "version" + if ($strcmp) + set $unsupported = "Version" + else + printf "Unrecognized type.\n" + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + end + + if ($unsupported) + printf "%s is not supported in the gdb MacsBug commands.\n", $unsupported + printf "Use the gdb PRINT command. With appropriate type\n" + printf "casts you'll probably get better results anyhow.\n" + end + end + end + end +end +document DM +DM [addr [n | basic type]] -- Display memory from addr for n bytes or as a basic type. +The basic types are Byte, Word, Long, SignedByte, SignedWord, SignedLong, +UnsignedByte, UnsignedWord, UnsignedLong, PString, CString, Boolean, +Binary8, Binary16, Binary32, OSType, and Rect. +Ê +Also see MSET for DITTO mode. +Ê +Macsbug features not supported: templates and the following basic types. +Ê Pointer, Handle, RGBColor, Text, IORefNum, +Ê VRefNum, Seconds, ATrapWord, AbsTicks, +Ê TickInterval, Region, RgnHandle, IOTrapWord, +Ê Version, Fixed, ShortFixed, UnsignedFixed, +Ê and Fract. +end + +################################################################################### +# +# DMA [addr [n]] +# +define DMA + if ($argc == 0) + if ($__lastcmd__ == 37) + set $dot = (unsigned char *)$dot + $__prev_dma_n__ + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + printf "Displaying memory from %.8X\n", $dot + set $__prev_dma_n__ = 512 + end + else + if (0 && $__lastcmd__ == 37 && $__next_addr__ == (unsigned char *)$dot + $__prev_dma_n__) + set $dot = (unsigned char *)$dot + $__prev_dma_n__ + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + set $dot = (unsigned char *)$arg0 + printf "Displaying memory from %.8X\n", $dot + end + if ($argc == 1) + set $__prev_dma_n__ = 512 + else + set $__prev_dma_n__ = $arg1 + end + end + + set $addr = $dot + set $addr1 = (unsigned char *)$addr + $__prev_dma_n__ + + set $prevaddr = (unsigned char *)$addr + set $rep_count = 0 + + while ($addr < $addr1) + # Only allow full ditto lines and never the last line + if ((unsigned char *)$addr + 64 < $addr1) + __repeated_dump_line $prevaddr $addr 64 + else + set $repeated = 0 + end + set $prevaddr = (unsigned char *)$addr + + if ($repeated) + if ($rep_count++ == 0) + printf " %.8X: ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\n", $addr + end + set $addr = (char *)$addr + 64 + else + set $rep_count = 0 + printf " %.8X: ", $addr + set $i = 0 + while ($i++ < 64 && $addr < $addr1) + set $x = *((unsigned char *)$addr)++ + if ($x >= 0x20 && $x <= 0x7F) + printf "%c", $x + else + printf "." + end + end + printf "\n" + end + end + + set $__next_addr__ = $addr1 + + set $__lastcmd__ = 37 +end +document DMA +DMA [addr [n]] -- Display memory as ASCII from addr for n (default 512) bytes. +ASCII characters outside the range 0x20 to 0x7F are shown as '.'s. +Ê +Also see MSET for DITTO mode. +end + +################################################################################### +# +# DP [addr] +# +define DP + if ($argc == 0) + if ($__lastcmd__ == 6) + set $dot = (unsigned char *)$dot + 128 + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + else + printf "Displaying memory from %.8X\n", $dot + end + else + set $dot = $arg0 + printf "Displaying memory from %.8X\n", $dot + end + + __hexdump $dot 128 + + set $__lastcmd__ = 6 +end +document DP +DP [addr] -- Display 128 bytes at addr (or $dot). +end + +################################################################################### +# +# DW [addr] +# +define DW + if ($argc == 0) + if ($__lastcmd__ == 7) + set $dot = (unsigned char *)$dot + 2 + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[2A\n", 0x1B + end + else + set $dot = $arg0 + end + + set $addr = $dot + + set $value = *(unsigned char *)$addr + set $addr = (unsigned char *)$addr + 1 + + set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr + + printf "Two bytes at %.8X = 0x%.4X %u %d ", $dot, $value, $value, (short)$value + __print_2 $value + printf "\n" + + set $__lastcmd__ = 7 +end +document DW +DW [addr] -- Display in hex the two bytes at addr (or $dot). +end + +# This is written assuming no alignment requiremnts. However, most machines +# actuall allow unaligned access. We could actually get away with set +# $value = *(unsigned short *)$addr. But I'll leave it the way it is since +# that way never has alignement concerns. + +################################################################################### +# +# DX [ON | OFF | NOW | SHOW] +# +# Note the "polarity" of the DX state switch is reversed, i.e., 0 means enabled/on, +# 1 means disabled/off. The reason for this is that if this command could be done +# before the DX state switch is defined (void in gdb, setting it outside the function +# has no effect). We can only test undefined gdb convenience variables with 'if ($dx)' +# (can't even negate it) which would be false when the switch is undefined, i.e., same +# result as if it were 0. Our initial default is to be ON, so undefined must also +# mean ON. Hence the polarity reversal. #%$@!()& gdb! +# +define DX + if ($argc == 0) + if ($__dx__) + set $__dx__ = 0 + enable breakpoints + printf "Breakpoints enabled\n" + else + set $__dx__ = 1 + disable breakpoints + printf "Breakpoints disabled\n" + end + else + __lower_case $arg0 + __strcmp $lower_case "on" + if ($strcmp) + if ($__dx__) + set $__dx__ = 0 + enable breakpoints + printf "Breakpoints enabled\n" + else + printf "Breakpoints still enabled\n" + end + else + __strcmp $lower_case "off" + if ($strcmp) + if ($__dx__) + printf "Breakpoints still disabled\n" + else + set $__dx__ = 1 + disable breakpoints + printf "Breakpoints disabled\n" + end + else + set $e = 1 + __strcmp $lower_case "now" + if ($strcmp) + set $e = 0 + else + __strcmp $lower_case "show" + if ($strcmp) + set $e = 0 + end + end + if ($e || $argc > 1) + printf "usage: DX [ON | OFF | NOW | SHOW] (invalid setting)\n" + else + if ($__dx__) + printf "Breakpoints still disabled\n" + else + printf "Breakpoints still enabled\n" + end + end + end + end + end + + set $__lastcmd__ = 39 +end +document DX +DX [ON | OFF | NOW | SHOW] -- Temporarily enable/disable/toggle breakpoints. +The setting is toggled when there is no argument. +Ê +SHOW is the same as NOW to display the current setting. It was added +since gdb uses SHOW to show settings. +end + +################################################################################### +# +# ES +# +define ES + set confirm off + quit +end +document ES +ES -- exit to shell (unconditionally quit gdb). +end + +################################################################################### +# +# FB addr n expr|"string" +# +define FB + FIND $arg0 $arg1 $arg2 1 +end +document FB +FB addr n expr|"string" -- Search from addr to addr+n-1 for the byte. +Ê +The MacsBug FB command overrides the gdb FB alias for a gdb FUTURE_BREAK +command. Use FU for the FUTURE_BREAK command. +end + +################################################################################### +# +# FILL addr n expr|"string" +# +define FILL + set $addr = $arg0 + set $n = $arg1 + + set $dot = $addr + + __is_string ($arg2) + + if ($string) + set $p = (unsigned char *)$string + __strlen $string + set $b = 0 + while ($n--) + set *((unsigned char *)$addr)++ = $string[$b] + if (++$b >= $strlen) + set $b = 0 + end + end + else + set $value = (long)$arg2 + if ($value >= -128 && $value <= 255) + while ($n--) + set *((unsigned char *)$addr)++ = (unsigned char)$value & 0xFF + end + else + if ($value >= -32768 && $value <= 65535) + set $b = 0 + while ($n--) + if ($b == 0) + set *((unsigned char *)$addr)++ = ((unsigned short)$value >> 8) & 0xFF + set $b = 1 + else + set *((unsigned char *)$addr)++ = (unsigned short)$value & 0xFF + set $b = 0 + end + end + else + set $b = 0 + while ($n--) + if ($b == 0) + set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 24) & 0xFF + set $b = 1 + else + if ($b == 1) + set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 16) & 0xFF + set $b = 2 + else + if ($b == 2) + set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 8) & 0xFF + set $b = 3 + else + set *((unsigned char *)$addr)++ = (unsigned long)$value & 0xFF + set $b = 0 + end + end + end + end + end + end + end + + printf "Memory set starting at %.8X\n", $dot + __hexdump $dot $arg1 + + set $__lastcmd__ = 34 +end +document FILL +FILL addr n expr|"string" -- Fill from addr to addr+n with expr or string. +The fill is repeatedly used as a byte, word, or long (determined by the size +of the expr value) or the string. +end + +################################################################################### +# +# FIND addr n expr|"string" [size] +# +# The size is an INTERNAL option to be able to use the general FIND function for +# FB, FW, and FL. +# +define FIND + set $e = 0 + + if ($argc > 3) + if ($arg3 != 1 && $arg3 != 2 && $arg3 != 4) + printf "usage: FIND addr n expr|"string" (wrong number of arguments)\n" + set $e = 1 + else + set $size = $arg3 + end + else + set $size = 0 + end + + if (!$e) + set $addr = $arg0 + set $addr1 = (unsigned char *)$addr + ($arg1) + set $found = 0 + + __is_string ($arg2) + + if ($string) + set $n = $arg1 + set $addr1 = $addr1 - $n + while (!$found && $addr < $addr1) + __strncmp $string $addr $n + if ($strncmp) + set $found = $addr + else + set ++((unsigned char *)$addr) + end + end + else + set $value = (long)$arg2 + if ($size == 1 || (!$size && ($value >= -128 && $value <= 255))) + set $size = 1 + set $value = (unsigned char)$value & 0xFF + while (!$found && $addr < $addr1) + if (*(unsigned char *)$addr == (unsigned char)$value) + set $found = $addr + else + set ++((unsigned char *)$addr) + end + end + else + if ($size == 2 || (!$size && ($value >= -32768 && $value <= 65535))) + set $size = 2 + set $addr1 = $addr1 - 2 + set $value = (unsigned short)$value & 0xFFFF + while (!$found && $addr < $addr1) + if (*(unsigned char *)$addr == (((unsigned short)$value >> 8) & 0xFF) && \ + *((unsigned char *)$addr+1) == ((unsigned short)$value & 0xFF)) + set $found = $addr + else + set ++((unsigned char *)$addr) + end + end + else + set $size = 4 + set $addr1 = $addr1 - 4 + while (!$found && $addr < $addr1) + if (*(unsigned char *)$addr == (((unsigned long)$value >> 24) & 0xFF) && \ + *((unsigned char *)$addr+1) == (((unsigned long)$value >> 16) & 0xFF) && \ + *((unsigned char *)$addr+2) == (((unsigned long)$value >> 8) & 0xFF) && \ + *((unsigned char *)$addr+3) == ((unsigned long)$value & 0xFF)) + set $found = $addr + else + set ++((unsigned char *)$addr) + end + end + end + end + end + end + + if (!$e) + printf "Searching for " + if ($string) + __strlen $string + printf "\"" + set $i = 0 + while ($strlen--) + __print_char $string[$i++] + end + printf "\"" + else + if ($size == 1) + printf "0x%.2X", $value + else + if ($size == 2) + printf "0x%.4X", $value + else + printf "0x%.8X", $value + end + end + end + printf " from 0x%.8X to 0x%.8X\n", $addr, (char *)$addr1-1 + + if (!$found) + printf "%c[31m Not found%c[0m\n", 0x1B, 0x1B + else + set $dot = $found + __hexdump $dot + end + end + + set $__lastcmd__ = 35 +end +document FIND +FIND addr n expr -- Search from addr to addr+n-1 for the pattern. +If pattern is an expr then the width of the pattern is the smallest +unit (byte, word or long) that contains its value. +Ê +Restriction: The expr value may not have any embedded blanks. For example +Ê a value like (unsigned char *)&a is invalid. +Ê +Macsbug features not supported: MacsBug F must be FIND here since F conflicts +Ê with the gdb FRAME command abbreviation. +Ê +Ê Double quoted "string" instead of single quoted +Ê 'string'. +Ê +Ê To keep the same semantics as MacsBug you run +Ê the risk of trying to search beyond the end of +Ê your memory since the comparison limit is based +Ê on the first byte of the objects to be matched +Ê rather than the last. +end + +################################################################################### +# +# FL addr n expr|"string" +# +define FL + FIND $arg0 $arg1 $arg2 4 +end +document FL +FL addr n expr|"string" -- Search from addr to addr+n-1 for the 4-byte long. +end + +################################################################################### +# +# FW addr n expr|"string" +# +define FW + FIND $arg0 $arg1 $arg2 2 +end +document FW +FW addr n expr|"string" -- Search from addr to addr+n-1 for the 2-byte word. +end + +################################################################################### +# +# G [addr] +# +define G + if ($argc != 0) + set $pc = $arg0 + end + + set $__lastcmd__ = 8 + continue +end +document G +G [addr] -- Continue execution (at addr if supplied) +end + +################################################################################### +# +# GT gdb-spec +# +define GT + tbreak $arg0 + set $__lastcmd__ = 36 + continue +end +document GT +GT gdb-spec -- Go (continue) until the gdb-spec is reached. +This implements the gdb "TBREAK gdb-spec". See gdb TBREAK +documentation for further details. +Ê +Macsbug features not supported: Command list not allowed. +end + +################################################################################### +# +# ID [addr] +# +define ID + if ($argc == 1) + set $dot = $arg0 + else + if ($__lastcmd__ == 9) + set $dot = (unsigned char *)$dot + 4 + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0) + else + set $dot = $pc + printf "Disassembly from %.8X\n", $dot + end + end + __disasmN $dot 1 + + set $__lastcmd__ = 9 +end +document ID +ID [addr] -- Disassemble 1 line starting at addr (or pc). +Ê +Macsbug features not supported: -c option. +end + +################################################################################### +# +# IDP [addr] +# +define IDP + if ($argc == 1) + id $arg0 + else + id + end + + #set $__lastcmd__ = $__lastcmd__ +end +document IDP +IDP [addr] -- Same as ID. +end + +################################################################################### +# +# IL [addr [n]] +# +define IL + if ($argc == 0) + if ($__lastcmd__ == 11) + set $dot = (unsigned char *)$dot + (4*20) + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *(char *)$dot + printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0) + else + set $dot = $pc + end + set $n = 20 + else + if ($argc == 1) + set $dot = $arg0 + set $n = 20 + else + set $dot = $arg0 + set $n = $arg1 + end + end + + __disasmN $dot $n + + set $__lastcmd__ = 11 +end +document IL +IL [addr [n]] -- Disassemble n (default 20) lines from the addr or pc. +Ê +Macsbug features not supported: -c option. +end + +################################################################################### +# +# ILP [addr [n]] +# +define ILP + if ($argc == 0) + il + else + if ($argc == 1) + il $arg0 + else + il $arg0 $arg1 + end + end + + #set $__lastcmd__ = $__lastcmd__ +end +document ILP +ILP [addr [n]] -- Same as IL. +end + +################################################################################### +# +# IP [addr] +# +define IP + if ($argc == 1) + set $dot = $arg0 + else + if ($__lastcmd__ == 13) + set $dot = (unsigned char *)$dot + (21*4) + # The following makes the displays contiguous by moving the cursor + # up over the gdb prompt. But just in case the display would fail + # because the memory is inaccessible we try to access the first + # byte of the display and let gdb error it out before moving the + # cursor if the memory is inaccessible. + set $accessible = *((char *)$dot - 40) + printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0) + else + set $dot = $pc + end + end + + # __disasmN takes a third argument only used here. This third argument is + # $dot so we can specially flag the $dot address in the disassembly to make + # it more easily identifiable in the display. + + __disasmN ($dot-40) 21 $dot + + set $__lastcmd__ = 13 +end +document IP +IP [addr] -- Disassemble 20 lines centered around the addr (or pc). +Ê +Macsbug features not supported: -c option. +end + +################################################################################### +# +# IPP [addr] +# +define IPP + if ($argc == 1) + ip $arg0 + else + ip + end + + #set $__lastcmd__ = $__lastcmd__ +end +document IPP +IPP [addr] -- Same as IP. +end + +################################################################################### +# +# MR +# +define MR + if ($argc != 0) + printf "Only the parameterless form of MR is supported.\n" + else + finish + end + + set $__lastcmd__ = 15 +end +document MR +MR -- Return from current frame. +Ê +Macsbug features not supported: offset and addr arguments +end + +################################################################################### +# +# MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] +# +# Note that the initial settings for these state switches is OFF. I'm mentioning this +# to point out the fact because it is possible that this command could be executed +# BEFORE the switches are defined (void in gdb, setting it outside the function has no +# effect). We can only test undefined gdb convenience variables with 'if ($dx)' +# (can't even negate it) which would be false when the switch is undefined, i.e., same +# result as if it were 0. Our initial default for these switches is OFF, so undefined +# and 0 have the same effect to indicate OFF. Bit if any future switches are added, +# and their default is to be ON, then their polarity will have to be reversed; 0 meaning +# ON and 1 meaning OFF. This is so the testing for those switches when they are +# initially undefined has the desired effect. #%$@!()& gdb! +# +define MSET + set $e = 0 + + if ($argc == 0) + printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (missing arguments)\n" + else + __lower_case $arg0 + __strcmp $lower_case "ditto" + if ($strcmp) + set $which = 1 + else + __strcmp $lower_case "unmangle" + if ($strcmp) + set $which = 2 + else + set $e = 1 + printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid option)\n" + end + end + + if (!$e) + if ($argc == 1) + if ($which == 1) + if ($__ditto__) + set $__ditto__ = 0 + printf "Ditto-display in memory dumps disabled\n" + else + set $__ditto__ = 1 + printf "Ditto-display in memory dumps enabled\n" + end + else + if ($__unmangle__) + set $__unmangle__ = 0 + printf "Unmangling of symbols disabled\n" + set print demangle off + set print asm-demangle off + else + set $__unmangle__ = 1 + set print demangle on + set print asm-demangle on + printf "Unmangling of symbols enabled\n" + end + end + else + __lower_case $arg1 + __strcmp $lower_case "on" + if ($strcmp) + if ($which == 1) + if ($__ditto__) + printf "Ditto-display in memory dumps is still enabled\n" + else + set $__ditto__ = 1 + printf "Ditto-display in memory dumps is enabled\n" + end + else + if ($__unmangle__) + printf "Unmangling of symbols is still enabled\n" + else + set $__unmangle__ = 1 + set print demangle on + set print asm-demangle on + printf "Unmangling of symbols is enabled\n" + end + end + else + __strcmp $lower_case "off" + if ($strcmp) + if ($which == 1) + if ($__ditto__) + set $__ditto__ = 0 + printf "Ditto-display in memory dumps is disabled\n" + else + printf "Ditto-display in memory dumps is still disabled\n" + end + else + if ($__unmangle__) + set $__unmangle__ = 0 + set print demangle off + set print asm-demangle off + printf "Unmangling of symbols is disabled\n" + else + printf "Unmangling of symbols is still disabled\n" + end + end + else + __strcmp $lower_case "now" + if (!$strcmp) + __strcmp $lower_case "show" + if (!$strcmp) + set $e = 1 + end + end + if ($e || $argc > 2) + printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid setting)\n" + else + if ($which == 1) + if ($__ditto__) + printf "Ditto-display in memory dumps is enabled\n" + else + printf "Ditto-display in memory dumps is disabled\n" + end + else + if ($__unmangle__) + printf "Unmangling of symbols is still enabled\n" + else + printf "Unmangling of symbols is still disabled\n" + end + end + end + end + end + end + end + end + + set $__lastcmd__ = 40 +end +document MSET +MSET option [ON|OFF|NOW|SHOW] -- Temporarially change the specified gdb MacsBug behavior. +On/off options toggle if you don't specify ON or OFF. NOW or SHOW lets you check +the setting without disturbing it. The options are: +Ê +Ê DITTO: When on, DM and DMA show ditto marks (''''''') instead of groups +Ê of identical lines. + +Ê UNMANGLE: When on, C++ symbols appear as in source code, such as "TFoo::Bar()". +Ê When off, you'll see stuff like "Bar__4TFooFv" instead. + +SHOW is the same as NOW to display the current setting. It was added since gdb +uses SHOW to show settings. +Ê +Macsbug features not supported: The is the MacsBug SET command was changed to +Ê MSET since SET conflicts with the SET gdb command. +Ê +Ê Options AUTOGP, ECHO, MOUSE, MENUBAR, SCROLLPROMPT, +Ê SUSPENDPROMPT, and SIMPLIFIED not supported. +end + +################################################################################### +# +# PC, R0 - R31 +# +define PC + __rn $pc +end +document PC +PC -- display the value of PC +end +# +define R0 + __Rn $r0 +end +document R0 +R0 -- display the value of R0 +end +# +define R1 + __Rn $r1 +end +document R1 +R1 -- display the value of R1 +end +# +define R2 + __Rn $r2 +end +document R2 +R2 -- display the value of R2 +end +# +define R3 + __Rn $r3 +end +document R3 +R3 -- display the value of R3 +end +# +define R4 + __Rn $r4 +end +document R4 +R4 -- display the value of R4 +end +# +define R5 + __Rn $r5 +end +document R5 +R5 -- display the value of R5 +end +# +define R6 + __Rn $r6 +end +document R6 +R6 -- display the value of R6 +end +# +define R7 + __Rn $r7 +end +document R7 +R7 -- display the value of R7 +end +# +define R8 + __Rn $r8 +end +document R8 +R8 -- display the value of R8 +end +# +define R9 + __Rn $r9 +end +document R9 +R9 -- display the value of R9 +end +# +define R10 + __Rn $r10 +end +document R10 +R10 -- display the value of R10 +end +# +define R11 + __Rn $r11 +end +document R11 +R11 -- display the value of R11 +end +# +define R12 + __Rn $r12 +end +document R12 +R12 -- display the value of R12 +end +# +define R13 + __Rn $r13 +end +document R13 +R13 -- display the value of R13 +end +# +define R14 + __Rn $r14 +end +document R14 +R14 -- display the value of R14 +end +# +define R15 + __Rn $r15 +end +document R15 +R15 -- display the value of R15 +end +# +define R16 + __Rn $r16 +end +document R16 +R16 -- display the value of R16 +end +# +define R17 + __Rn $r17 +end +document R17 +R17 -- display the value of R17 +end +# +define R18 + __Rn $r18 +end +document R18 +R18 -- display the value of R18 +end +# +define R19 + __Rn $r19 +end +document R19 +R19 -- display the value of R19 +end +# +define R20 + __Rn $r20 +end +document R20 +R20 -- display the value of R20 +end +# +define R21 + __Rn $r21 +end +document R21 +R21 -- display the value of R21 +end +# +define R22 + __Rn $r22 +end +document R22 +R22 -- display the value of R22 +end +# +define R23 + __Rn $r23 +end +document R23 +R23 -- display the value of R23 +end +# +define R24 + __Rn $r24 +end +document R24 +R24 -- display the value of R24 +end +# +define R25 + __Rn $r25 +end +document R25 +R25 -- display the value of R25 +end +# +define R26 + __Rn $r26 +end +document R26 +R26 -- display the value of R26 +end +# +define R27 + __Rn $r27 +end +document R27 +R27 -- display the value of R27 +end +# +define R28 + __Rn $r28 +end +document R28 +R28 -- display the value of R28 +end +# +define R29 + __Rn $r29 +end +document R29 +R29 -- display the value of R29 +end +# +define R30 + __Rn $r30 +end +document R30 +R30 -- display the value of R30 +end +# +define R31 + __Rn $r31 +end +document R31 +R31 -- display the value of R31 +end +# +# __rn reg - display a single register value +# +# This is the common routine used by all Rn (n = 0...31) functions. The +# register arg is the actual register specified ($rn) in lower case (since +# upper case $Ri appears to be a undefined convenience symbol). This +# internal routine is placed here since it is only for the singe register +# command displays immediate above here. +# +# The format we use is identical to the DL command. MacsBug also puts some +# just in parenthesis after the value which I think is of dubious use. So +# the hell with it. +# +define __Rn + set $__r = (char *)"$arg0" + set $__r[1] = 'A' + ($__r[1] - 'a') + if ($__r[1] == 'P') + set $__r[2] = 'A' + ($__r[2] - 'a') + end + printf "%s = 0x%.8X %u %d ", &$__r[1], $arg0, $arg0, $arg0 + __print_4 $arg0 + printf "\n" + set $__lastcmd__ = 41 +end +document __Rn +For internal use only -- do not use. +end + +################################################################################### +# +# RA +# +define RA + set confirm off + run + set confirm on +end +document RA +RA -- Unconditionaly restart (run) with current argument list ("run again"). +This is identical to RUN except no prompt is displayed if the program is +currently running. The debugged program is unconditionally restarted. + +Assumes confirmation is on, or it will be on after this command is executed. + +Note, this is NOT a MacsBug command but it is useful in a gdb environment. +end + +################################################################################### +# +# SB addr value1 [... value9] +# +define SB + if ($argc < 2) + printf "usage: SB addr value1 [... value9]\n" + set $e = 1 + else + set $addr = $arg0 + set $e = 0 + end + + set $debug = 0 + + set $i = 1 + + while ($i < $argc && $e == 0) + if ($i == 1) + set $value = $arg1 + __is_string ($arg1) + else + if ($i == 2) + set $value = $arg2 + __is_string ($arg2) + else + if ($i == 3) + set $value = $arg3 + __is_string ($arg3) + else + if ($i == 4) + set $value = $arg4 + __is_string ($arg4) + else + if ($i == 5) + set $value = $arg5 + __is_string ($arg5) + else + if ($i == 6) + set $value = $arg6 + __is_string ($arg6) + else + if ($i == 7) + set $value = $arg7 + __is_string ($arg7) + else + if ($i == 8) + set $value = $arg8 + __is_string ($arg8) + else + set $value = $arg9 + __is_string ($arg9) + # gdb limits to 10 args and errors out for us + end + end + end + end + end + end + end + end + + if ($i == 1) + printf "Memory set starting at %.8X\n", $addr + set $dot = $addr + end + + if ($string) + __strlen $string + if ($debug) + printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen + else + __memcpy $addr $string $strlen + end + set $addr = (unsigned char *)$addr + $strlen + else + if ($debug) + printf "%.8X = %.2X\n", $addr, (unsigned long)$value & 0xFF + else + set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF + end + set $addr = (unsigned char *)$addr + 1 + end + + set $i = $i + 1 + end + + if ($e == 0) + set $start = $arg0 + set $n = (unsigned long)$addr - (unsigned long)$start + if ($debug) + printf "__hexdump %X %d\n", $start, (($n+15)/16)*16 + else + __hexdump $start (($n+15)/16)*16 + end + end + + set $__lastcmd__ = 17 +end +document SB +SB addr values -- Assign up to 9 values to bytes starting at addr. +String values are fully assigned at the next assignable byte. +Ê +Restrictions: The values value may not have any embedded blanks. For example +Ê a value like (unsigned char *)0x1234 is invalid. +Ê +Ê There is a limit of 9 values that can be set. +Ê +Macsbug features not supported: Double quoted "string" instead of single quoted +Ê 'string'. +end + +# Note, SB, SL, SW, and SM are parse their args exactly the same way. We could +# generalize SM and let SB, SL, SW call it. But that would mean taking away one +# or two arguments from the possible total of 10. So to keep them all consistent +# with the 10 limit we repeat the code in each of these routines. + +################################################################################### +# +# SC +# +define SC + bt + set $__lastcmd__ = 18 +end +document SC +SC -- Display back trace. +end + +################################################################################### +# +# SC6 +# +define SC6 + bt + set $__lastcmd__ = 19 +end +document SC6 +SC6 -- Same as SC. +end + +################################################################################### +# +# SC7 +# +define SC7 + bt + set $__lastcmd__ = 20 +end +document SC7 +SC7 -- Same as SC. +end + +################################################################################### +# +# SI [n] [m] +# +define SI + if ($argc == 0) + if ($__lastcmd__ != 16 && $__lastcmd__ != 23) + set $__STEP__ = 1 + set $__WINDOW__ = 4 + end + else + if ($argc == 1) + set $__STEP__ = $arg0 + set $__WINDOW__ = 4 + else + set $__STEP__ = $arg0 + set $__WINDOW__ = $arg1 + end + end + + stepi $__STEP__ + set $dot = $pc + __disasmN $pc $__WINDOW__ $pc + + set $__lastcmd__ = 16 +end +document SI +SI [n] [m] -- Step n (or 1) instruction(s) and disassemble m (or 4) lines from new pc. +See also gdb's next and step instructions, which step by source lines, +not instructions. +Ê +The second argument is a extension to the MacsBug syntax to allow a disassembly +of m lines to show the next instructions to be executed. This approximates the +disassembly window that MacsBug always shows. +Ê +Macsbug features not supported: S expr +Ê +Ê The MacsBug S is SI here. This was done to preserve +Ê gdb's definition of S[tep] to single statement step. +Ê There is (was) a gdb SI to which does exactly what +Ê this MacsBug SI does except that now the instruction +Ê is also displayed at each instruction step. +end + +################################################################################### +# +# SL addr value1 [... value9] +# +define SL + if ($argc < 2) + printf "usage: SL addr value1 [... value9]\n" + set $e = 1 + else + set $addr = $arg0 + set $e = 0 + end + + set $debug = 0 + + set $i = 1 + + while ($i < $argc && $e == 0) + if ($i == 1) + set $value = $arg1 + __is_string ($arg1) + else + if ($i == 2) + set $value = $arg2 + __is_string ($arg2) + else + if ($i == 3) + set $value = $arg3 + __is_string ($arg3) + else + if ($i == 4) + set $value = $arg4 + __is_string ($arg4) + else + if ($i == 5) + set $value = $arg5 + __is_string ($arg5) + else + if ($i == 6) + set $value = $arg6 + __is_string ($arg6) + else + if ($i == 7) + set $value = $arg7 + __is_string ($arg7) + else + if ($i == 8) + set $value = $arg8 + __is_string ($arg8) + else + set $value = $arg9 + __is_string ($arg9) + # gdb limits to 10 args and errors out for us + end + end + end + end + end + end + end + end + + if ($i == 1) + printf "Memory set starting at %.8X\n", $addr + set $dot = $addr + end + + # Although we probably can use unaligned access, why take chances? So + # the following sets memory a byte at a time. + + if ($string) + __strlen $string + if ($debug) + printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen + else + __memcpy $addr $string $strlen + end + set $addr = (unsigned char *)$addr + $strlen + else + if ($debug) + printf "%.8X = %.8X\n", $addr, (unsigned long)$value + set $addr = (unsigned char *)$addr + 4 + else + set *((unsigned char *)$addr) = ((unsigned long)$value >> 24) & 0xFF + set $addr = (unsigned char *)$addr + 1 + + set *((unsigned char *)$addr) = ((unsigned long)$value >> 16) & 0xFF + set $addr = (unsigned char *)$addr + 1 + + set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF + set $addr = (unsigned char *)$addr + 1 + + set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF + set $addr = (unsigned char *)$addr + 1 + end + end + + set $i = $i + 1 + end + + if ($e == 0) + set $start = $arg0 + set $n = (unsigned long)$addr - (unsigned long)$start + if ($debug) + printf "__hexdump %X %d\n", $start, (($n+15)/16)*16 + else + __hexdump $start (($n+15)/16)*16 + end + end + + set $__lastcmd__ = 21 +end +document SL +SL addr values -- Assign up to 9 values to (4-byte) longs starting at addr. +String values are fully assigned at the next assignable byte. +Ê +Restrictions: The values value may not have any embedded blanks. For example +Ê a value like (unsigned char *)0x1234 is invalid. +Ê +Ê There is a limit of 9 values that can be set. +Ê +Macsbug features not supported: Double quoted "string" instead of single quoted +Ê 'string'. +end + +# Note, SB, SL, SW, and SM are parse their args exactly the same way. We could +# generalize SM and let SB, SL, SW call it. But that would mean taking away one +# or two arguments from the possible total of 10. So to keep them all consistent +# with the 10 limit we repeat the code in each of these routines. + +################################################################################### +# +# SM addr value1 [... value9] +# +define SM + if ($argc < 2) + printf "usage: SM addr value1 [... value9]\n" + set $e = 1 + else + set $addr = $arg0 + set $e = 0 + end + + set $debug = 0 + + set $i = 1 + + while ($i < $argc && $e == 0) + if ($i == 1) + set $value = $arg1 + __is_string ($arg1) + else + if ($i == 2) + set $value = $arg2 + __is_string ($arg2) + else + if ($i == 3) + set $value = $arg3 + __is_string ($arg3) + else + if ($i == 4) + set $value = $arg4 + __is_string ($arg4) + else + if ($i == 5) + set $value = $arg5 + __is_string ($arg5) + else + if ($i == 6) + set $value = $arg6 + __is_string ($arg6) + else + if ($i == 7) + set $value = $arg7 + __is_string ($arg7) + else + if ($i == 8) + set $value = $arg8 + __is_string ($arg8) + else + set $value = $arg9 + __is_string ($arg9) + # gdb limits to 10 args and errors out for us + end + end + end + end + end + end + end + end + + if ($i == 1) + printf "Memory set starting at %.8X\n", $addr + set $dot = $addr + end + + # Although we probably can use unaligned access, why take chances? So + # the following sets memory a byte at a time. + + if ($string) + __strlen $string + if ($debug) + printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen + else + __memcpy $addr $string $strlen + end + set $addr = (unsigned char *)$addr + $strlen + else + if ((long)$value >= -128 && (long)$value <= 255) + set $size = 1 + else + if ((long)$value >= -32768 && (long)$value <= 65535) + set $size = 2 + else + set $size = 4 + end + end + + if ($debug) + if ($size == 4) + printf "%.8X = %.8X\n", $addr, (unsigned long)$value + else + if ($size == 2) + printf "%.8X = %.4X\n", $addr, (unsigned long)$value & 0xFFFF + else + printf "%.8X = %.2X\n", $addr, (unsigned long)$value & 0xFF + end + end + set $addr = (unsigned char *)$addr + $size + else + if ($size == 4) + set *((unsigned char *)$addr) = ((unsigned long)$value >> 24) & 0xFF + set $addr = (unsigned char *)$addr + 1 + + set *((unsigned char *)$addr) = ((unsigned long)$value >> 16) & 0xFF + set $addr = (unsigned char *)$addr + 1 + end + + if ($size == 2 || $size == 4) + set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF + set $addr = (unsigned char *)$addr + 1 + end + + set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF + set $addr = (unsigned char *)$addr + 1 + end + end + + set $i = $i + 1 + end + + if ($e == 0) + set $start = $arg0 + set $n = (unsigned long)$addr - (unsigned long)$start + if ($debug) + printf "__hexdump %X %d\n", $start, (($n+15)/16)*16 + else + __hexdump $start (($n+15)/16)*16 + end + end + + set $__lastcmd__ = 22 +end +document SM +SM addr value -- Assign up to 9 values to memory starting at addr. +Each value determines the assignment size (byte, 2-byte word, or 4-byte +long). Specific sizes can be set using SB, SW, or SL. String values +are fully assigned at the next assignable byte. +Ê +Restrictions: The values value may not have any embedded blanks. For example +Ê a value like (unsigned char *)0x1234 is invalid. +Ê +Ê There is a limit of 9 values that can be set. +Ê +Macsbug features not supported: Double quoted "string" instead of single quoted +Ê 'string'. +end + +# Note, SB, SL, SW, and SM are parse their args exactly the same way. We could +# generalize SM and let SB, SL, SW call it. But that would mean taking away one +# or two arguments from the possible total of 10. So to keep them all consistent +# with the 10 limit we repeat the code in each of these routines. + +################################################################################### +# +# SO [n] [m] +# +define SO + if ($argc == 0) + if ($__lastcmd__ != 23 && $__lastcmd__ != 16) + set $__STEP__ = 1 + set $__WINDOW__ = 4 + end + else + if ($argc == 1) + set $__STEP__ = $arg0 + set $__WINDOW__ = 4 + else + set $__STEP__ = $arg0 + set $__WINDOW__ = $arg1 + end + end + + nexti $__STEP__ + set $dot = $pc + __disasmN $pc $__WINDOW__ $pc + + set $__lastcmd__ = 23 +end +document SO +SO [n] [m] -- Step over n instructions and disassemble m (or 4) lines from new pc. +See also gdb's next and step instructions, which step by source lines, +not instructions. +Ê +The second argument is a extension to the MacsBug syntax to allow a disassembly +of m lines to show the next instructions to be executed. This approximates the +disassembly window that MacsBug always shows. +end + +################################################################################### +# +# SW addr value1 [... value9] +# +define sw + if ($argc < 2) + printf "usage: SW addr value1 [... value9]\n" + set $e = 1 + else + set $addr = $arg0 + set $e = 0 + end + + set $debug = 0 + + set $i = 1 + + while ($i < $argc && $e == 0) + if ($i == 1) + set $value = $arg1 + __is_string ($arg1) + else + if ($i == 2) + set $value = $arg2 + __is_string ($arg2) + else + if ($i == 3) + set $value = $arg3 + __is_string ($arg3) + else + if ($i == 4) + set $value = $arg4 + __is_string ($arg4) + else + if ($i == 5) + set $value = $arg5 + __is_string ($arg5) + else + if ($i == 6) + set $value = $arg6 + __is_string ($arg6) + else + if ($i == 7) + set $value = $arg7 + __is_string ($arg7) + else + if ($i == 8) + set $value = $arg8 + __is_string ($arg8) + else + set $value = $arg9 + __is_string ($arg9) + # gdb limits to 10 args and errors out for us + end + end + end + end + end + end + end + end + + if ($i == 1) + printf "Memory set starting at %.8X\n", $addr + set $dot = $addr + end + + # Although we probably can use unaligned access, why take chances? So + # the following sets memory a byte at a time. + + if ($string) + __strlen $string + if ($debug) + printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen + else + __memcpy $addr $string $strlen + end + set $addr = (unsigned char *)$addr + $strlen + else + if ($debug) + printf "%.8X = %.4X\n", $addr, (unsigned long)$value & 0xFFFF + set $addr = (unsigned char *)$addr + 2 + else + set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF + set $addr = (unsigned char *)$addr + 1 + + set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF + set $addr = (unsigned char *)$addr + 1 + end + end + + set $i = $i + 1 + end + + if ($e == 0) + set $start = $arg0 + set $n = (unsigned long)$addr - (unsigned long)$start + if ($debug) + printf "__hexdump %X %d\n", $start, (($n+15)/16)*16 + else + __hexdump $start (($n+15)/16)*16 + end + end + + set $__lastcmd__ = 24 +end +document SW +SW addr values -- Assign up to 9 values to (2-byte) words starting at addr. +String values are fully assigned at the next assignable byte. +Ê +Restrictions: The values value may not have any embedded blanks. For example +Ê a value like (unsigned char *)0x1234 is invalid. +Ê +Ê There is a limit of 9 values that can be set. +Ê +Macsbug features not supported: Double quoted "string" instead of single quoted +Ê 'string'. +end + +# Note, SB, SL, SW, and SM are parse their args exactly the same way. We could +# generalize SM and let SB, SL, SW call it. But that would mean taking away one +# or two arguments from the possible total of 10. So to keep them all consistent +# with the 10 limit we repeat the code in each of these routines. + +################################################################################### +# +# T [n] [m] +# +define T + if ($argc == 0) + SO + else + if ($argc == 1) + SO $arg0 + else + SO $arg0 $arg1 + end + end + + #set $__lastcmd__ = 25 +end +document T +T [n] [m] -- Trace n (or 1) instruction(s) and disassemble m (or 4) from pc (same as SO). +end + +################################################################################### +# +# TD +# +#PowerPC Registers +# CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 +# PC = 05AB2950 CR 0100 0010 0000 0000 0000 1000 0100 1000 +# LR = 05AB29A4 <>=O XEVO +# CTR = FFD6A848 +# MSR = 00000000 SOC Compare Count +# Int = 0 XER 000 00 00 MQ = 00000000 +# +# R0 = 00000000 R8 = 00000000 R16 = 05B0FD25 R24 = 05B0FC90 +# SP = 05BCDF00 R9 = 05B150A0 R17 = 05B0FCAC R25 = 0032822A +# R1 = 05B0AB4B R10 = 00000000 R18 = 05B0FC8C R26 = 00000003 +# R3 = 0053866F R11 = 00538E7A R19 = 05B10668 R27 = 00000000 +# R4 = 00000000 R12 = 0002CEA4 R20 = 05B0FCA9 R28 = 05BCE206 +# R5 = 05BCDEF8 R13 = 00000000 R21 = 05B0FCAF R29 = 05B32AD0 +# R6 = 05ABAEC4 R14 = 00000000 R22 = 0000001E R30 = 00538670 +# R7 = 05B32AD0 R15 = 00000000 R23 = 00000000 R31 = 05B0FE6C +# +define TD + printf "PowerPC Registers\n" + printf " CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7\n" + printf " PC = %.8X CR ", $pc + __binary ($cr>>28) 4 + printf " " + __binary ($cr>>24&15) 4 + printf " " + __binary ($cr>>20&15) 4 + printf " " + __binary ($cr>>16&15) 4 + printf " " + __binary ($cr>>12&15) 4 + printf " " + __binary ($cr>>8&15) 4 + printf " " + __binary ($cr>>4&15) 4 + printf " " + __binary ($cr&15) 4 + printf "\n" + + printf " LR = %.8X <>=O XEVO\n", $lr + printf " CTR = %.8X\n", $ctr + printf " MSR = %.8X SOC Compare Count\n", $ps + printf " XER " + __binary ($xer>>29&7) 3 + printf " %.2X %.2X MQ = %.8X\n", ($xer>>8&0xFF), ($xer&0x7F), $mq + + printf "\n" + + printf " R0 = %.8X R8 = %.8X R16 = %.8X R24 = %.8X\n", $r0, $r8, $r16, $r24 + printf " SP = %.8X R9 = %.8X R17 = %.8X R25 = %.8X\n", $r1, $r9, $r17, $r25 + printf " R2 = %.8X R10 = %.8X R18 = %.8X R26 = %.8X\n", $r2, $r10, $r18, $r26 + printf " R3 = %.8X R11 = %.8X R19 = %.8X R27 = %.8X\n", $r3, $r11, $r19, $r27 + printf " R4 = %.8X R12 = %.8X R20 = %.8X R28 = %.8X\n", $r4, $r12, $r20, $r28 + printf " R5 = %.8X R13 = %.8X R21 = %.8X R29 = %.8X\n", $r5, $r13, $r21, $r29 + printf " R6 = %.8X R14 = %.8X R22 = %.8X R30 = %.8X\n", $r6, $r14, $r22, $r30 + printf " R7 = %.8X R15 = %.8X R23 = %.8X R31 = %.8X\n", $r7, $r15, $r23, $r31 + + set $__lastcmd__ = 26 +end +document TD +TD -- Display integer and machine registers. +end + +################################################################################### +# +# TF +# +#PowerPC FPU Registers +# S S +# F N I I Z I O Q C +# FPSCR F E V O U Z X A S D D M V F F F R V V O U Z X N +# X X X X X X X N I I Z Z C R I C < > = ? T T I E E E E E I RN +# 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 00 +# +# FPR0 = FFF 8000082004000 -NAN(000) +# FPR1 = 408 4700000000000 6.540000000000000e+2 +# - - - +# FPR30 = 000 0000000000000 0.000000000000000e+0 +# FPR31 = 000 0000000000000 0.000000000000000e+0 +# +# There's no way to display the floating regs in hex like this. So we'll +# just have to settle with what info registers $fN produces. It's a +# pretty good approximation so it isn't too bad. +# +define TF + printf "PowerPC Vector Registers\n" + printf " S S\n" + printf " F N I I Z I O Q C\n" + printf " FPSCR F E V O U Z X A S D D M V F F F R V V O U Z X N\n" + printf " X X X X X X X N I I Z Z C R I C < > = ? T T I E E E E E I RN\n" + + printf " " + set $i = 0 + set $r = $fpscr + while ($i++ < 32) + printf "%1d", ($r >> (32-$i)) & 1 + if ($i < 31) + printf " " + end + end + printf "\n\n" + + info registers $f0 + info registers $f1 + info registers $f2 + info registers $f3 + info registers $f4 + info registers $f5 + info registers $f6 + info registers $f7 + info registers $f8 + info registers $f9 + info registers $f10 + info registers $f11 + info registers $f12 + info registers $f13 + info registers $f14 + info registers $f15 + info registers $f16 + info registers $f17 + info registers $f18 + info registers $f19 + info registers $f20 + info registers $f21 + info registers $f22 + info registers $f23 + info registers $f24 + info registers $f25 + info registers $f26 + info registers $f27 + info registers $f28 + info registers $f29 + info registers $f30 + info registers $f31 + + set $__lastcmd__ = 27 +end +document TF +TF -- Display the floating point registers. +end + +################################################################################### +# +# TV +# +#PowerPC Vector Registers +# S +# VRsave = 00000000 N A +# J T +# VSCR = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +# +# V0 = 00000000 00000000 00000000 00000000 0.0000e+0 0.0000e+0 0.0000e+0 0.0000e+0 +# V1 = 53706F74 20636865 636B206F 66207472 1.0327e+12 1.9262e-19 4.3373e+21 1.8943e+23 +# - - - +# V30 = 7FFFDEAD 7FFFDEAD 7FFFDEAD 7FFFDEAD NAN(222) NAN(222) NAN(222) NAN(222) +# V31 = 7FFFDEAD 7FFFDEAD 7FFFDEAD 7FFFDEAD NAN(222) NAN(222) NAN(222) NAN(222) +# +define TV + printf "PowerPC Vector Registers\n" + printf "%c[31m", 0x1B + printf " Not available - can't get or manipulate the vector registers yet! Sorry. Sigh :-(\n" + printf "\n" + printf "%c[0m\n", 0x1B + info registers + + set $__lastcmd__ = 28 +end +document TV +TV -- Display the vector registers (not yet supported). +end + +################################################################################### +################################################################################### + +# ########################################################## +# # Internal helper functions for the above user functions # +# ########################################################## + +# Because gdb doesn't have the concept of local function variables the convention +# here is to define all "locals" with a double underbar prefix to try to keep them +# distinct from their function's callers. Indeed, we also follow the convention +# for all these private function names as well. It makes this stuff almost +# unreadable but that's gdb for you. Yuk! + +# +# __binary value n +# +# Internal function to display $arg0 as $arg1 binary digits. Only the right- +# most $arg2 binary bits are displayed. No newline is output here. +# +define __binary + set $__value = $arg0 + set $__n = $arg1 + + set $__i = 0 + while ($__i++ < $__n) + printf "%1d", ($__value >> ($__n-$__i)) & 1 + end +end +document __binary +For internal use only -- do not use. +end + +################################################################################### +# +# __branch_taken - determine if a conditional branch at $pc will be taken +# +# Returns $branch_taken = 1 if conditional branch will be taken +# = -1 if conditional branch will not be taken +# = 0 if not conditional branch at $pc +# +# The algorithm here is based on what is described in the IBM PPC Architecture book. +# To paraphrase what's there in determining whether the branch is taken or not it +# basically says: +# +# bc[l][a] (primary = 16) +# bclr[l] (primary = 19, extend = 16) +# cond_ok = BO[0] || (CR[BI] == BO[1]) +# if !BO[2] then CTR = CTR-1 +# ctr_ok = BO[2] || (CTR != 0) ^ BO[3] +# if ctr_ok && cond_ok then "will branch" +# else "will not branch" +# +# bcctr[l] (primary = 19, extend = 528) +# cond_ok = BO[0] || (CR[BI] == BO[1]) +# if cond_ok then "will branch" +# else "will not branch" +# +# where the notation X[i] is bit i in field X. +# +# The implementation of this below is "optimized" to read as: +# cond_ok = BO[0] || (CR[BI] == BO[1]) +# if (cond_ok && !"bcctr[l]") then cond_ok = BO[2] || (CTR-1 != 0) ^ BO[3] +# if cond_ok then "will branch" +# else "will not branch" +# +# Note, for all these brances, of BO == 0x14 we have a "branch always" which are not +# classed as conditional branches for our purposes. +# +define __branch_taken + # First decode the instruction to see if it's a conditional branch... + set $__pri = *(unsigned long *)$pc >> 26 + if ($__pri == 19) + set $__ext = (*(unsigned long *)$pc >> 1) & 0x3FF + if ($__ext != 16 && $__ext != 528) + set $__pri = 0 + end + else + if ($__pri != 16) + set $__pri = 0 + else + set $__ext = 0 + end + end + + if (((*(unsigned long *)$pc >> 21) & 0x14) == 0x14) + set $__pri = 0 + end + + # If we have a conditional branch then check it out... + + if ($__pri) + # cond_ok = BO[0] || (CR[BI] == BO[1]) + set $__cond_ok = ((*(unsigned long *)$pc & 0x02000000) != 0) + if (!$__cond_ok) + set $__cond_ok = ((((unsigned long)$cr >> (31-((*(unsigned long *)$pc>>16) & 0x1f))) & 1) == \ + (((*(unsigned long *)$pc & 0x01000000) >> 24) & 1)) + end + + if ($__cond_ok && ($__ext != 528)) + # cond_ok = BO[2] || (CTR-1 != 0) ^ BO[3] + set $__cond_ok = ((*(unsigned long *)$pc & 0x00800000) != 0) + if (!$__cond_ok) + set $__cond_ok = ($ctr-1 != 0) ^ ((*(unsigned long *)$pc & 0x00400000) >> 22) + end + end + + if ($__cond_ok) + set $branch_taken = 1 + else + set $branch_taken = -1 + end + else + set $branch_taken = 0 + end +end +document __branch_taken +For internal use only -- do not use. +end + +################################################################################### +# +# __flag_asm_line loc flag color +# +# This is called when a disassembly line for the specified location (loc) is +# output. The cursor is positioned back to the start of the disassembly +# (preceding) line and the location redisplayed to move the cursor to the +# space that follows it (so we don't have to know how long it was). That space +# is then flagged with the specified flag character in the specified color. +# +# The color value is the standard xterm color value. +# +# Examples: color = 0 ==> normal +# 1 ==> bold +# 31 ==> red +# 34 ==> blue +# +define __flag_asm_line + printf "%c[1A", 0x1B + printf "0x%x%c[%dm%c%c[0m\n", $arg0, 0x1B, $arg2, $arg1, 0x1B +end +document __flag_asm_line +For internal use only -- do not use. +end + +################################################################################### +# +# __flag_pc - shorthand for __flag_asm_line $pc '*' 31 +# +define __flag_pc + __flag_asm_line $pc '*' 31 +end +document __flag_pc +For internal use only -- do not use. +end + +################################################################################### +# +# __flag_loc loc - shorthand for __flag_asm_line loc '*' 31 +# +define __flag_loc + set $__loc = $arg0 + __flag_asm_line $__loc '.' 34 +end +document __flag_loc +For internal use only -- do not use. +end + +################################################################################### +# +# __disasm1 loc flagloc +# +# Disassemble one instruction at loc. If loc is equal to the flag_loc then flag +# the line with the pc flag if flag_loc == $pc or the non-pc loc flag if loc == +# flag_loc. +# +define __disasm1 + set $__loc = $arg0 + set $__flagloc = $arg1 + + x/1i $__loc + + if ($__loc == $pc) + __flag_pc + __branch_taken + else + if ($__loc == $__flagloc) + __flag_loc $__flagloc + end + end +end +document __disasm1 +For internal use only -- do not use. +end + +################################################################################### +# +# __disasmN addr n [flagloc] +# +# Disassemble n lines from addr and flag flagloc if it is specified. +# +define __disasmN + set $__addr = $arg0 + set $__n = $arg1 + + if ($argc > 2) + set $__flagloc = $arg2 + else + set $__flagloc = -1 + end + + set $__i = 0 + set $branch_taken = 0 + + while ($__i < $__n) + __disasm1 ((char*)$__addr+4*$__i++) $__flagloc + end + + if ($branch_taken == 1) + printf "Will branch\n" + else + if ($branch_taken == -1) + printf "Will not branch\n" + end + end + + if ($__running__) + __display_registers_v + end +end +document __disasmN +For internal use only -- do not use. +end + +################################################################################### +# +# __hexdump [addr [n]] - dump n (default 16) bytes starting at addr (default pc) +# +define __hexdump + if ($argc == 0) + set $__addr = (unsigned char *)$pc + set $__addr1 = (unsigned char *)$pc + 16 + else + if ($argc == 1) + set $__addr = (unsigned char *)($arg0) + set $__addr1 = (unsigned char *)$__addr + 16 + else + set $__addr = (unsigned char *)($arg0) + set $__addr1 = (unsigned char *)$__addr + ($arg1) + end + end + + set $__prevaddr = (unsigned char *)$__addr + set $__rep_count = 0 + + while ($__addr < $__addr1) + set $__addr2 = $__addr + + # Only allow full ditto lines and never the last line + + if ((unsigned char *)$__addr + 16 < $__addr1) + __repeated_dump_line $__prevaddr $__addr 16 + else + set $repeated = 0 + end + set $__prevaddr = (unsigned char *)$__addr + + if ($repeated) + if ($__rep_count++ == 0) + printf " %.8X: '''' '''' '''' '''' '''' '''' '''' '''' ''''''''''''''''\n", $__addr + end + set $__addr = (char *)$__addr + 16 + else + printf " %.8X: ", $__addr + set $__rep_count = 0 + set $__i = 0 + while ($__i++ < 8) + set $__j = 0 + while ($__j++ < 2) + if ($__addr < $__addr1) + set $__x = *((unsigned char *)$__addr)++ + printf "%1X%1X", ($__x >> 4) & 0x0F, $__x & 0x0F + else + printf " " + end + end + printf " " + if ($__i == 4) + printf " " + end + end + + printf " " + + set $__i = 0 + while ($__i++ < 16) + if ($__addr2 < $__addr1) + set $__x = *((unsigned char *)$__addr2)++ + if ($__x >= 0x20 && $__x <= 0x7F) + printf "%c", $__x + else + printf "." + end + else + printf " " + end + end + printf "\n" + end + + end +end +document __hexdump +For internal use only -- do not use. +end + +################################################################################### +# +# __repeated_dump_line prev addr n - Check for repeated dump lines +# +# If the n bytes starting at the prev address is the same as the n bytes starting at addr then +# set $repeated to 1. Otherwise set it to 0. +# +# This is used by __hexdump and DMA to control whether repeated lines are to be +# displayed. This is further controlled by the MSET DITTO setting. +# +define __repeated_dump_line + set $repeated = 0 + + # Test $__ditto__ as a single operand just in case it is still undefined. Gdb + # sets undefined convenience variables to void which tests as false. + + if ($__ditto__ && $arg0 < $arg1) + set $__p1 = (unsigned char *)$arg0 + set $__p2 = (unsigned char *)$arg1 + set $__k = $arg2 + + set $repeated = 1 + + while ($repeated && $__k--) + if (*((unsigned char *)$__p1)++ != *((unsigned char *)$__p2)++) + set $repeated = 0 + end + end + else + set $repeated = 0 + end +end +document __repeated_dump_line +For internal use only -- do not use. +end + +################################################################################### +# +# __print_char char [isString] - print a (possibly escaped) character +# +# If isString (actually any 2nd argument) is specified then this character is +# in the context of a "string" as opposed to a 'string' (i.e., the surrounding +# quotes on the string) so that a single quote do not need to be escaped. On +# the other hand if this is the context of a double-quoted string then double +# quotes need to be escaped. +# +define __print_char + set $__c = $arg0 + if ($__c <= 0xFF) + if ($__c == '\n') + printf "\\n" + else + if ($__c == '\r') + printf "\\r" + else + if ($__c == '\t') + printf "\\t" + else + if ($__c == '\a') + printf "\\a" + else + if ($__c == '\f') + printf "\\f" + else + if ($__c == '\b') + printf "\\b" + else + if ($__c == '\v') + printf "\\v" + else + if ($__c == '\'' && $argc == 1) + printf "\\'" + else + if ($__c == '"' && $argc > 1) + printf "\\\"" + else + if (($__c < 0x20) || ($__c >= 0x7f)) + # show escaped octals in bold + printf "%c[1m\\%03o%c[0m", 0x1B, $__c, 0x1B + else + printf "%c", $__c + end + end + end + end + end + end + end + end + end + end + end +end +document __print_char +For internal use only -- do not use. +end + +################################################################################### +# +# __print_1 value +# +define __print_1 + set $__value = $arg0 + printf "'" + __print_char ($__value&0xFF) + printf "'" +end +document __print_1 +For internal use only -- do not use. +end + +################################################################################### +# +# __print_2 value +# +define __print_2 + set $__value = $arg0 + printf "'" + __print_char ($__value>>8)&0xFF + __print_char ($__value&0xFF) + printf "'" +end +document __print_2 +For internal use only -- do not use. +end + +################################################################################### +# +# __print_4 value +# +define __print_4 + set $__value = $arg0 + printf "'" + __print_char (($__value>>24)&0xFF) + __print_char (($__value>>16)&0xFF) + __print_char (($__value>>8)&0xFF) + __print_char ($__value&0xFF) + printf "'" +end +document __print_4 +For internal use only -- do not use. +end + +################################################################################### +# +# __strcmp s1 s2 - set $strcmp != 0 if strings match else 0 +# +# We could test for the existence of the function strcmp() and use it instead of +# doing all this crap. While the odds are that it would always be found (I think +# it's part of the System Framework which most everything links in, and I did +# always see it in my testing) having our own gdb strcmp is guaranteed and 100% +# safe. While the probability is very low, it is not zero that the user defined +# his own strcmp() that doesn't do what the C/C++ strcmp() does. Ok, I'm being +# overly paranoid. +# +define __strcmp + set $__s1 = (unsigned char *)($arg0) + set $__s2 = (unsigned char *)($arg1) + + set $strcmp = 1 + + set $__c1 = *((unsigned char *)$__s1)++ + while ($strcmp && $__c1) + set $__c2 = *((unsigned char *)$__s2)++ + if ($__c1 == $__c2) + set $__c1 = *((unsigned char *)$__s1)++ + else + set $strcmp = 0 + end + end + + set $strcmp &= (*(unsigned char *)$__s2 == 0) +end +document __strcmp +For internal use only -- do not use. +end + +################################################################################### +# +# __strncmp s1 s2 n - set $strncmp != 0 if n characters of strings match else 0 +# +# Similar to __strcmp except that this one's the equivalent to strncmp(). +# +define __strncmp + set $__s1 = (unsigned char *)($arg0) + set $__s2 = (unsigned char *)($arg1) + set $__n = $arg2 + 1 + + set $strncmp = 1 + + while ($strncmp && --$__n) + set $__c1 = *((unsigned char *)$__s1)++ + set $__c2 = *((unsigned char *)$__s2)++ + + if ($__c1 != $__c2) + set $strncmp = 0 + else + if ($__c1 == 0) + set $__n = 1 + end + end + end +end +document __strncmp +For internal use only -- do not use. +end + +################################################################################### +# +# __strlen s - return the length of the string (argument) in $strlen +# +define __strlen + set $strlen = -1 + set $__s = (char *)$arg0 + while ($__s[++$strlen]) + end +end +document __strlen +For internal use only -- do not use. +end + +################################################################################### +# +# __memcpy s1 s2 n +# +define __memcpy + set $__s1 = (unsigned char *)($arg0) + set $__s2 = (unsigned char *)($arg1) + set $__n = $arg2 + 1 + + while (--$__n) + set *((unsigned char *)$__s1)++ = *((unsigned char *)$__s2)++ + end +end +document __memcpy +For internal use only -- do not use. +end + +################################################################################### +# +# __lower_case option_arg - lower case an option argument +# +# Returns $lower_case containing the lower cased copy of the option_arg. The +# option_arg must be an ACTUAL $argN symbol from the caller, not a value set from it. +# +define __lower_case + set $lower_case = (char *)"$arg0" + set $__i = 0 + while ($lower_case[$__i]) + if ($lower_case[$__i] >= 'A' && $lower_case[$__i] <= 'Z') + set $lower_case[$__i] = 'a' + ($lower_case[$__i] - 'A') + end + set ++$__i + end +end +document __lower_case +For internal use only -- do not use. +end + +################################################################################### +# +# __is_string arg - determine if arg is a value or "string" +# +# Returns $string set to the a pointer to the string if arg is a string and $string +# is set to 0 if the arg is not a string. +# +# This function uses the fact (determined after much expirimentation) that assigning +# a value to a variable simply yields that value. But assigning a string yields a +# new instance of the pointer to the string and thus the resultant pointer will not +# be the same as the original argument pointer. If someone can figure out a simpler +# way of determining a double quoted "string" argument from a value in this dumb +# command language I'm open to it! +# +# Note, the arg must be an ACTUAL $argN symbol, not a value set from it. A set +# assignment yields a pointer value. We need the actual arg as written because +# actual arg substitution is a string substitution which we are assuming here when +# we do the (char *)$arg0 assignment. We are actually doing (char *)"string" here +# when the arg really was a string which allows us to do what we do here. +# +define __is_string + if ((long)$arg0 < 0) + # Negative values are assumed to be just that, values, and not strings. + set $string = 0 + else + # If value is not negative, get its value cast as a pointer... + set $__p = (char *)$arg0 + + # If original value is same as pointer value then it's a value. Otherwise + # the set $__p created a new instance of the string (lucky for use) and + # it won't be the same when it's a string. What a kludge! What a language! + if ($__p == $arg0) + set $string = 0 + else + set $string = $__p + end + end +end +document __is_string +For internal use only -- do not use. +end + +################################################################################### +# +# __save_all_regs_v - save current values of all registers +# +# This is called by __display_registers_v to remember the previous display. +# It is also called by __save_all_regs_h which saved additional registers. +# +define __save_all_regs_v + set $__lr = $lr + set $__ctr = $ctr + set $__msr = $ps + set $__xer = $xer + set $__mq = $mq + + set $__cr0 = ($cr>>28&15) + set $__cr1 = ($cr>>24&15) + set $__cr2 = ($cr>>20&15) + set $__cr3 = ($cr>>16&15) + set $__cr4 = ($cr>>12&15) + set $__cr5 = ($cr>>8&15) + set $__cr6 = ($cr>>4&15) + set $__cr7 = ($cr&15) + + set $__r0 = $r0 + set $__sp = $r1 + set $__r2 = $r2 + set $__r3 = $r3 + set $__r4 = $r4 + set $__r5 = $r5 + set $__r6 = $r6 + set $__r7 = $r7 + set $__r8 = $r8 + set $__r9 = $r9 + set $__r10 = $r10 + set $__r11 = $r11 + set $__r12 = $r12 + set $__r13 = $r13 + set $__r14 = $r14 + set $__r15 = $r15 + set $__r16 = $r16 + set $__r17 = $r17 + set $__r18 = $r18 + set $__r19 = $r19 + set $__r20 = $r20 + set $__r21 = $r21 + set $__r22 = $r22 + set $__r23 = $r23 + set $__r24 = $r24 + set $__r25 = $r25 + set $__r26 = $r26 + set $__r27 = $r27 + set $__r28 = $r28 + set $__r29 = $r29 + set $__r30 = $r30 + set $__r31 = $r31 +end +document __save_all_regs_v +For internal use only -- do not use. +end + +################################################################################### +# +# __save_all_regs_h - save current values of all registers +# +# This is called by __display_registers_h to remember the previous display. +# +define __save_all_regs_h + __save_all_regs_v + + set $__so = $xer>>31 & 1 + set $__ov = $xer>>30 & 1 + set $__ca = $xer>>29 & 1 + set $__xcmp = $xer>>8 & 0xFF + set $__xcnt = $xer & 0x7F + + set $__cr00 = $__cr0>>3 & 1 + set $__cr01 = $__cr0>>2 & 1 + set $__cr02 = $__cr0>>1 & 1 + set $__cr03 = $__cr0 & 1 + + set $__cr10 = $__cr1>>3 & 1 + set $__cr11 = $__cr1>>2 & 1 + set $__cr12 = $__cr1>>1 & 1 + set $__cr13 = $__cr1 & 1 + + set $__cr20 = $__cr2>>3 & 1 + set $__cr21 = $__cr2>>2 & 1 + set $__cr22 = $__cr2>>1 & 1 + set $__cr23 = $__cr2 & 1 + + set $__cr30 = $__cr3>>3 & 1 + set $__cr31 = $__cr3>>2 & 1 + set $__cr32 = $__cr3>>1 & 1 + set $__cr33 = $__cr3 & 1 + + set $__cr40 = $__cr4>>3 & 1 + set $__cr41 = $__cr4>>2 & 1 + set $__cr42 = $__cr4>>1 & 1 + set $__cr43 = $__cr4 & 1 + + set $__cr50 = $__cr5>>3 & 1 + set $__cr51 = $__cr5>>2 & 1 + set $__cr52 = $__cr5>>1 & 1 + set $__cr53 = $__cr5 & 1 + + set $__cr60 = $__cr6>>3 & 1 + set $__cr61 = $__cr6>>2 & 1 + set $__cr62 = $__cr6>>1 & 1 + set $__cr63 = $__cr6 & 1 + + set $__cr70 = $__cr7>>3 & 1 + set $__cr71 = $__cr7>>2 & 1 + set $__cr72 = $__cr7>>1 & 1 + set $__cr73 = $__cr7 & 1 +end +document __save_all_regs_h +For internal use only -- do not use. +end + +################################################################################### +# +# __color_change boolean-expression - set color to red or normal depending on +# whether expression is true (red) or false +# (0). +# +# This for coloring register value changes. Once upon a time we used "%c[3%dm" +# as the print format, where "\e[31m" was red and "\e[30m" was black. Thus we +# could use the boolean expresion directly in print statements and not need this +# routine. However, it turns out that black on some terminal color schemes is +# not the same thing as normal/standard color which is "\e[0m". Hence this more +# elaborate scheme. Sigh! :-( +# +define __color_change + if ($arg0) + printf "%c[31m", 0x1B + else + printf "%c[0m", 0x1B + end +end + +################################################################################### +# +# __display_registers_v [col] - display all registers in a fixed position vertically +# on the right side of the terminal window (or starting +# in the specified 1-relative column) +# +# Any register which changes value from the previous display is shown in red. The +# "previous" display is one for which any compatible command was previously used +# (e.g., so's, si's, il's, etc.). +# +define __display_registers_v + # Assume we will display in the last 14 columns of a 132-width display starting + # at the top of the window... + + set $screen_width = 132 + set $__row = 1 + + # We'll generalize this a bit to specify a starting column which defaults to + # the screen width minus 14. We don't allow specifying the top row since + # scrolling always moves the display up when a command is entered and this + # display looks as best as we can when we start it on row 1. + + if ($argc == 1) + set $__col = $arg0 + else + set $__col = $screen_width - 14 + end + + # If the previous command wasn't one that displayed the registers then init + # the previous values with the current values. This also makes sure they + # are defined the first time we ever use them. + + # Check for ID, IL, IP, SI, and SO... + if ($__lastcmd__ != 9 && \ + $__lastcmd__ != 11 && \ + $__lastcmd__ != 13 && \ + $__lastcmd__ != 16 && \ + $__lastcmd__ != 23) + __save_all_regs_v + set $__saved_regs = 1 + else + set $__saved_regs = 0 + end + + # Finally print all these suckers. We control the positioning for each registers + # and make sure we preserve the cursor's original position so we leave it where + # we found it. + + printf "%c7", 0x1B + #set $__row += 0 + + printf "%c[%d;%dH| PC %.8X%c[0K", 0x1B, $__row+ 0, $__col, $pc, 0x1B + printf "%c[%d;%dH| SP %.8X%c[0K", 0x1B, $__row+ 1, $__col, $sp, 0x1B + + printf "%c[%d;%dH| %c[0K", 0x1B, $__row+ 2, $__col, 0x1B + + printf "%c[%d;%dH%c[0m| LR ", 0x1B, $__row+ 3, $__col, 0x1B + __color_change ($__lr!=$lr) + printf "%.8X%c[0K", $lr, 0x1B + + printf "%c[%d;%dH| CR ", 0x1B, $__row+ 4, $__col + __color_change ($__cr0!=($cr>>28&15)) + printf "%.1X", ($cr>>28&15) + __color_change ($__cr1!=($cr>>24&15)) + printf "%.1X", ($cr>>24&15) + __color_change ($__cr2!=($cr>>20&15)) + printf "%.1X", ($cr>>20&15) + __color_change ($__cr3!=($cr>>16&15)) + printf "%.1X", ($cr>>16&15) + __color_change ($__cr4!=($cr>>12&15)) + printf "%.1X", ($cr>>12&15) + __color_change ($__cr5!=($cr>>8&15)) + printf "%.1X", ($cr>>8&15) + __color_change ($__cr6!=($cr>>4&15)) + printf "%.1X", ($cr>>4&15) + __color_change ($__cr7!=($cr&15)) + printf "%.1X", ($cr&15) + printf "%c[0K", 0x1B + + printf "%c[%d;%dH%c[0m|%c[0K", 0x1B, $__row+ 5, $__col, 0x1B, 0x1B + + printf "%c[%d;%dH%c[0m| CTR ", 0x1B, $__row+ 6, $__col, 0x1B + __color_change ($__ctr!=$ctr) + printf "%.8X%c[0K", $ctr, 0x1B + + printf "%c[%d;%dH%c[0m| MSR ", 0x1B, $__row+ 7, $__col, 0x1B + __color_change ($__msr!=$ps) + printf "%.8X%c[0K", $ps, 0x1B + + printf "%c[%d;%dH%c[0m| MQ ", 0x1B, $__row+ 8, $__col, 0x1B + __color_change ($__mq!=$mq) + printf "%.8X%c[0K", $mq, 0x1B + + printf "%c[%d;%dH%c[0m| XER ", 0x1B, $__row+ 9, $__col, 0x1B + __color_change (($__xer>>28&0xF)!=($xer>>28&0xF)) + printf "%.1X%c[0m%.3X", ($xer>>28&0xF), 0x1B, ($xer>>16&0xFFF) + __color_change (($__xer>>8&0xFF)!=($xer>>8&0xFF)) + printf "%.2X", ($xer>>8&0xFF) + __color_change (($__xer&0xFF)!=($xer&0xFF)) + printf "%2X%c[0K", ($xer&0xFF), 0x1B + + printf "%c[%d;%dH%c[0m|%c[0K", 0x1B, $__row+10, $__col, 0x1B, 0x1B + + set $__row += 11 + + printf "%c[%d;%dH%c[0m| R0 ", 0x1B, $__row+ 0, $__col, 0x1B + __color_change ($__r0!=$r0) + printf "%.8X%c[0K", $r0, 0x1B + + printf "%c[%d;%dH%c[0m| SP ", 0x1B, $__row+ 1, $__col, 0x1B + __color_change ($__sp!=$r1) + printf "%.8X%c[0K", $r1, 0x1B + + printf "%c[%d;%dH%c[0m| R2 ", 0x1B, $__row+ 2, $__col, 0x1B + __color_change ($__r2!=$r2) + printf "%.8X%c[0K", $r2, 0x1B + + printf "%c[%d;%dH%c[0m| R3 ", 0x1B, $__row+ 3, $__col, 0x1B + __color_change ($__r3!=$r3) + printf "%.8X%c[0K", $r3, 0x1B + + printf "%c[%d;%dH%c[0m| R4 ", 0x1B, $__row+ 4, $__col, 0x1B + __color_change ($__r4!=$r4) + printf "%.8X%c[0K", $r4, 0x1B + + printf "%c[%d;%dH%c[0m| R5 ", 0x1B, $__row+ 5, $__col, 0x1B + __color_change ($__r5!=$r5) + printf "%.8X%c[0K", $r5, 0x1B + + printf "%c[%d;%dH%c[0m| R6 ", 0x1B, $__row+ 6, $__col, 0x1B + __color_change ($__r6!=$r6) + printf "%.8X%c[0K", $r6, 0x1B + + printf "%c[%d;%dH%c[0m| R7 ", 0x1B, $__row+ 7, $__col, 0x1B + __color_change ($__r7!=$r7) + printf "%.8X%c[0K", $r7, 0x1B + + printf "%c[%d;%dH%c[0m| R8 ", 0x1B, $__row+ 8, $__col, 0x1B + __color_change ($__r8!=$r8) + printf "%.8X%c[0K", $r8, 0x1B + + printf "%c[%d;%dH%c[0m| R9 ", 0x1B, $__row+ 9, $__col, 0x1B + __color_change ($__r9!=$r9) + printf "%.8X%c[0K", $r9, 0x1B + + printf "%c[%d;%dH%c[0m| R10 ", 0x1B, $__row+10, $__col, 0x1B + __color_change ($__r10!=$r10) + printf "%.8X%c[0K", $r10, 0x1B + + printf "%c[%d;%dH%c[0m| R11 ", 0x1B, $__row+11, $__col, 0x1B + __color_change ($__r11!=$r11) + printf "%.8X%c[0K", $r11, 0x1B + + printf "%c[%d;%dH%c[0m| R12 ", 0x1B, $__row+12, $__col, 0x1B + __color_change ($__r12!=$r12) + printf "%.8X%c[0K", $r12, 0x1B + + printf "%c[%d;%dH%c[0m| R13 ", 0x1B, $__row+13, $__col, 0x1B + __color_change ($__r13!=$r13) + printf "%.8X%c[0K", $r13, 0x1B + + printf "%c[%d;%dH%c[0m| R14 ", 0x1B, $__row+14, $__col, 0x1B + __color_change ($__r14!=$r14) + printf "%.8X%c[0K", $r14, 0x1B + + printf "%c[%d;%dH%c[0m| R15 ", 0x1B, $__row+15, $__col, 0x1B + __color_change ($__r15!=$r15) + printf "%.8X%c[0K", $r15, 0x1B + + printf "%c[%d;%dH%c[0m| R16 ", 0x1B, $__row+16, $__col, 0x1B + __color_change ($__r16!=$r16) + printf "%.8X%c[0K", $r16, 0x1B + + printf "%c[%d;%dH%c[0m| R17 ", 0x1B, $__row+17, $__col, 0x1B + __color_change ($__r17!=$r17) + printf "%.8X%c[0K", $r17, 0x1B + + printf "%c[%d;%dH%c[0m| R18 ", 0x1B, $__row+18, $__col, 0x1B + __color_change ($__r18!=$r18) + printf "%.8X%c[0K", $r18, 0x1B + + printf "%c[%d;%dH%c[0m| R19 ", 0x1B, $__row+19, $__col, 0x1B + __color_change ($__r19!=$r19) + printf "%.8X%c[0K", $r19, 0x1B + + printf "%c[%d;%dH%c[0m| R20 ", 0x1B, $__row+20, $__col, 0x1B + __color_change ($__r20!=$r20) + printf "%.8X%c[0K", $r20, 0x1B + + printf "%c[%d;%dH%c[0m| R21 ", 0x1B, $__row+21, $__col, 0x1B + __color_change ($__r21!=$r21) + printf "%.8X%c[0K", $r21, 0x1B + + printf "%c[%d;%dH%c[0m| R22 ", 0x1B, $__row+22, $__col, 0x1B + __color_change ($__r22!=$r22) + printf "%.8X%c[0K", $r22, 0x1B + + printf "%c[%d;%dH%c[0m| R23 ", 0x1B, $__row+23, $__col, 0x1B + __color_change ($__r23!=$r23) + printf "%.8X%c[0K", $r23, 0x1B + + printf "%c[%d;%dH%c[0m| R24 ", 0x1B, $__row+24, $__col, 0x1B + __color_change ($__r24!=$r24) + printf "%.8X%c[0K", $r24, 0x1B + + printf "%c[%d;%dH%c[0m| R25 ", 0x1B, $__row+25, $__col, 0x1B + __color_change ($__r25!=$r25) + printf "%.8X%c[0K", $r25, 0x1B + + printf "%c[%d;%dH%c[0m| R26 ", 0x1B, $__row+26, $__col, 0x1B + __color_change ($__r26!=$r26) + printf "%.8X%c[0K", $r26, 0x1B + + printf "%c[%d;%dH%c[0m| R27 ", 0x1B, $__row+27, $__col, 0x1B + __color_change ($__r27!=$r27) + printf "%.8X%c[0K", $r27, 0x1B + + printf "%c[%d;%dH%c[0m| R28 ", 0x1B, $__row+28, $__col, 0x1B + __color_change ($__r28!=$r28) + printf "%.8X%c[0K", $r28, 0x1B + + printf "%c[%d;%dH%c[0m| R29 ", 0x1B, $__row+29, $__col, 0x1B + __color_change ($__r29!=$r29) + printf "%.8X%c[0K", $r29, 0x1B + + printf "%c[%d;%dH%c[0m| R30 ", 0x1B, $__row+30, $__col, 0x1B + __color_change ($__r30!=$r30) + printf "%.8X%c[0K", $r30, 0x1B + + printf "%c[%d;%dH%c[0m| R31 ", 0x1B, $__row+31, $__col, 0x1B + __color_change ($__r31!=$r31) + printf "%.8X%c[0K", $r31, 0x1B + + printf "%c[%d;%dH%c[0m+ÑÑÑÑÑÑÑÑÑÑÑÑÑ%c[0K", 0x1B, $__row+32, $__col, 0x1B, 0x1B + printf "%c8", 0x1B + + # Now that we know what's changed, save the values for the next time + # through here unless we already saved them. + + if (!$__saved_regs) + __save_all_regs_v + end +end +document __display_registers_v +For internal use only -- do not use. +end + +################################################################################### +# +# __display_registers_h - display all registers horizontally at the top of the +# screen +# +# Any register which changes value from the previous display is shown in red. The +# "previous" display is one for which any compatible command was previously used +# (e.g., so's, si's, il's, etc.). +# +# PC 00001D18 CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 +# LR 00001D14 CR 1000 0010 0000 0000 0000 0000 0001 0100 +# CTR 5ACE8160 +# MSR 0002D030 XER 000/00/00 (SOC/Compare/Count) +# +# R0 00001C48 R8 00000000 R16 00000000 R24 00000000 +# SP BFFFF170 R9 BFFFF378 R17 00000000 R25 00000000 +# R2 00000000 R10 BFFFF3DF R18 00000000 R26 BFFFF284 +# R3 00000001 R11 BFFFFFFF R19 00000000 R27 00000008 +# R4 BFFFF288 R12 5ACE8160 R20 00000000 R28 00000001 +# R5 BFFFF290 R13 00000000 R21 00000000 R29 BFFFF290 +# R6 BFFFF370 R14 00000000 R22 00000000 R30 BFFFF170 +# R7 0000000A R15 00000000 R23 00000000 R31 00001D14 +# +define __display_registers_h + # If the previous command wasn't one that displayed the registers then init + # the previous values with the current values. This also makes sure they + # are defined the first time we ever use them. + + # Check for ID, IL, IP, SI, and SO... + if ($__lastcmd__ != 9 && \ + $__lastcmd__ != 11 && \ + $__lastcmd__ != 13 && \ + $__lastcmd__ != 16 && \ + $__lastcmd__ != 23) + __save_all_regs_h + set $__saved_regs = 1 + else + set $__saved_regs = 0 + end + + printf "%c7", 0x1B + printf "%c[1;1H", 0x1B + + printf "PC %.8X CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7%c[0K\n", $pc, 0x1B + + printf "LR " + __color_change ($__lr!=$lr) + printf "%.8X%c[0m CR ", $lr, 0x1B + + __color_change ($__cr00!=($cr>>31&1)) + printf "%.1X", ($cr>>31&1) + __color_change ($__cr01!=($cr>>30&1)) + printf "%.1X", ($cr>>30&1) + __color_change ($__cr02!=($cr>>29&1)) + printf "%.1X", ($cr>>29&1) + __color_change ($__cr03!=($cr>>28&1)) + printf "%.1X", ($cr>>28&1) + printf " " + __color_change ($__cr10!=($cr>>27&1)) + printf "%.1X", ($cr>>27&1) + __color_change ($__cr11!=($cr>>26&1)) + printf "%.1X", ($cr>>26&1) + __color_change ($__cr12!=($cr>>25&1)) + printf "%.1X", ($cr>>25&1) + __color_change ($__cr13!=($cr>>24&1)) + printf "%.1X", ($cr>>24&1) + printf " " + __color_change ($__cr20!=($cr>>23&1)) + printf "%.1X", ($cr>>23&1) + __color_change ($__cr21!=($cr>>22&1)) + printf "%.1X", ($cr>>22&1) + __color_change ($__cr21!=($cr>>21&1)) + printf "%.1X", ($cr>>21&1) + __color_change ($__cr23!=($cr>>20&1)) + printf "%.1X", ($cr>>20&1) + printf " " + __color_change ($__cr30!=($cr>>19&1)) + printf "%.1X", ($cr>>19&1) + __color_change ($__cr31!=($cr>>18&1)) + printf "%.1X", ($cr>>18&1) + __color_change ($__cr32!=($cr>>17&1)) + printf "%.1X", ($cr>>17&1) + __color_change ($__cr33!=($cr>>16&1)) + printf "%.1X", ($cr>>16&1) + printf " " + __color_change ($__cr40!=($cr>>15&1)) + printf "%.1X", ($cr>>15&1) + __color_change ($__cr41!=($cr>>14&1)) + printf "%.1X", ($cr>>14&1) + __color_change ($__cr42!=($cr>>13&1)) + printf "%.1X", ($cr>>13&1) + __color_change ($__cr43!=($cr>>12&1)) + printf "%.1X", ($cr>>12&1) + printf " " + __color_change ($__cr50!=($cr>>11&1)) + printf "%.1X", ($cr>>11&1) + __color_change ($__cr51!=($cr>>10&1)) + printf "%.1X", ($cr>>10&1) + __color_change ($__cr52!=($cr>>9&1)) + printf "%.1X", ($cr>>9&1) + __color_change ($__cr53!=($cr>>8&1)) + printf "%.1X", ($cr>>8&1) + printf " " + __color_change ($__cr60!=($cr>>7&1)) + printf "%.1X", ($cr>>7&1) + __color_change ($__cr61!=($cr>>6&1)) + printf "%.1X", ($cr>>6&1) + __color_change ($__cr62!=($cr>>5&1)) + printf "%.1X", ($cr>>5&1) + __color_change ($__cr63!=($cr>>4&1)) + printf "%.1X", ($cr>>4&1) + printf " " + __color_change ($__cr70!=($cr>>3&1)) + printf "%.1X", ($cr>>3&1) + __color_change ($__cr71!=($cr>>2&1)) + printf "%.1X", ($cr>>2&1) + __color_change ($__cr72!=($cr>>1&1)) + printf "%.1X", ($cr>>1&1) + __color_change ($__cr73!=($cr&1)) + printf "%.1X", ($cr&1) + printf "%c[0m%c[0K\n", 0x1B, 0x1B + + printf "CTR " + __color_change ($__ctr!=$ctr) + printf "%.8X%c[0m%c[0K\n", $ctr, 0x1B, 0x1B + + printf "MSR " + __color_change ($__msr!=$ps) + printf "%.8X%c[0m XER ", $ps, 0x1B + + __color_change ($__so!=($xer>>31&1)) + printf "%.1X", ($xer>>31&1) + __color_change ($__ov!=($xer>>30&1)) + printf "%.1X", ($xer>>30&1) + __color_change ($__ca!=($xer>>29&1)) + printf "%.1X%c[0m/", ($xer>>29&1), 0x1B + __color_change ($__xcmp!=($xer>>8&0xFF)) + printf "%.2X%c[0m/", ($xer>>8&0xFF), 0x1B + __color_change ($__xcnt!=($xer&0x7F)) + printf "%.2X%c[0m (SOC/Compare/Count)%c[0K\n", ($xer&0x7F), 0x1B, 0x1B + + printf "%c[0K\n", 0x1B + + printf "R0 " + __color_change ($__r0!=$r0) + printf "%.8X%c[0m ", $r0, 0x1B + printf "R8 " + __color_change ($__r8!=$r8) + printf "%.8X%c[0m ", $r8, 0x1B + printf "R16 " + __color_change ($__r16!=$r16) + printf "%.8X%c[0m ", $r16, 0x1B + printf "R24 " + __color_change ($__r24!=$r24) + printf "%.8X%c[0m%c[0K\n", $r24, 0x1B, 0x1B + + printf "SP " + __color_change ($__sp!=$r1) + printf "%.8X%c[0m ", $r1, 0x1B + printf "R9 " + __color_change ($__r9!=$r9) + printf "%.8X%c[0m ", $r9, 0x1B + printf "R17 " + __color_change ($__r17!=$r17) + printf "%.8X%c[0m ", $r17, 0x1B + printf "R25 " + __color_change ($__r25!=$r25) + printf "%.8X%c[0m%c[0K\n", $r25, 0x1B, 0x1B + + printf "R2 " + __color_change ($__r2!=$r2) + printf "%.8X%c[0m ", $r2, 0x1B + printf "R10 " + __color_change ($__r10!=$r10) + printf "%.8X%c[0m ", $r10, 0x1B + printf "R18 " + __color_change ($__r18!=$r18) + printf "%.8X%c[0m ", $r18, 0x1B + printf "R26 " + __color_change ($__r26!=$r26) + printf "%.8X%c[0m%c[0K\n", $r26, 0x1B, 0x1B + + printf "R3 " + __color_change ($__r3!=$r3) + printf "%.8X%c[0m ", $r3, 0x1B + printf "R11 " + __color_change ($__r11!=$r11) + printf "%.8X%c[0m ", $r11, 0x1B + printf "R19 " + __color_change ($__r19!=$r19) + printf "%.8X%c[0m ", $r19, 0x1B + printf "R27 " + __color_change ($__r27!=$r27) + printf "%.8X%c[0m%c[0K\n", $r27, 0x1B, 0x1B + + printf "R4 " + __color_change ($__r4!=$r4) + printf "%.8X%c[0m ", $r4, 0x1B + printf "R12 " + __color_change ($__r12!=$r12) + printf "%.8X%c[0m ", $r12, 0x1B + printf "R20 " + __color_change ($__r20!=$r20) + printf "%.8X%c[0m ", $r20, 0x1B + printf "R28 " + __color_change ($__r28!=$r28) + printf "%.8X%c[0m%c[0K\n", $r28, 0x1B, 0x1B + + printf "R5 " + __color_change ($__r5!=$r5) + printf "%.8X%c[0m ", $r5, 0x1B + printf "R13 " + __color_change ($__r13!=$r13) + printf "%.8X%c[0m ", $r13, 0x1B + printf "R21 " + __color_change ($__r21!=$r21) + printf "%.8X%c[0m ", $r21, 0x1B + printf "R29 " + __color_change ($__r29!=$r29) + printf "%.8X%c[0m%c[0K\n", $r29, 0x1B, 0x1B + + printf "R6 " + __color_change ($__r6!=$r6) + printf "%.8X%c[0m ", $r6, 0x1B + printf "R14 " + __color_change ($__r14!=$r14) + printf "%.8X%c[0m ", $r14, 0x1B + printf "R22 " + __color_change ($__r22!=$r22) + printf "%.8X%c[0m ", $r22, 0x1B + printf "R30 " + __color_change ($__r30!=$r30) + printf "%.8X%c[0m%c[0K\n", $r30, 0x1B, 0x1B + + printf "R7 " + __color_change ($__r7!=$r7) + printf "%.8X%c[0m ", $r7, 0x1B + printf "R15 " + __color_change ($__r15!=$r15) + printf "%.8X%c[0m ", $r15, 0x1B + printf "R23 " + __color_change ($__r23!=$r23) + printf "%.8X%c[0m ", $r23, 0x1B + printf "R31 " + __color_change ($__r31!=$r31) + printf "%.8X%c[0m%c[0K\n", $r31, 0x1B, 0x1B + + printf "ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ%c[0K", 0x1B + printf "%c8", 0x1B + + # Now that we know what's changed, save the values for the next time + # through here unless we already saved them. + + if (!$__saved_regs) + __save_all_regs_h + end +end +document __display_registers_h +For internal use only -- do not use. +end + +################################################################################### +# +# __scroll N - turn scrolling on (N > 0) or off (N < 0) +# +# If turned on, scrolling extends from line 15 through $arg0 to accomodate the +# 14-line register display done by __display_registers_h starting at line 1. If +# scrolling is turned off, scrolling is set from line 1 through -$arg0 +# +define __scroll + #set $screen_height = 60 + + set $__bottom = $arg0 + + if ($__bottom > 0) + if ($__running__) + __display_registers_h + else + printf "%c[1;1HRegisters will be displayed here when program is running.", 0x1B + printf "%c[0J", 0x1B + end + + printf "%c[14;1H", 0x1B + printf "ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ%c[0K%c8", 0x1B, 0x1B + printf "%c[15;%dr", 0x1B, $__bottom + printf "%c[15;1H", 0x1B + printf "%c[0J", 0x1B + else + printf "%c7", 0x1B + printf "%c[1;%dr", 0x1B, -$__bottom + printf "%c8", 0x1B + end + + +end +document __scroll +For internal use only -- do not use. +end + +################################################################################### +# +# Intercept the RUN command to initialize our "global" convenience variables. None +# of the Macsbug commands make sense anyway until the user does a RUN command. This +# is fortunate since the only way to fire up execution is with a run command and +# there is NO OTHER WAY to initialize convenience variables! Simply setting them in +# this script doesn't work since gdb wipes out the variables AFTER it runs the +# script. They also get wiped out when a FILE command is done (and a hook-file is +# run before the variables are clobbered so that won't work either). +# +define hook-run + set $dot = 0 + set $__lastcmd__ = -1 + set $__next_addr__ = -1 + set $__prev_dm_n__ = 0 + set $__prev_dma_n__ = 0 + + if ($__initialized__) + # When $__initialized__ is undefined it will test false. We can only test + # undefined gdb convenience variables as shown (i.e., cannot mix with any + # operators). So this path of this if remains empty once we initialize the + # state switches. Of course a FILE command will uninialize everyting again. + else + set $__unmangle__ = 0 + set $__ditto__ = 0 + set $__dx__ = 0 + + set $__initialized__ = 1 + set $__running__ = 1 + end +end + +################################################################################### diff --git a/.gdb/misc.gdb b/.gdb/misc.gdb new file mode 100644 index 0000000..e451c36 --- /dev/null +++ b/.gdb/misc.gdb @@ -0,0 +1,164 @@ +# ____________________misc____________________ +# bunch of semi-useless commands + +# enable and disable shortcuts for stop-on-solib-events fantastic trick! +define enablesolib + set stop-on-solib-events 1 + printf "Stop-on-solib-events is enabled!\n" +end +document enablesolib +Shortcut to enable stop-on-solib-events trick. +end + + +define disablesolib + set stop-on-solib-events 0 + printf "Stop-on-solib-events is disabled!\n" +end +document disablesolib +Shortcut to disable stop-on-solib-events trick. +end + + +# enable commands for different displays +define enableobjectivec + set $SHOWOBJECTIVEC = 1 +end +document enableobjectivec +Enable display of objective-c information in the context window. +end + + +define enablecpuregisters + set $SHOWCPUREGISTERS = 1 +end +document enablecpuregisters +Enable display of cpu registers in the context window. +end + + +define enablestack + set $SHOWSTACK = 1 +end +document enablestack +Enable display of stack in the context window. +end + + +define enabledatawin + set $SHOWDATAWIN = 1 +end +document enabledatawin +Enable display of data window in the context window. +end + + +# disable commands for different displays +define disableobjectivec + set $SHOWOBJECTIVEC = 0 +end +document disableobjectivec +Disable display of objective-c information in the context window. +end + + +define disablecpuregisters + set $SHOWCPUREGISTERS = 0 +end +document disablecpuregisters +Disable display of cpu registers in the context window. +end + + +define disablestack + set $SHOWSTACK = 0 +end +document disablestack +Disable display of stack information in the context window. +end + + +define disabledatawin + set $SHOWDATAWIN = 0 +end +document disabledatawin +Disable display of data window in the context window. +end + + +define 32bits + set $64BITS = 0 + if $X86FLAVOR == 0 + set disassembly-flavor intel + else + set disassembly-flavor att + end +end +document 32bits +Set gdb to work with 32bits binaries. +end + + +define 64bits + set $64BITS = 1 + if $X86FLAVOR == 0 + set disassembly-flavor intel + else + set disassembly-flavor att + end +end +document 64bits +Set gdb to work with 64bits binaries. +end + + +define arm + if $ARMOPCODES == 1 + set arm show-opcode-bytes 1 + else + set arm show-opcode-bytes 1 + end + set $ARM = 1 + set $64BITS = 0 +end +document arm +Set gdb to work with ARM binaries. +end + + +define enablelib + set stop-on-solib-events 1 +end +document enablelib +Activate stop-on-solib-events. +end + + +define disablelib + set stop-on-solib-events 0 +end +document disablelib +Deactivate stop-on-solib-events. +end + + +define intelsyntax + if (($X86 == 1) || ($X86_64 == 1)) + set disassembly-flavor intel + set $X86FLAVOR = 0 + end +end +document intelsyntax +Change disassembly syntax to intel flavor. +end + + +define attsyntax + if (($X86 == 1) || ($X86_64 == 1)) + set disassembly-flavor att + set $X86FLAVOR = 1 + end +end +document attsyntax +Change disassembly syntax to at&t flavor. +end diff --git a/.gdb/patch.gdb b/.gdb/patch.gdb new file mode 100644 index 0000000..c65a070 --- /dev/null +++ b/.gdb/patch.gdb @@ -0,0 +1,279 @@ +# ____________________patch___________________ +# the usual nops are mov r0,r0 for arm (0xe1a00000) +# and mov r8,r8 in Thumb (0x46c0) +# armv7 has other nops +# FIXME: make sure that the interval fits the 32bits address for arm and 16bits for thumb +# status: works, fixme +define nop + if ($argc > 2 || $argc == 0) + help nop + end + + if $ARM == 1 + if ($argc == 1) + if ($cpsr->t &1) + # thumb + set *(short *) $arg0 = 0x46c0 + else + # arm + set *(int *) $arg0 = 0xe1a00000 + end + else + set $addr = $arg0 + if ($cpsr->t & 1) + # thumb + while ($addr < $arg1) + set *(short *) $addr = 0x46c0 + set $addr = $addr + 2 + end + else + # arm + while ($addr < $arg1) + set *(int *) $addr = 0xe1a00000 + set $addr = $addr + 4 + end + end + end + end + + if (($X86 == 1) || ($X86_64 == 1)) + if ($argc == 1) + set *(unsigned char *) $arg0 = 0x90 + else + set $addr = $arg0 + while ($addr < $arg1) + set *(unsigned char *) $addr = 0x90 + set $addr = $addr + 1 + end + end + end +end +document nop +Usage: nop ADDR1 [ADDR2] +Patch a single byte at address ADDR1, or a series of bytes between ADDR1 and ADDR2 to a NOP (0x90) instruction. +ARM or Thumb code will be patched accordingly. +end + + +define null + if ($argc >2 || $argc == 0) + help null + end + + if ($argc == 1) + set *(unsigned char *) $arg0 = 0 + else + set $addr = $arg0 + while ($addr < $arg1) + set *(unsigned char *) $addr = 0 + set $addr = $addr + 1 + end + end +end +document null +Usage: null ADDR1 [ADDR2] +Patch a single byte at address ADDR1 to NULL (0x00), or a series of bytes between ADDR1 and ADDR2. +end + +# FIXME: thumb breakpoint ? +define int3 + if $argc != 1 + help int3 + else + if $ARM == 1 + set $ORIGINAL_INT3 = *(unsigned int *) $arg0 + set $ORIGINAL_INT3ADDRESS = $arg0 + set *(unsigned int*) $arg0 = 0xe7ffdefe + end + + if (($X86 == 1) || ($X86_64 == 1)) + # save original bytes and address + set $ORIGINAL_INT3 = *(unsigned char *) $arg0 + set $ORIGINAL_INT3ADDRESS = $arg0 + # patch + set *(unsigned char *) $arg0 = 0xCC + end + end +end +document int3 +Patch byte at address ADDR to an INT3 (0xCC) instruction or the equivalent software breakpoint for ARM. +Usage: int3 ADDR +end + + +define rint3 + if $ARM == 1 + set *(unsigned int *) $ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3 + set $pc = $ORIGINAL_INT3ADDRESS + end + + if (($X86 == 1) || ($X86_64 == 1)) + set *(unsigned char *) $ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3 + if $64BITS == 1 + set $rip = $ORIGINAL_INT3ADDRESS + else + set $eip = $ORIGINAL_INT3ADDRESS + end + end +end +document rint3 +Restore the original byte previous to int3 patch issued with "int3" command. +end + + +# original by Tavis Ormandy (http://my.opera.com/taviso/blog/index.dml/tag/gdb) (great fix!) +# modified to work with Mac OS X by fG! +# seems nasm shipping with Mac OS X has problems accepting input from stdin or heredoc +# input is read into a variable and sent to a temporary file which nasm can read +define assemble + # dont enter routine again if user hits enter + dont-repeat + if ($argc) + if (*$arg0 = *$arg0) + # check if we have a valid address by dereferencing it, + # if we havnt, this will cause the routine to exit. + end + printf "Instructions will be written to %#x.\n", $arg0 + else + printf "Instructions will be written to stdout.\n" + end + printf "Type instructions, one per line." + echo \033[1m + printf " Do not forget to use NASM assembler syntax!\n" + echo \033[0m + printf "End with a line saying just \"end\".\n" + + if ($argc) + if ($X86_64 == 1) + # argument specified, assemble instructions into memory at address specified. + shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)"; \ + GDBASMFILENAME=$RANDOM; \ + echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME; \ + /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | \ + /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble; \ + /bin/rm -f /tmp/$GDBASMFILENAME + source /tmp/gdbassemble + # all done. clean the temporary file + shell /bin/rm -f /tmp/gdbassemble + end + + if ($X86 == 1) + # argument specified, assemble instructions into memory at address specified. + shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)"; \ + GDBASMFILENAME=$RANDOM; \ + echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME; \ + /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | \ + /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble; \ + /bin/rm -f /tmp/$GDBASMFILENAME + source /tmp/gdbassemble + # all done. clean the temporary file + shell /bin/rm -f /tmp/gdbassemble + end + else + if ($X86_64 == 1) + # no argument, assemble instructions to stdout + shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)"; + GDBASMFILENAME=$RANDOM; \ + echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME; \ + /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | \ + /usr/local/bin/ndisasm -i -b64 /dev/stdin; \ + /bin/rm -f /tmp/$GDBASMFILENAME + end + + if ($X86 == 1) + # no argument, assemble instructions to stdout + shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)"; \ + GDBASMFILENAME=$RANDOM; \ + echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME; \ + /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | \ + /usr/bin/ndisasm -i -b32 /dev/stdin; \ + /bin/rm -f /tmp/$GDBASMFILENAME + end + end +end +document assemble +Assemble instructions using nasm. +Type a line containing "end" to indicate the end. +If an address is specified, insert/modify instructions at that address. +If no address is specified, assembled instructions are printed to stdout. +Use the pseudo instruction "org ADDR" to set the base address. +end + + +define asm + if $argc == 1 + assemble $arg0 + else + assemble + end +end +document asm +Shortcut to the asssemble command. +end + + +define assemble_gas + printf "\nType code to assemble and hit Ctrl-D when finished.\n" + printf "You must use GNU assembler (AT&T) syntax.\n" + + shell filename=$(mktemp); \ + binfilename=$(mktemp); \ + echo -e "Writing into: ${filename}\n"; \ + cat > $filename; echo ""; \ + as -o $binfilename < $filename; \ + objdump -d -j .text $binfilename; \ + rm -f $binfilename; \ + rm -f $filename; \ + echo -e "temporaly files deleted.\n" +end +document assemble_gas +Assemble instructions to binary opcodes. Uses GNU as and objdump. +Usage: assemble_gas +end + + +define dump_hexfile + dump ihex memory $arg0 $arg1 $arg2 +end +document dump_hexfile +Write a range of memory to a file in Intel ihex (hexdump) format. +The range is specified by ADDR1 and ADDR2 addresses. +Usage: dump_hexfile FILENAME ADDR1 ADDR2 +end + + +define dump_binfile + dump memory $arg0 $arg1 $arg2 +end +document dump_binfile +Write a range of memory to a binary file. +The range is specified by ADDR1 and ADDR2 addresses. +Usage: dump_binfile FILENAME ADDR1 ADDR2 +end + + +define dumpmacho + if $argc != 2 + help dumpmacho + end + set $headermagic = *$arg0 + # the || operator isn't working as it should, wtf!!! + if $headermagic != 0xfeedface + if $headermagic != 0xfeedfacf + printf "[Error] Target address doesn't contain a valid Mach-O binary!\n" + help dumpmacho + end + end + set $headerdumpsize = *($arg0 + 0x14) + if $headermagic == 0xfeedface + dump memory $arg1 $arg0 ($arg0 + 0x1c + $headerdumpsize) + end + if $headermagic == 0xfeedfacf + dump memory $arg1 $arg0 ($arg0 + 0x20 + $headerdumpsize) + end +end +document dumpmacho +Dump the Mach-O header to a file. +You need to input the start address (use info shared command to find it). +Usage: dumpmacho STARTADDRESS FILENAME +end diff --git a/.gdb/process.gdb b/.gdb/process.gdb new file mode 100644 index 0000000..8988d78 --- /dev/null +++ b/.gdb/process.gdb @@ -0,0 +1,7 @@ +# ______________process information____________ +define argv + show args +end +document argv +Print program arguments. +end diff --git a/.gdb/profile.gdb b/.gdb/profile.gdb new file mode 100644 index 0000000..6312d5a --- /dev/null +++ b/.gdb/profile.gdb @@ -0,0 +1,33 @@ +set $rusage = 0 +set $rusagebuffer = 0 + +define getrusage + if ($rusagebuffer == 0) + set $rusagebuffer = (unsigned long *) malloc (1024) + end + call (void) getrusage (0, $rusagebuffer) + set $rusage = (($rusagebuffer[0] * 1000) + ($rusagebuffer[1] / 1000)) +end + +define mark + getrusage + set $rusagemark = $rusage + printf "Timer started; total elapsed CPU time is %lu ms.\n", $rusagemark +end +document mark +Start a counter representing the elapsed CPU time since 'mark' was called. +To determine the amount of CPU time used since 'mark' was called, use the +'cur' command. +end + +define cur + if ($rusagebuffer == 0) + printf "No timer has been started.\n" + else + getrusage + printf "Elapsed CPU time since last mark is %lu ms.\n", ($rusage - $rusagemark) + end +end +document cur +Display the amount of CPU time used since the last 'mark' command. +end \ No newline at end of file diff --git a/.gdb/setup.gdb b/.gdb/setup.gdb new file mode 100644 index 0000000..eccbd56 --- /dev/null +++ b/.gdb/setup.gdb @@ -0,0 +1,28 @@ +define setup-detect-target + set $ARM = 0 + set $X86 = 0 + set $X86_64 = 0 + set $MIPS = 0 + + set $64BITS = 0 + + set logging file /tmp/gdb_info_target + set logging overwrite on + set logging redirect on + set logging on + set pagination off + info target + show osabi + set pagination on + set logging off + set logging redirect off + set logging overwrite off + + shell ~/.gdb/detect-target.sh + source /tmp/gdb_target_arch.gdb + shell rm -f /tmp/gdb_info_target /tmp/gdb_target_arch.gdb +end +document setup-detect-target +Sets up various globals used throughout the GDB macros to provide +architecture-specific support. +end diff --git a/.gdb/tips.gdb b/.gdb/tips.gdb new file mode 100644 index 0000000..079007a --- /dev/null +++ b/.gdb/tips.gdb @@ -0,0 +1,100 @@ +# _________________user tips_________________ +# The 'tips' command is used to provide tutorial-like info to the user +define tips + printf "Tip Topic Commands:\n" + printf "\ttip_display : Automatically display values on each break\n" + printf "\ttip_patch : Patching binaries\n" + printf "\ttip_strip : Dealing with stripped binaries\n" + printf "\ttip_syntax : AT&T vs Intel syntax\n" +end +document tips +Provide a list of tips from users on various topics. +end + + +define tip_patch + printf "\n" + printf " PATCHING MEMORY\n" + printf "Any address can be patched using the 'set' command:\n" + printf "\t`set ADDR = VALUE` \te.g. `set *0x8049D6E = 0x90`\n" + printf "\n" + printf " PATCHING BINARY FILES\n" + printf "Use `set write` in order to patch the target executable\n" + printf "directly, instead of just patching memory\n" + printf "\t`set write on` \t`set write off`\n" + printf "Note that this means any patches to the code or data segments\n" + printf "will be written to the executable file\n" + printf "When either of these commands has been issued,\n" + printf "the file must be reloaded.\n" + printf "\n" +end +document tip_patch +Tips on patching memory and binary files. +end + + +define tip_strip + printf "\n" + printf " STOPPING BINARIES AT ENTRY POINT\n" + printf "Stripped binaries have no symbols, and are therefore tough to\n" + printf "start automatically. To debug a stripped binary, use\n" + printf "\tinfo file\n" + printf "to get the entry point of the file\n" + printf "The first few lines of output will look like this:\n" + printf "\tSymbols from '/tmp/a.out'\n" + printf "\tLocal exec file:\n" + printf "\t `/tmp/a.out', file type elf32-i386.\n" + printf "\t Entry point: 0x80482e0\n" + printf "Use this entry point to set an entry point:\n" + printf "\t`tbreak *0x80482e0`\n" + printf "The breakpoint will delete itself after the program stops as\n" + printf "the entry point\n" + printf "\n" +end +document tip_strip +Tips on dealing with stripped binaries. +end + + +define tip_syntax + printf "\n" + printf "\t INTEL SYNTAX AT&T SYNTAX\n" + printf "\tmnemonic dest, src, imm mnemonic src, dest, imm\n" + printf "\t[base+index*scale+disp] disp(base, index, scale)\n" + printf "\tregister: eax register: %%eax\n" + printf "\timmediate: 0xFF immediate: $0xFF\n" + printf "\tdereference: [addr] dereference: addr(,1)\n" + printf "\tabsolute addr: addr absolute addr: *addr\n" + printf "\tbyte insn: mov byte ptr byte insn: movb\n" + printf "\tword insn: mov word ptr word insn: movw\n" + printf "\tdword insn: mov dword ptr dword insn: movd\n" + printf "\tfar call: call far far call: lcall\n" + printf "\tfar jump: jmp far far jump: ljmp\n" + printf "\n" + printf "Note that order of operands in reversed, and that AT&T syntax\n" + printf "requires that all instructions referencing memory operands \n" + printf "use an operand size suffix (b, w, d, q)\n" + printf "\n" +end +document tip_syntax +Summary of Intel and AT&T syntax differences. +end + + +define tip_display + printf "\n" + printf "Any expression can be set to automatically be displayed every time\n" + printf "the target stops. The commands for this are:\n" + printf "\t`display expr' : automatically display expression 'expr'\n" + printf "\t`display' : show all displayed expressions\n" + printf "\t`undisplay num' : turn off autodisplay for expression # 'num'\n" + printf "Examples:\n" + printf "\t`display/x *(int *)$esp` : print top of stack\n" + printf "\t`display/x *(int *)($ebp+8)` : print first parameter\n" + printf "\t`display (char *)$esi` : print source string\n" + printf "\t`display (char *)$edi` : print destination string\n" + printf "\n" +end +document tip_display +Tips on automatically displaying values when a program stops. +end diff --git a/.gdb/tracing.gdb b/.gdb/tracing.gdb new file mode 100644 index 0000000..72865c9 --- /dev/null +++ b/.gdb/tracing.gdb @@ -0,0 +1,328 @@ +# used by ptraceme/rptraceme +set $ptrace_bpnum = 0 + +# _______________process control______________ +define n + if $argc == 0 + nexti + end + if $argc == 1 + nexti $arg0 + end + if $argc > 1 + help n + end +end +document n +Step one instruction, but proceed through subroutine calls. +If NUM is given, then repeat it NUM times or till program stops. +This is alias for nexti. +Usage: n +end + + +define go + if $argc == 0 + stepi + end + if $argc == 1 + stepi $arg0 + end + if $argc > 1 + help go + end +end +document go +Step one instruction exactly. +If NUM is given, then repeat it NUM times or till program stops. +This is alias for stepi. +Usage: go +end + + +define pret + finish +end +document pret +Execute until selected stack frame returns (step out of current call). +Upon return, the value returned is printed and put in the value history. +end + + +define init + set $SHOW_NEST_INSN = 0 + tbreak _init + r +end +document init +Run program and break on _init(). +end + + +define start + set $SHOW_NEST_INSN = 0 + tbreak _start + r +end +document start +Run program and break on _start(). +end + + +define sstart + set $SHOW_NEST_INSN = 0 + tbreak __libc_start_main + r +end +document sstart +Run program and break on __libc_start_main(). +Useful for stripped executables. +end + + +define main + set $SHOW_NEST_INSN = 0 + tbreak main + r +end +document main +Run program and break on main(). +end + + +# FIXME64 +#### WARNING ! WARNING !! +#### More more messy stuff starting !!! +#### I was thinking about how to do this and then it ocurred me that it could be as simple as this ! :) +define stepoframework + if $ARM == 1 + stepoframeworkarm + end + + if (($X86 == 1) || ($X86_64 == 1)) + stepoframeworkx86 + end +end +document stepoframework +Auxiliary function to stepo command. +end + +define stepo + stepoframework 0 +end +document stepo +Step over calls (interesting to bypass the ones to msgSend). +This function will set a temporary breakpoint on next instruction after the call so the call will be bypassed. +You can safely use it instead nexti or n since it will single step code if it's not a call instruction (unless you want to go into the call function). +end + + +define stepoh + stepoframework 1 +end +document stepoh +Same as stepo command but uses temporary hardware breakpoints. +end + + +# FIXME: ARM +define skip + x/2i $pc + set $instruction_size = (int) ($_ - $pc) + set $pc = $pc + $instruction_size + if ($SKIPEXECUTE == 1) + if ($SKIPSTEP == 1) + stepo + else + stepi + end + else + context + end +end +document skip +Skip over the instruction located at EIP/RIP. By default, the instruction will not be executed! +Some configurable options are available on top of gdbinit to override this. +end + + +define step_to_call + set $_saved_ctx = $SHOW_CONTEXT + set $SHOW_CONTEXT = 0 + set $SHOW_NEST_INSN = 0 + + set logging file /dev/null + set logging redirect on + set logging on + + set $_cont = 1 + while ($_cont > 0) + stepi + get_insn_type $pc + if ($INSN_TYPE == 3) + set $_cont = 0 + end + end + + set logging off + + if ($_saved_ctx > 0) + context + end + + set $SHOW_CONTEXT = $_saved_ctx + set $SHOW_NEST_INSN = 0 + + set logging file ~/gdb.txt + set logging redirect off + set logging on + + printf "step_to_call command stopped at:\n " + x/i $pc + printf "\n" + set logging off +end +document step_to_call +Single step until a call instruction is found. +Stop before the call is taken. +Log is written into the file ~/gdb.txt. +end + + +define trace_calls + + printf "Tracing...please wait...\n" + + set $_saved_ctx = $SHOW_CONTEXT + set $SHOW_CONTEXT = 0 + set $SHOW_NEST_INSN = 0 + set $_nest = 1 + set listsize 0 + + set logging overwrite on + set logging file ~/gdb_trace_calls.txt + set logging on + set logging off + set logging overwrite off + + while ($_nest > 0) + get_insn_type $pc + # handle nesting + if ($INSN_TYPE == 3) + set $_nest = $_nest + 1 + else + if ($INSN_TYPE == 4) + set $_nest = $_nest - 1 + end + end + # if a call, print it + if ($INSN_TYPE == 3) + set logging file ~/gdb_trace_calls.txt + set logging redirect off + set logging on + + set $x = $_nest - 2 + while ($x > 0) + printf "\t" + set $x = $x - 1 + end + x/i $pc + end + + set logging off + set logging file /dev/null + set logging redirect on + set logging on + stepi + set logging redirect off + set logging off + end + + set $SHOW_CONTEXT = $_saved_ctx + set $SHOW_NEST_INSN = 0 + + printf "Done, check ~/gdb_trace_calls.txt\n" +end +document trace_calls +Create a runtime trace of the calls made by target. +Log overwrites(!) the file ~/gdb_trace_calls.txt. +end + + +define trace_run + + printf "Tracing...please wait...\n" + + set $_saved_ctx = $SHOW_CONTEXT + set $SHOW_CONTEXT = 0 + set $SHOW_NEST_INSN = 1 + set logging overwrite on + set logging file ~/gdb_trace_run.txt + set logging redirect on + set logging on + set $_nest = 1 + + while ($_nest > 0) + get_insn_type $pc + # jmp, jcc, or cll + if ($INSN_TYPE == 3) + set $_nest = $_nest + 1 + else + # ret + if ($INSN_TYPE == 4) + set $_nest = $_nest - 1 + end + end + stepi + end + + printf "\n" + + set $SHOW_CONTEXT = $_saved_ctx + set $SHOW_NEST_INSN = 0 + set logging redirect off + set logging off + + # clean up trace file + shell grep -v ' at ' ~/gdb_trace_run.txt > ~/gdb_trace_run.1 + shell grep -v ' in ' ~/gdb_trace_run.1 > ~/gdb_trace_run.txt + shell rm -f ~/gdb_trace_run.1 + printf "Done, check ~/gdb_trace_run.txt\n" +end +document trace_run +Create a runtime trace of target. +Log overwrites(!) the file ~/gdb_trace_run.txt. +end + +#define ptraceme +# catch syscall ptrace +# commands +# if ($X86 == 1) +# if ($ebx == 0) +# set $eax = 0 +# continue +# end +# end +# +# if ($X86_64 == 1) +# if ($rdi == 0) +# set $rax = 0 +# continue +# end +# end +# end +# set $ptrace_bpnum = $bpnum +#end +#document ptraceme +#Hook ptrace to bypass PTRACE_TRACEME anti debugging technique +#end + +define rptraceme + if ($ptrace_bpnum != 0) + delete $ptrace_bpnum + set $ptrace_bpnum = 0 + end +end +document rptraceme +Remove ptrace hook. +end diff --git a/.gdb/window.gdb b/.gdb/window.gdb new file mode 100644 index 0000000..08433e1 --- /dev/null +++ b/.gdb/window.gdb @@ -0,0 +1,46 @@ +# ______________window size control___________ +define contextsize-stack + if $argc != 1 + help contextsize-stack + else + set $CONTEXTSIZE_STACK = $arg0 + end +end +document contextsize-stack +Set stack dump window size to NUM lines. +Usage: contextsize-stack NUM +end + + +define contextsize-data + if $argc != 1 + help contextsize-data + else + set $CONTEXTSIZE_DATA = $arg0 + end +end +document contextsize-data +Set data dump window size to NUM lines. +Usage: contextsize-data NUM +end + + +define contextsize-code + if $argc != 1 + help contextsize-code + else + set $CONTEXTSIZE_CODE = $arg0 + end +end +document contextsize-code +Set code window size to NUM lines. +Usage: contextsize-code NUM +end + + +define cls + shell clear +end +document cls +Clear screen. +end diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..dc99139 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,132 @@ +### +# Options + +# set to 0 if you have problems with the colorized prompt - reported by Plouj with Ubuntu gdb 7.2 +set $COLOUREDPROMPT = 0 +# Colour the first line of the disassembly - default is green, if you want to change it search for +# SETCOLOUR1STLINE and modify it :-) +set $SETCOLOUR1STLINE = 0 +# set to 0 to remove display of objectivec messages (default is 1) +set $SHOWOBJECTIVEC = 0 +# set to 0 to remove display of cpu registers (default is 1) +set $SHOWCPUREGISTERS = 1 +# set to 1 to enable display of stack (default is 0) +set $SHOWSTACK = 0 +# set to 1 to enable display of data window (default is 0) +set $SHOWDATAWIN = 0 +# set to 0 to disable coloured display of changed registers +set $SHOWREGCHANGES = 1 +# set to 1 so skip command to execute the instruction at the new location +# by default it EIP/RIP will be modified and update the new context but not execute the instruction +set $SKIPEXECUTE = 0 +# if $SKIPEXECUTE is 1 configure the type of execution +# 1 = use stepo (do not get into calls), 0 = use stepi (step into calls) +set $SKIPSTEP = 1 +# show the ARM opcodes - change to 0 if you don't want such thing (in x/i command) +set $ARMOPCODES = 1 +# x86 disassembly flavor: 0 for Intel, 1 for AT&T +set $X86FLAVOR = 0 + +set $displayobjectivec = 0 + +set confirm off +set verbose off + +set output-radix 0x10 +set input-radix 0x10 + +# These make gdb never pause in its output +set height 0 +set width 0 + +set $SHOW_CONTEXT = 1 +set $SHOW_NEST_INSN = 0 + +set $CONTEXTSIZE_STACK = 6 +set $CONTEXTSIZE_DATA = 8 +set $CONTEXTSIZE_CODE = 8 + +# Options +### + + +if $COLOUREDPROMPT == 1 + set prompt \033[31mgdb$ \033[0m +end + + +### +# Command files + +source ~/.gdb/setup.gdb +source ~/.gdb/cpu.gdb +source ~/.gdb/data.gdb + +source ~/.gdb/window.gdb +source ~/.gdb/process.gdb +source ~/.gdb/datawin.gdb +source ~/.gdb/dumpjump.gdb +source ~/.gdb/patch.gdb +source ~/.gdb/tracing.gdb +source ~/.gdb/misc.gdb +source ~/.gdb/info.gdb +source ~/.gdb/tips.gdb +source ~/.gdb/macsbug.gdb +source ~/.gdb/carbon.gdb +source ~/.gdb/profile.gdb + +source ~/.gdb/c++.gdb +source ~/.gdb/eigen.gdb + +# The following is commented out because it caused errors last time for me (egall) +#source ~/.gdb/kgmacros.gdb + +# Configuration options specific to local machine. This file should never go +# into version control. +source ~/.gdbinit.local + +# Command files +### + + +### +# Hooks + +define hook-run + # Attempt to detect the target in case gdb was started with the executable + # as an argument. + setup-detect-target +end + + +define hook-file + # Attempt to detect the target again since a new binary has been loaded. + setup-detect-target +end + + +define hook-core-file + # Attempt to detect the target again since a new core has been loaded. + setup-detect-target +end + + +define hook-stop + # Display instructions formats + hookstopcpu + + # this makes 'context' be called at every BP/step + if ($SHOW_CONTEXT > 0) + context + end + if ($SHOW_NEST_INSN > 0) + set $x = $_nest + while ($x > 0) + printf "\t" + set $x = $x - 1 + end + end +end + +# Hooks +### diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ec4534 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.gdbinit.local +.gdb/history +*.pyc +*.DS_Store diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..6486218 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,266 @@ +INSTALL INSTRUCTIONS: save as ~/.gdbinit + +DESCRIPTION: A user-friendly gdb configuration file, for x86/x86_64 and ARM + platforms. + +REVISION : 8.0.2 (31/07/2012) + +CONTRIBUTORS: mammon_, elaine, pusillus, mong, zhang le, l0kit, + truthix the cyberpunk, fG!, gln + +FEEDBACK: http://reverse.put.as - reverser@put.as + +NOTES: 'help user' in gdb will list the commands/descriptions in this file + 'context on' now enables auto-display of context screen + +MAC OS X NOTES: If you are using this on Mac OS X, you must either attach gdb to + a process or launch gdb without any options and then load the + binary file you want to analyse with "exec-file" option. If you + load the binary from the command line, like $gdb binary-name, + this will not work as it should. + For more information, read it here + http://reverse.put.as/2008/11/28/apples-gdb-bug/ + +UPDATE: This bug can be fixed in gdb source. Refer to + http://reverse.put.as/2009/08/10/fix-for-apples-gdb-bug-or-why-apple-forks-are-bad/ + and http://reverse.put.as/2009/08/26/gdb-patches/ (if you want the fixed + binary for i386) + + An updated version of the patch and binary is available at + http://reverse.put.as/2011/02/21/update-to-gdb-patches-fix-a-new-bug/ + +iOS NOTES: iOS gdb from Cydia (and Apple's) suffer from the same OS X bug. + If you are using this on Mac OS X or iOS, you must either attach gdb + to a process or launch gdb without any options and then load the + binary file you want to analyse with "exec-file" option. If you load + the binary from the command line, like $gdb binary-name, this will + not work as it should. + For more information, read it + here http://reverse.put.as/2008/11/28/apples-gdb-bug/ + +CHANGELOG: (older changes at the end of the file) + + Version 8.0.2 (31/07/2012) + - Merge pull request from mheistermann to support local modifications in a + .gdbinit.local file + - Add a missing opcode to the stepo command + + Version 8.0.1 (23/04/2012) + - Small bug fix to the attsyntax and intelsyntax commands (changing X86 + flavor variable was missing) + + Version 8.0 (13/04/2012) + - Merged x86/x64 and ARM versions + - Added commands intelsyntax and attsyntax to switch between x86 disassembly + flavors + - Added new configuration variables ARM, ARMOPCODES, and X86FLAVOR + - Code cleanups and fixes to the indentation + - Bug fixes to some ARM related code + - Added the dumpmacho command to memory dump the mach-o header to a file + + Version 7.4.4 (02/01/2012) + - Added the "skip" command. This will jump to the next instruction after + EIP/RIP without executing the current one. + Thanks to @bSr43 for the tip to retrieve the current instruction size. + + Version 7.4.3 (04/11/2011) + - Modified "hexdump" command to support a variable number of lines (optional + parameter) + - Removed restrictions on type of addresses in the "dd" command - Thanks to + Plouj for the warning :-) + I don't know what was the original thinking behind those :-) + - Modified the assemble command to support 64bits - You will need to + recompile nasm since the version shipped with OS X doesn't supports 64bits + (www.nasm.us). + Assumes that the new binary is installed at /usr/local/bin - modify the + variable at the top if you need so. + It will assemble based on the target arch being debugged. If you want to + use gdb for a quick asm just use the 32bits or 64bits commands to set your + target. + Thanks to snare for the warning and original patch :-) + - Added "asm" command - it's a shortcut to the "assemble" command. + - Added configuration variable for colorized prompt. Plouj reported some + issues with Ubuntu's gdb 7.2 if prompt is colorized. + + Version 7.4.2 (11/08/2011) + - Small fix to a weird bug happening on FreeBSD 8.2. It doesn't like a "if(" + instruction, needs to be "if (". Weird! + Many thanks to Evan for reporting and sending the patch :-) + - Added the ptraceme/rptraceme commands to bypass PTRACE_TRACME + anti-debugging technique. + Grabbed this from http://falken.tuxfamily.org/?p=171 + It's commented out due to a gdb problem in OS X (refer to + http://reverse.put.as/2011/08/20/another-patch-for-apples-gdb-the-definecommands-problem/) + Just uncomment it if you want to use in ptrace enabled systems. + + Version 7.4.1 (21/06/2011) - fG! + - Added patch sent by sbz, more than 1 year ago, which I forgot to add :-/ + This will allow to search for a given pattern between start and end address. + On sbz words: "It's usefull to find call, ret or everything like that." :-) + New command is "search" + + Version 7.4 (20/06/2011) - fG! + - When registers change between instructions the colour will change to red + (like it happens in OllyDBG). + This is the default behavior, if you don't like it, modify the variable + SHOWREGCHANGES + - Added patch sent by Philippe Langlois + Colour the first disassembly line - change the setting below on + SETCOLOUR1STLINE - by default it's disabled + + Version 7.3.2 (21/02/2011) - fG! + - Added the command rint3 and modified the int3 command. The new command + will restore the byte in previous int3 patch. + + Version 7.3.1 (29/06/2010) - fG! + - Added enablelib/disablelib command to quickly set the + stop-on-solib-events trick + - Implemented the stepoh command equivalent to the stepo but using hardware + breakpoints + - More fixes to stepo + + Version 7.3 (16/04/2010) - fG! + - Support for 64bits targets. Default is 32bits, you should modify the + variable or use the 32bits or 64bits to choose the mode. + I couldn't find another way to recognize the type of binary… Testing the + register doesn't work that well. + TODO: fix objectivec messages and stepo for 64bits + + Version 7.2.1 (24/11/2009) - fG! + - Another fix to stepo (0xFF92 missing) + + Version 7.2 (11/10/2009) - fG! + - Added the smallregisters function to create 16 and 8 bit versions from the + registers EAX, EBX, ECX, EDX + - Revised and fixed all the dumpjump stuff, following Intel manuals. There + were some errors (thx to rev who pointed the jle problem). + - Small fix to stepo command (missed a few call types) + + Version 7.1.7 - fG! + - Added the possibility to modify what's displayed with the context window. + You can change default options at the gdb options part. For example, + kernel debugging is much slower if the stack display is enabled... + - New commands enableobjectivec, enablecpuregisters, enablestack, + enabledatawin and their disable equivalents (to support realtime change of + default options) + - Fixed problem with the assemble command. I was calling /bin/echo which + doesn't support the -e option ! DUH ! Should have used bash internal + version. + - Small fixes to colours... + - New commands enablesolib and disablesolib. Just shortcuts for the + stop-on-solib-events fantastic trick ! Hey... I'm lazy ;) + - Fixed this: Possible removal of "u" command, info udot is missing in gdb + 6.8-debian . Doesn't exist on OS X so bye bye !!! + - Displays affected flags in jump decisions + + Version 7.1.6 - fG! + - Added modified assemble command from Tavis Ormandy (further modified to + work with Mac OS X) (shell commands used use full path name, working for + Leopard, modify for others if necessary) + - Renamed thread command to threads because thread is an internal gdb + command that allows to move between program threads + + Version 7.1.5 (04/01/2009) - fG! + - Fixed crash on Leopard! There was a If Else condition where the else had + no code and that made gdb crash on Leopard (CRAZY!!!!) + - Better code indention + + Version 7.1.4 (02/01/2009) - fG! + - Bug in show objective c messages with Leopard ??? + - Nop routine support for single address or range (contribution from gln + [ghalen at hack.se]) + - Used the same code from nop to null routine + + Version 7.1.3 (31/12/2008) - fG! + - Added a new command 'stepo'. This command will step a temporary breakpoint + on next instruction after the call, so you can skip over the call. Did + this because normal commands not always skip over (mainly with + objc_msgSend) + + Version 7.1.2 (31/12/2008) - fG! + - Support for the jump decision (will display if a conditional jump will be + taken or not) + + Version 7.1.1 (29/12/2008) - fG! + - Moved gdb options to the beginning (makes more sense) + - Added support to dump message being sent to msgSend (easier to understand + what's going on) + + Version 7.1 + - Fixed serious (and old) bug in dd and datawin, causing dereference of + obviously invalid address. See below: + gdb$ dd 0xffffffff + FFFFFFFF : Cannot access memory at address 0xffffffff + + Version 7.0 + - Added cls command. + - Improved documentation of many commands. + - Removed bp_alloc, was neither portable nor usefull. + - Checking of passed argument(s) in these commands: + contextsize-stack, contextsize-data, contextsize-code + bp, bpc, bpe, bpd, bpt, bpm, bhb,... + - Fixed bp and bhb inconsistencies, look at * signs in Version 6.2 + - Bugfix in bhb command, changed "break" to "hb" command body + - Removed $SHOW_CONTEXT=1 from several commands, this variable + should only be controlled globally with context-on and context-off + Improved stack, func, var and sig, dis, n, go,... + they take optional argument(s) now + - Fixed wrong $SHOW_CONTEXT assignment in context-off + - Fixed serious bug in cft command, forgotten ~ sign + - Fixed these bugs in step_to_call: + 1) the correct logging sequence is: + set logging file > set logging redirect > set logging on + 2) $SHOW_CONTEXT is now correctly restored from $_saved_ctx + - Fixed these bugs in trace_calls: + 1) the correct logging sequence is: + set logging file > set logging overwrite > + set logging redirect > set logging on + 2) removed the "clean up trace file" part, which is not needed now, + stepi output is properly redirected to /dev/null + 3) $SHOW_CONTEXT is now correctly restored from $_saved_ctx + - Fixed bug in trace_run: + 1) $SHOW_CONTEXT is now correctly restored from $_saved_ctx + - Fixed print_insn_type -- removed invalid semicolons!, wrong value checking + - Added TODO entry regarding the "u" command + - Changed name from gas_assemble to assemble_gas due to consistency + - Output from assemble and assemble_gas is now similar, because i made + both of them to use objdump, with respect to output format (AT&T|Intel). + - Whole code was checked and made more consistent, readable/maintainable. + + Version 6.2 + - Add global variables to allow user to control stack, data and code window + sizes + - Increase readability for registers + - Some corrections (hexdump, ddump, context, cfp, assemble, gas_asm, tips, + prompt) + + Version 6.1-color-user + - Took the Gentoo route and ran sed s/user/user/g + + Version 6.1-color + - Added color fixes from + http://gnurbs.blogsome.com/2006/12/22/colorizing-mamons-gdbinit/ + + Version 6.1 + - Fixed filename in step_to_call so it points to /dev/null + - Changed location of logfiles from /tmp to ~ + + Version 6 + - Added print_insn_type, get_insn_type, context-on, context-off commands + - Added trace_calls, trace_run, step_to_call commands + - Changed hook-stop so it checks $SHOW_CONTEXT variable + + Version 5 + - Added bpm, dump_bin, dump_hex, bp_alloc commands + - Added 'assemble' by elaine, 'gas_asm' by mong + - Added Tip Topics for aspiring users ;) + + Version 4 + - Added eflags-changing insns by pusillus + - Added bp, nop, null, and int3 patch commands, also hook-stop + + Version 3 + - Incorporated elaine's if/else goodness into the hex/ascii dump + + Version 2 + - Radix bugfix by elaine diff --git a/README b/README deleted file mode 100644 index 63cebfd..0000000 --- a/README +++ /dev/null @@ -1,10 +0,0 @@ -Public repo for gdbinit - -x86/x86_64 and ARM are supported simultaneously since version 8.0. - -FEEDBACK: http://reverse.put.as - reverser@put.as - -You should read the header of the script for important information regarding some Mac OS X/iOS gdb bugs. - -Have fun, -fG! diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..0c88c3c --- /dev/null +++ b/README.markdown @@ -0,0 +1,524 @@ +# dotgdb + +This project was based on [Gdbinit](https://github.com/gdbinit/Gdbinit) by +[fG!](http://reverse.put.as/) which in turn is based on work by the following +people: + + * mammon_ + * elaine + * pusillus + * mong + * zhang le + * l0kit + * truthix the cyberpunk + * gln + + +Currently there is support for the following architectures: + + * x86 + * x86-64 + * arm + * mips + + +## How do I install it? + +Clone the project from git://github.com/dholm/dotgdb.git and symbolically link +*.gdb* and *.gdbinit* into your home directory. + + +## Commands + +This section is incomplete. + +### Data + +``` + * hexdump + + Display a 16-byte hex/ASCII dump of memory starting at address ADDR. + Optional parameter is the number of lines to display if you want more than + one. + + Usage: hexdump ADDR [nr lines] +``` + +``` + * search + + Search for the given pattern beetween $start and $end address. + + Usage: search +``` + +``` + * ascii_char + + Print ASCII value of byte at address ADDR. + Print "." if the value is unprintable. + + Usage: ascii_char ADDR +``` + +``` + * hex_quad + + Print eight hexadecimal bytes starting at address ADDR. + + Usage: hex_quad ADDR +``` + + +### CPU + +``` + * context + + Print context window, i.e. regs, stack, ds:esi and disassemble cs:eip. +``` + +``` + * context-on + + Enable display of context on every program break. +``` + +``` + * context-off + + Disable display of context on every program break. +``` + +``` + * dis + + Disassemble a specified section of memory. + Default is to disassemble the function surrounding the PC (program counter) + of selected frame. + With one argument, ADDR1, the function surrounding this address is dumped. + Two arguments are taken as a range of memory to dump. + + Usage: dis +``` + +``` + * flags + + Print flags register. +``` + +``` + * eflags + + Print eflags register. +``` + +``` + * reg + + Print CPU registers. +``` + +``` + * cfn + + Change Negative/Less Than Flag. +``` + +``` + * cfc + + Change Carry Flag. +``` + +``` + * cfp + + Change Parity Flag. +``` + +``` + * cfa + + Change Auxiliary Carry Flag. +``` + +``` + * cfz + + Change Zero Flag. +``` + +``` + * cfs + + Change Sign Flag. +``` + +``` + * cft + + Change Trap Flag. +``` + +``` + * cfi + + Change Interrupt Flag. + Only privileged applications (usually the OS kernel) may modify IF. + This only applies to protected mode (real mode code may always modify IF). +``` + +``` + * cfd + + Change Direction Flag. +``` + +``` + * cfo + + Change Overflow Flag. +``` + +``` + * cfv + + Change Overflow Flag. +``` + + +### Patch + +``` + * nop + + Patch a single byte at address ADDR1, or a series of bytes between ADDR1 and + ADDR2 to a NOP instruction. + + Usage: nop ADDR1 [ADDR2] +``` + +``` + * null + + Patch a single byte at address ADDR1 to NULL (0x00), or a series of bytes + between ADDR1 and ADDR2. + + Usage: null ADDR1 [ADDR2] +``` + +``` + * assemble + + Assemble instructions using nasm. + Type a line containing "end" to indicate the end. + If an address is specified, insert/modify instructions at that address. + If no address is specified, assembled instructions are printed to stdout. + Use the pseudo instruction "org ADDR" to set the base address. +``` + +``` + * assemble_gas + + Assemble instructions to binary opcodes. Uses GNU as and objdump. + + Usage: assemble_gas +``` + +``` + * dump_hexfile + + Write a range of memory to a file in Intel ihex (hexdump) format. + The range is specified by ADDR1 and ADDR2 addresses. + + Usage: dump_hexfile FILENAME ADDR1 ADDR2 +``` + +``` + * dump_binfile + + Write a range of memory to a binary file. + The range is specified by ADDR1 and ADDR2 addresses. + + Usage: dump_binfile FILENAME ADDR1 ADDR2 +``` + +``` + * dumpmacho + + Dump the Mach-O header to a file. + You need to input the start address (use info shared command to find it). + + Usage: dumpmacho STARTADDRESS FILENAME +``` + + +### Tracing + +``` + * n + + Step one instruction, but proceed through subroutine calls. + If NUM is given, then repeat it NUM times or till program stops. + This is alias for nexti. + + Usage: n +``` + +``` + * go + + Step one instruction exactly. + If NUM is given, then repeat it NUM times or till program stops. + This is alias for stepi. + + Usage: go +``` + +``` + * init + + Run program and break on _init(). +``` + +``` + * start + + Run program and break on _start(). +``` + +``` + * sstart + + Run program and break on __libc_start_main(). + Useful for stripped executables. +``` + +``` + * main + + Run program and break on main(). +``` + +``` + * stepo + + Step over calls (interesting to bypass the ones to msgSend in Objective-C). + This function will set a temporary breakpoint on next instruction after the + call so the call will be bypassed. + You can safely use it instead nexti or n since it will single step code if + it's not a call instruction (unless you want to go into the call function). +``` + +``` + * stepoh + + Same as stepo command but uses temporary hardware breakpoints. +``` + +``` + * step_to_call + + Single step until a call instruction is found. + Stop before the call is taken. + Log is written into the file ~/gdb.txt. +``` + +``` + * trace_calls + + Create a runtime trace of the calls made by target. + Log overwrites(!) the file ~/gdb_trace_calls.txt. +``` + +``` + * trace_run + + Create a runtime trace of target. + Log overwrites(!) the file ~/gdb_trace_run.txt. +``` + +``` + * dumpjump + + Display if conditional jump will be taken or not. +``` + + +### Breakpoints + +``` + * bpl + + List all breakpoints. +``` + +``` + * bp + + Set breakpoint. + + Usage: bp LOCATION + LOCATION may be a line number, function name, or "*" and an address. + To break on a symbol you must enclose symbol name inside "". + Example: + bp "[NSControl stringValue]" + Or else you can use directly the break command (break [NSControl + stringValue]) +``` + +``` + * bpc + + Clear breakpoint. + + Usage: bpc LOCATION + LOCATION may be a line number, function name, or "*" and an address. +``` + +``` + * bpe + + Enable breakpoint with number NUM. + + Usage: bpe NUM +``` + +``` + * bpd + + Disable breakpoint with number NUM. + + Usage: bpd NUM +``` + +``` + * bpt + + Set a temporary breakpoint. + This breakpoint will be automatically deleted when hit!. + + Usage: bpt LOCATION + LOCATION may be a line number, function name, or "*" and an address. +``` + +``` + * bpm + + Set a read/write breakpoint on EXPRESSION, e.g. *address. + + Usage: bpm EXPRESSION +``` + +``` + * bhb + + Set hardware assisted breakpoint. + + Usage: bhb LOCATION + LOCATION may be a line number, function name, or "*" and an address. +``` + +``` + * bht + + Set a temporary hardware breakpoint. + This breakpoint will be automatically deleted when hit! + + Usage: bht LOCATION + LOCATION may be a line number, function name, or "*" and an address. +``` + + +### Information + +``` + * stack + + Print backtrace of the call stack, or innermost COUNT frames. + + Usage: stack +``` + +``` + * frame + + Print stack frame. +``` + +``` + * func + + Print all function names in target, or those matching REGEXP. + + Usage: func +``` + +``` + * var + + Print all global and static variable names (symbols), or those matching + REGEXP. + + Usage: var +``` + +``` + * lib + + Print shared libraries linked to target. +``` + +``` + * sig + + Print what debugger does when program gets various signals. + Specify a SIGNAL as argument to print info on that signal only. + + Usage: sig +``` + +``` + * threads + + Print threads in target. +``` + + +### Tips + +``` + * tips + + Provide a list of tips from users on various topics. +``` + +``` + * tip_patch + + Tips on patching memory and binary files. +``` + +``` + * tip_strip + + Tips on dealing with stripped binaries. +``` + +``` + * tip_syntax + + Summary of Intel and AT&T syntax differences. +``` + +``` + * tip_display + + Tips on automatically displaying values when a program stops. +``` + +### MacsBug +Type `MACSBUG_HELP` to summarize the MacsBug commands + diff --git a/gdbinit b/gdbinit deleted file mode 100644 index 3be173e..0000000 --- a/gdbinit +++ /dev/null @@ -1,3512 +0,0 @@ -# INSTALL INSTRUCTIONS: save as ~/.gdbinit -# -# DESCRIPTION: A user-friendly gdb configuration file, for x86/x86_64 and ARM platforms. -# -# REVISION : 8.0.2 (31/07/2012) -# -# CONTRIBUTORS: mammon_, elaine, pusillus, mong, zhang le, l0kit, -# truthix the cyberpunk, fG!, gln -# -# FEEDBACK: http://reverse.put.as - reverser@put.as -# -# NOTES: 'help user' in gdb will list the commands/descriptions in this file -# 'context on' now enables auto-display of context screen -# -# MAC OS X NOTES: If you are using this on Mac OS X, you must either attach gdb to a process -# or launch gdb without any options and then load the binary file you want to analyse with "exec-file" option -# If you load the binary from the command line, like $gdb binary-name, this will not work as it should -# For more information, read it here http://reverse.put.as/2008/11/28/apples-gdb-bug/ -# -# UPDATE: This bug can be fixed in gdb source. Refer to http://reverse.put.as/2009/08/10/fix-for-apples-gdb-bug-or-why-apple-forks-are-bad/ -# and http://reverse.put.as/2009/08/26/gdb-patches/ (if you want the fixed binary for i386) -# -# An updated version of the patch and binary is available at http://reverse.put.as/2011/02/21/update-to-gdb-patches-fix-a-new-bug/ -# -# iOS NOTES: iOS gdb from Cydia (and Apple's) suffer from the same OS X bug. -# If you are using this on Mac OS X or iOS, you must either attach gdb to a process -# or launch gdb without any options and then load the binary file you want to analyse with "exec-file" option -# If you load the binary from the command line, like $gdb binary-name, this will not work as it should -# For more information, read it here http://reverse.put.as/2008/11/28/apples-gdb-bug/ -# -# CHANGELOG: (older changes at the end of the file) -# -# Version 8.0.2 (31/07/2012) -# - Merge pull request from mheistermann to support local modifications in a .gdbinit.local file -# - Add a missing opcode to the stepo command -# -# Version 8.0.1 (23/04/2012) -# - Small bug fix to the attsyntax and intelsyntax commands (changing X86 flavor variable was missing) -# -# Version 8.0 (13/04/2012) -# - Merged x86/x64 and ARM versions -# - Added commands intelsyntax and attsyntax to switch between x86 disassembly flavors -# - Added new configuration variables ARM, ARMOPCODES, and X86FLAVOR -# - Code cleanups and fixes to the indentation -# - Bug fixes to some ARM related code -# - Added the dumpmacho command to memory dump the mach-o header to a file -# -# TODO: -# - -# __________________gdb options_________________ - -# set to 1 to have ARM target debugging as default, use the "arm" command to switch inside gdb -set $ARM = 0 -# set to 1 to enable 64bits target by default (32bits is the default) -set $64BITS = 0 - -if $64BITS == 1 - printf "64-bit mode is default. Use the 32bits command if your target is 32 bits.\n" - printf "Edit the $64BITS variable in your .gdbinit file to switch to default 32-bit mode.\n" -else - printf "32-bit mode is default. Use the 64bits command if your target is 64 bits.\n" - printf "Edit the $64BITS variable in your .gdbinit file to switch to default 64-bit mode.\n" -end -# set to 0 if you have problems with the colorized prompt - reported by Plouj with Ubuntu gdb 7.2 -set $COLOUREDPROMPT = 1 -# Colour the first line of the disassembly - default is green, if you want to change it search for -# SETCOLOUR1STLINE and modify it :-) -set $SETCOLOUR1STLINE = 0 -# set to 0 to remove display of objectivec messages (default is 1) -set $SHOWOBJECTIVEC = 1 -# set to 0 to remove display of cpu registers (default is 1) -set $SHOWCPUREGISTERS = 1 -# set to 1 to enable display of stack (default is 0) -set $SHOWSTACK = 0 -# set to 1 to enable display of data window (default is 0) -set $SHOWDATAWIN = 0 -# set to 0 to disable coloured display of changed registers -set $SHOWREGCHANGES = 1 -# set to 1 so skip command to execute the instruction at the new location -# by default it EIP/RIP will be modified and update the new context but not execute the instruction -set $SKIPEXECUTE = 0 -# if $SKIPEXECUTE is 1 configure the type of execution -# 1 = use stepo (do not get into calls), 0 = use stepi (step into calls) -set $SKIPSTEP = 1 -# show the ARM opcodes - change to 0 if you don't want such thing (in x/i command) -set $ARMOPCODES = 1 -# x86 disassembly flavor: 0 for Intel, 1 for AT&T -set $X86FLAVOR = 0 - -set confirm off -set verbose off - - - -set output-radix 0x10 -set input-radix 0x10 - -# These make gdb never pause in its output -set height 0 -set width 0 - -set $SHOW_CONTEXT = 1 -set $SHOW_NEST_INSN = 0 - -set $CONTEXTSIZE_STACK = 6 -set $CONTEXTSIZE_DATA = 8 -set $CONTEXTSIZE_CODE = 8 - -# __________________end gdb options_________________ -# - -if $COLOUREDPROMPT == 1 - set prompt \033[31mgdb$ \033[0m -end - -# this way anyone can have their custom prompt - argp's idea :-) -source ~/.gdbinit.local - -# Initialize these variables else comparisons will fail for colouring -# we must initialize all of them at once, 32 and 64 bits, and ARM. -set $oldrax = 0 -set $oldrbx = 0 -set $oldrcx = 0 -set $oldrdx = 0 -set $oldrsi = 0 -set $oldrdi = 0 -set $oldrbp = 0 -set $oldrsp = 0 -set $oldr8 = 0 -set $oldr9 = 0 -set $oldr10 = 0 -set $oldr11 = 0 -set $oldr12 = 0 -set $oldr13 = 0 -set $oldr14 = 0 -set $oldr15 = 0 -set $oldeax = 0 -set $oldebx = 0 -set $oldecx = 0 -set $oldedx = 0 -set $oldesi = 0 -set $oldedi = 0 -set $oldebp = 0 -set $oldesp = 0 -set $oldr0 = 0 -set $oldr1 = 0 -set $oldr2 = 0 -set $oldr3 = 0 -set $oldr4 = 0 -set $oldr5 = 0 -set $oldr6 = 0 -set $oldr7 = 0 -set $oldsp = 0 -set $oldlr = 0 - -# used by ptraceme/rptraceme -set $ptrace_bpnum = 0 - -# ______________window size control___________ -define contextsize-stack - if $argc != 1 - help contextsize-stack - else - set $CONTEXTSIZE_STACK = $arg0 - end -end -document contextsize-stack -Set stack dump window size to NUM lines. -Usage: contextsize-stack NUM -end - - -define contextsize-data - if $argc != 1 - help contextsize-data - else - set $CONTEXTSIZE_DATA = $arg0 - end -end -document contextsize-data -Set data dump window size to NUM lines. -Usage: contextsize-data NUM -end - - -define contextsize-code - if $argc != 1 - help contextsize-code - else - set $CONTEXTSIZE_CODE = $arg0 - end -end -document contextsize-code -Set code window size to NUM lines. -Usage: contextsize-code NUM -end - - -# _____________breakpoint aliases_____________ -define bpl - info breakpoints -end -document bpl -List all breakpoints. -end - - -define bp - if $argc != 1 - help bp - else - break $arg0 - end -end -document bp -Set breakpoint. -Usage: bp LOCATION -LOCATION may be a line number, function name, or "*" and an address. -To break on a symbol you must enclose symbol name inside "". -Example: -bp "[NSControl stringValue]" -Or else you can use directly the break command (break [NSControl stringValue]) -end - - -define bpc - if $argc != 1 - help bpc - else - clear $arg0 - end -end -document bpc -Clear breakpoint. -Usage: bpc LOCATION -LOCATION may be a line number, function name, or "*" and an address. -end - - -define bpe - if $argc != 1 - help bpe - else - enable $arg0 - end -end -document bpe -Enable breakpoint with number NUM. -Usage: bpe NUM -end - - -define bpd - if $argc != 1 - help bpd - else - disable $arg0 - end -end -document bpd -Disable breakpoint with number NUM. -Usage: bpd NUM -end - - -define bpt - if $argc != 1 - help bpt - else - tbreak $arg0 - end -end -document bpt -Set a temporary breakpoint. -This breakpoint will be automatically deleted when hit!. -Usage: bpt LOCATION -LOCATION may be a line number, function name, or "*" and an address. -end - - -define bpm - if $argc != 1 - help bpm - else - awatch $arg0 - end -end -document bpm -Set a read/write breakpoint on EXPRESSION, e.g. *address. -Usage: bpm EXPRESSION -end - - -define bhb - if $argc != 1 - help bhb - else - hb $arg0 - end -end -document bhb -Set hardware assisted breakpoint. -Usage: bhb LOCATION -LOCATION may be a line number, function name, or "*" and an address. -end - - -define bht - if $argc != 1 - help bht - else - thbreak $arg0 - end -end -document bht -Set a temporary hardware breakpoint. -This breakpoint will be automatically deleted when hit! -Usage: bht LOCATION -LOCATION may be a line number, function name, or "*" and an address. -end - - -# ______________process information____________ -define argv - show args -end -document argv -Print program arguments. -end - - -define stack - if $argc == 0 - info stack - end - if $argc == 1 - info stack $arg0 - end - if $argc > 1 - help stack - end -end -document stack -Print backtrace of the call stack, or innermost COUNT frames. -Usage: stack -end - - -define frame - info frame - info args - info locals -end -document frame -Print stack frame. -end - - -define flagsarm -# conditional flags are -# negative/less than (N), bit 31 of CPSR -# zero (Z), bit 30 -# Carry/Borrow/Extend (C), bit 29 -# Overflow (V), bit 28 - # negative/less than (N), bit 31 of CPSR - if ($cpsr->n & 1) - printf "N " - set $_n_flag = 1 - else - printf "n " - set $_n_flag = 0 - end - # zero (Z), bit 30 - if ($cpsr->z & 1) - printf "Z " - set $_z_flag = 1 - else - printf "z " - set $_z_flag = 0 - end - # Carry/Borrow/Extend (C), bit 29 - if ($cpsr->c & 1) - printf "C " - set $_c_flag = 1 - else - printf "c " - set $_c_flag = 0 - end - # Overflow (V), bit 28 - if ($cpsr->v & 1) - printf "V " - set $_v_flag = 1 - else - printf "v " - set $_v_flag = 0 - end - # Sticky overflow (Q), bit 27 - if ($cpsr->q & 1) - printf "Q " - set $_q_flag = 1 - else - printf "q " - set $_q_flag = 0 - end - # Java state bit (J), bit 24 - # When T=1: - # J = 0 The processor is in Thumb state. - # J = 1 The processor is in ThumbEE state. - if ($cpsr->j & 1) - printf "J " - set $_j_flag = 1 - else - printf "j " - set $_j_flag = 0 - end - # Data endianness bit (E), bit 9 - if ($cpsr->e & 1) - printf "E " - set $_e_flag = 1 - else - printf "e " - set $_e_flag = 0 - end - # Imprecise abort disable bit (A), bit 8 - # The A bit is set to 1 automatically. It is used to disable imprecise data aborts. - # It might not be writable in the Nonsecure state if the AW bit in the SCR register is reset. - if ($cpsr->a & 1) - printf "A " - set $_a_flag = 1 - else - printf "a " - set $_a_flag = 0 - end - # IRQ disable bit (I), bit 7 - # When the I bit is set to 1, IRQ interrupts are disabled. - if ($cpsr->i & 1) - printf "I " - set $_i_flag = 1 - else - printf "i " - set $_i_flag = 0 - end - # FIQ disable bit (F), bit 6 - # When the F bit is set to 1, FIQ interrupts are disabled. - # FIQ can be nonmaskable in the Nonsecure state if the FW bit in SCR register is reset. - if ($cpsr->f & 1) - printf "F " - set $_f_flag = 1 - else - printf "f " - set $_f_flag = 0 - end - # Thumb state bit (F), bit 5 - # if 1 then the processor is executing in Thumb state or ThumbEE state depending on the J bit - if ($cpsr->t & 1) - printf "T " - set $_t_flag = 1 - else - printf "t " - set $_t_flag = 0 - end - # TODO: GE bit ? -end -document flagsarm -Auxiliary function to set ARM cpu flags. -end - - -define flagsx86 - # OF (overflow) flag - if (($eflags >> 0xB) & 1) - printf "O " - set $_of_flag = 1 - else - printf "o " - set $_of_flag = 0 - end - # DF (direction) flag - if (($eflags >> 0xA) & 1) - printf "D " - else - printf "d " - end - # IF (interrupt enable) flag - if (($eflags >> 9) & 1) - printf "I " - else - printf "i " - end - # TF (trap) flag - if (($eflags >> 8) & 1) - printf "T " - else - printf "t " - end - # SF (sign) flag - if (($eflags >> 7) & 1) - printf "S " - set $_sf_flag = 1 - else - printf "s " - set $_sf_flag = 0 - end - # ZF (zero) flag - if (($eflags >> 6) & 1) - printf "Z " - set $_zf_flag = 1 - else - printf "z " - set $_zf_flag = 0 - end - # AF (adjust) flag - if (($eflags >> 4) & 1) - printf "A " - else - printf "a " - end - # PF (parity) flag - if (($eflags >> 2) & 1) - printf "P " - set $_pf_flag = 1 - else - printf "p " - set $_pf_flag = 0 - end - # CF (carry) flag - if ($eflags & 1) - printf "C " - set $_cf_flag = 1 - else - printf "c " - set $_cf_flag = 0 - end - printf "\n" -end -document flagsx86 -Auxiliary function to set X86/X64 cpu flags. -end - - -define flags - # call the auxiliary functions based on target cpu - if $ARM == 1 - flagsarm - else - flagsx86 - end -end -document flags -Print flags register. -end - - -define eflags - if $ARM == 1 - printf " N <%d> Z <%d> C <%d> V <%d>",\ - ($cpsr->n & 1), ($cpsr->z & 1), \ - ($cpsr->c & 1), ($cpsr->v & 1) - printf " Q <%d> J <%d> GE <%d> E <%d> A <%d>",\ - ($cpsr->q & 1), ($cpsr->j & 1),\ - ($cpsr->ge), ($cpsr->e & 1), ($cpsr->a & 1) - printf " I <%d> F <%d> T <%d> \n",\ - ($cpsr->i & 1), ($cpsr->f & 1), \ - ($cpsr->t & 1) - else - printf " OF <%d> DF <%d> IF <%d> TF <%d>",\ - (($eflags >> 0xB) & 1), (($eflags >> 0xA) & 1), \ - (($eflags >> 9) & 1), (($eflags >> 8) & 1) - printf " SF <%d> ZF <%d> AF <%d> PF <%d> CF <%d>\n",\ - (($eflags >> 7) & 1), (($eflags >> 6) & 1),\ - (($eflags >> 4) & 1), (($eflags >> 2) & 1), ($eflags & 1) - printf " ID <%d> VIP <%d> VIF <%d> AC <%d>",\ - (($eflags >> 0x15) & 1), (($eflags >> 0x14) & 1), \ - (($eflags >> 0x13) & 1), (($eflags >> 0x12) & 1) - printf " VM <%d> RF <%d> NT <%d> IOPL <%d>\n",\ - (($eflags >> 0x11) & 1), (($eflags >> 0x10) & 1),\ - (($eflags >> 0xE) & 1), (($eflags >> 0xC) & 3) - end -end -document eflags -Print eflags register. -end - - -define cpsr - eflags -end -document cpsr -Print cpsr register. -end - -define regarm - printf " " - echo \033[32m - printf "R0:" - if ($r0 != $oldr0 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r0 - - echo \033[32m - printf "R1:" - if ($r1 != $oldr1 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r1 - - echo \033[32m - printf "R2:" - if ($r2 != $oldr2 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r2 - - echo \033[32m - printf "R3:" - if ($r3 != $oldr3 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X\n", $r3 - printf " " - - echo \033[32m - printf "R4:" - if ($r4 != $oldr4 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r4 - - echo \033[32m - printf "R5:" - if ($r5 != $oldr5 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r5 - - echo \033[32m - printf "R6:" - if ($r6 != $oldr6 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r6 - - echo \033[32m - printf "R7:" - if ($r7 != $oldr7 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X\n", $r7 - printf " " - - echo \033[32m - printf "R8:" - if ($r8 != $oldr8 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r8 - - echo \033[32m - printf "R9:" - if ($r9 != $oldr9 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r9 - - echo \033[32m - printf "R10:" - if ($r10 != $oldr10 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r10 - - echo \033[32m - printf "R11:" - if ($r11 != $oldr11 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $r11 - dumpjump - printf "\n" - echo \033[32m - printf " R12:" - if ($r12 != $oldr12 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X", $r12 - printf " " - echo \033[32m - printf "SP:" - if ($sp != $oldsp && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $sp - - echo \033[32m - printf "LR:" - if ($lr != $oldlr && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $lr - - echo \033[32m - printf "PC:" - echo \033[0m - printf " 0x%08X ", $pc - echo \033[1m\033[4m\033[31m - flags - echo \033[0m - printf "\n" -end -document regarm -Auxiliary function to display ARM registers. -end - -define regx64 - # 64bits stuff - printf " " - # RAX - echo \033[32m - printf "RAX:" - if ($rax != $oldrax && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rax - # RBX - echo \033[32m - printf "RBX:" - if ($rbx != $oldrbx && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rbx - # RCX - echo \033[32m - printf "RCX:" - if ($rcx != $oldrcx && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rcx - # RDX - echo \033[32m - printf "RDX:" - if ($rdx != $oldrdx && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rdx - echo \033[1m\033[4m\033[31m - flags - echo \033[0m - printf " " - # RSI - echo \033[32m - printf "RSI:" - if ($rsi != $oldrsi && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rsi - # RDI - echo \033[32m - printf "RDI:" - if ($rdi != $oldrdi && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rdi - # RBP - echo \033[32m - printf "RBP:" - if ($rbp != $oldrbp && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rbp - # RSP - echo \033[32m - printf "RSP:" - if ($rsp != $oldrsp && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $rsp - echo \033[32m - printf "RIP:" - echo \033[0m - printf " 0x%016lX\n ", $rip - # R8 - echo \033[32m - printf "R8 :" - if ($r8 != $oldr8 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r8 - # R9 - echo \033[32m - printf "R9 :" - if ($r9 != $oldr9 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r9 - # R10 - echo \033[32m - printf "R10:" - if ($r10 != $oldr10 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r10 - # R11 - echo \033[32m - printf "R11:" - if ($r11 != $oldr11 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r11 - # R12 - echo \033[32m - printf "R12:" - if ($r12 != $oldr12 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX\n ", $r12 - # R13 - echo \033[32m - printf "R13:" - if ($r13 != $oldr13 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r13 - # R14 - echo \033[32m - printf "R14:" - if ($r14 != $oldr14 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX ", $r14 - # R15 - echo \033[32m - printf "R15:" - if ($r15 != $oldr15 && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%016lX\n ", $r15 - echo \033[32m - printf "CS:" - echo \033[0m - printf " %04X ", $cs - echo \033[32m - printf "DS:" - echo \033[0m - printf " %04X ", $ds - echo \033[32m - printf "ES:" - echo \033[0m - printf " %04X ", $es - echo \033[32m - printf "FS:" - echo \033[0m - printf " %04X ", $fs - echo \033[32m - printf "GS:" - echo \033[0m - printf " %04X ", $gs - echo \033[32m - printf "SS:" - echo \033[0m - printf " %04X", $ss - echo \033[0m -end -document regx64 -Auxiliary function to display X86_64 registers. -end - - -define regx86 - printf " " - # EAX - echo \033[32m - printf "EAX:" - if ($eax != $oldeax && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $eax - # EBX - echo \033[32m - printf "EBX:" - if ($ebx != $oldebx && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $ebx - # ECX - echo \033[32m - printf "ECX:" - if ($ecx != $oldecx && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $ecx - # EDX - if ($edx != $oldedx && $SHOWREGCHANGES == 1) - echo \033[32m - printf "EDX:" - echo \033[31m - printf " 0x%08X ", $edx - else - echo \033[32m - printf "EDX:" - echo \033[0m - printf " 0x%08X ", $edx - end - echo \033[1m\033[4m\033[31m - flags - echo \033[0m - printf " " - # ESI - echo \033[32m - printf "ESI:" - if ($esi != $oldesi && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $esi - # EDI - echo \033[32m - printf "EDI:" - if ($edi != $oldedi && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $edi - # EBP - echo \033[32m - printf "EBP:" - if ($ebp != $oldebp && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $ebp - # ESP - echo \033[32m - printf "ESP:" - if ($esp != $oldesp && $SHOWREGCHANGES == 1) - echo \033[31m - else - echo \033[0m - end - printf " 0x%08X ", $esp - # EIP - echo \033[32m - printf "EIP:" - echo \033[0m - printf " 0x%08X\n ", $eip - echo \033[32m - printf "CS:" - echo \033[0m - printf " %04X ", $cs - echo \033[32m - printf "DS:" - echo \033[0m - printf " %04X ", $ds - echo \033[32m - printf "ES:" - echo \033[0m - printf " %04X ", $es - echo \033[32m - printf "FS:" - echo \033[0m - printf " %04X ", $fs - echo \033[32m - printf "GS:" - echo \033[0m - printf " %04X ", $gs - echo \033[32m - printf "SS:" - echo \033[0m - printf " %04X", $ss - echo \033[0m -end -document regx86 -Auxiliary function to display X86 registers. -end - - -define reg - if $ARM == 1 - regarm - if ($SHOWREGCHANGES == 1) - set $oldr0 = $r0 - set $oldr1 = $r1 - set $oldr2 = $r2 - set $oldr3 = $r3 - set $oldr4 = $r4 - set $oldr5 = $r5 - set $oldr6 = $r6 - set $oldr7 = $r7 - set $oldr8 = $r8 - set $oldr9 = $r9 - set $oldr10 = $r10 - set $oldr11 = $r11 - set $oldr12 = $r12 - set $oldsp = $sp - set $oldlr = $lr - end - else - if ($64BITS == 1) - regx64 - else - regx86 - end - # call smallregisters - smallregisters - # display conditional jump routine - if ($64BITS == 1) - printf "\t\t\t\t" - end - dumpjump - printf "\n" - if ($SHOWREGCHANGES == 1) - if ($64BITS == 1) - set $oldrax = $rax - set $oldrbx = $rbx - set $oldrcx = $rcx - set $oldrdx = $rdx - set $oldrsi = $rsi - set $oldrdi = $rdi - set $oldrbp = $rbp - set $oldrsp = $rsp - set $oldr8 = $r8 - set $oldr9 = $r9 - set $oldr10 = $r10 - set $oldr11 = $r11 - set $oldr12 = $r12 - set $oldr13 = $r13 - set $oldr14 = $r14 - set $oldr15 = $r15 - else - set $oldeax = $eax - set $oldebx = $ebx - set $oldecx = $ecx - set $oldedx = $edx - set $oldesi = $esi - set $oldedi = $edi - set $oldebp = $ebp - set $oldesp = $esp - end - end - end -end -document reg -Print CPU registers. -end - - -define smallregisters - if ($64BITS == 1) - #64bits stuff - # from rax - set $eax = $rax & 0xffffffff - set $ax = $rax & 0xffff - set $al = $ax & 0xff - set $ah = $ax >> 8 - # from rbx - set $ebx = $rbx & 0xffffffff - set $bx = $rbx & 0xffff - set $bl = $bx & 0xff - set $bh = $bx >> 8 - # from rcx - set $ecx = $rcx & 0xffffffff - set $cx = $rcx & 0xffff - set $cl = $cx & 0xff - set $ch = $cx >> 8 - # from rdx - set $edx = $rdx & 0xffffffff - set $dx = $rdx & 0xffff - set $dl = $dx & 0xff - set $dh = $dx >> 8 - # from rsi - set $esi = $rsi & 0xffffffff - set $si = $rsi & 0xffff - # from rdi - set $edi = $rdi & 0xffffffff - set $di = $rdi & 0xffff - #32 bits stuff - else - # from eax - set $ax = $eax & 0xffff - set $al = $ax & 0xff - set $ah = $ax >> 8 - # from ebx - set $bx = $ebx & 0xffff - set $bl = $bx & 0xff - set $bh = $bx >> 8 - # from ecx - set $cx = $ecx & 0xffff - set $cl = $cx & 0xff - set $ch = $cx >> 8 - # from edx - set $dx = $edx & 0xffff - set $dl = $dx & 0xff - set $dh = $dx >> 8 - # from esi - set $si = $esi & 0xffff - # from edi - set $di = $edi & 0xffff - end -end -document smallregisters -Create the 16 and 8 bit cpu registers (gdb doesn't have them by default). -And 32bits if we are dealing with 64bits binaries. -end - - -define func - if $argc == 0 - info functions - end - if $argc == 1 - info functions $arg0 - end - if $argc > 1 - help func - end -end -document func -Print all function names in target, or those matching REGEXP. -Usage: func -end - - -define var - if $argc == 0 - info variables - end - if $argc == 1 - info variables $arg0 - end - if $argc > 1 - help var - end -end -document var -Print all global and static variable names (symbols), or those matching REGEXP. -Usage: var -end - - -define lib - info sharedlibrary -end -document lib -Print shared libraries linked to target. -end - - -define sig - if $argc == 0 - info signals - end - if $argc == 1 - info signals $arg0 - end - if $argc > 1 - help sig - end -end -document sig -Print what debugger does when program gets various signals. -Specify a SIGNAL as argument to print info on that signal only. -Usage: sig -end - - -define threads - info threads -end -document threads -Print threads in target. -end - - -define dis - if $argc == 0 - disassemble - end - if $argc == 1 - disassemble $arg0 - end - if $argc == 2 - disassemble $arg0 $arg1 - end - if $argc > 2 - help dis - end -end -document dis -Disassemble a specified section of memory. -Default is to disassemble the function surrounding the PC (program counter) of selected frame. -With one argument, ADDR1, the function surrounding this address is dumped. -Two arguments are taken as a range of memory to dump. -Usage: dis -end - - -# __________hex/ascii dump an address_________ -define ascii_char - if $argc != 1 - help ascii_char - else - # thanks elaine :) - set $_c = *(unsigned char *)($arg0) - if ($_c < 0x20 || $_c > 0x7E) - printf "." - else - printf "%c", $_c - end - end -end -document ascii_char -Print ASCII value of byte at address ADDR. -Print "." if the value is unprintable. -Usage: ascii_char ADDR -end - - -define hex_quad - if $argc != 1 - help hex_quad - else - printf "%02X %02X %02X %02X %02X %02X %02X %02X", \ - *(unsigned char*)($arg0), *(unsigned char*)($arg0 + 1), \ - *(unsigned char*)($arg0 + 2), *(unsigned char*)($arg0 + 3), \ - *(unsigned char*)($arg0 + 4), *(unsigned char*)($arg0 + 5), \ - *(unsigned char*)($arg0 + 6), *(unsigned char*)($arg0 + 7) - end -end -document hex_quad -Print eight hexadecimal bytes starting at address ADDR. -Usage: hex_quad ADDR -end - - -define hexdump - if $argc == 1 - hexdump_aux $arg0 - else - if $argc == 2 - set $_count = 0 - while ($_count < $arg1) - set $_i = ($_count * 0x10) - hexdump_aux $data_addr+$_i - set $_count++ - end - else - help hexdump - end - end -end -document hexdump -Display a 16-byte hex/ASCII dump of memory starting at address ADDR. -Optional parameter is the number of lines to display if you want more than one. -Usage: hexdump ADDR [nr lines] -end - - -define hexdump_aux - if $argc != 1 - help hexdump_aux - else - echo \033[1m - if ($64BITS == 1) - printf "0x%016lX : ", $arg0 - else - printf "0x%08X : ", $arg0 - end - echo \033[0m - hex_quad $arg0 - echo \033[1m - printf " - " - echo \033[0m - hex_quad $arg0+8 - printf " " - echo \033[1m - ascii_char $arg0+0x0 - ascii_char $arg0+0x1 - ascii_char $arg0+0x2 - ascii_char $arg0+0x3 - ascii_char $arg0+0x4 - ascii_char $arg0+0x5 - ascii_char $arg0+0x6 - ascii_char $arg0+0x7 - ascii_char $arg0+0x8 - ascii_char $arg0+0x9 - ascii_char $arg0+0xA - ascii_char $arg0+0xB - ascii_char $arg0+0xC - ascii_char $arg0+0xD - ascii_char $arg0+0xE - ascii_char $arg0+0xF - echo \033[0m - printf "\n" - end -end -document hexdump_aux -Display a 16-byte hex/ASCII dump of memory at address ADDR. -Usage: hexdump_aux ADDR -end - - -# _______________data window__________________ -define ddump - if $argc != 1 - help ddump - else - echo \033[34m - if ($64BITS == 1) - printf "[0x%04X:0x%016lX]", $ds, $data_addr - else - printf "[0x%04X:0x%08X]", $ds, $data_addr - end - echo \033[34m - printf "------------------------" - printf "-------------------------------" - if ($64BITS == 1) - printf "-------------------------------------" - end - echo \033[1;34m - printf "[data]\n" - echo \033[0m - set $_count = 0 - while ($_count < $arg0) - set $_i = ($_count * 0x10) - hexdump $data_addr+$_i - set $_count++ - end - end -end -document ddump -Display NUM lines of hexdump for address in $data_addr global variable. -Usage: ddump NUM -end - - -define dd - if $argc != 1 - help dd - else - set $data_addr = $arg0 - ddump 0x10 - end -end -document dd -Display 16 lines of a hex dump of address starting at ADDR. -Usage: dd ADDR -end - - -define datawin - if $ARM == 1 - if ((($r0 >> 0x18) == 0x40) || (($r0 >> 0x18) == 0x08) || (($r0 >> 0x18) == 0xBF)) - set $data_addr = $r0 - else - if ((($r1 >> 0x18) == 0x40) || (($r1 >> 0x18) == 0x08) || (($r1 >> 0x18) == 0xBF)) - set $data_addr = $r1 - else - if ((($r2 >> 0x18) == 0x40) || (($r2 >> 0x18) == 0x08) || (($r2 >> 0x18) == 0xBF)) - set $data_addr = $r2 - else - set $data_addr = $sp - end - end - end -################################# X86 - else - if ($64BITS == 1) - if ((($rsi >> 0x18) == 0x40) || (($rsi >> 0x18) == 0x08) || (($rsi >> 0x18) == 0xBF)) - set $data_addr = $rsi - else - if ((($rdi >> 0x18) == 0x40) || (($rdi >> 0x18) == 0x08) || (($rdi >> 0x18) == 0xBF)) - set $data_addr = $rdi - else - if ((($rax >> 0x18) == 0x40) || (($rax >> 0x18) == 0x08) || (($rax >> 0x18) == 0xBF)) - set $data_addr = $rax - else - set $data_addr = $rsp - end - end - end - else - if ((($esi >> 0x18) == 0x40) || (($esi >> 0x18) == 0x08) || (($esi >> 0x18) == 0xBF)) - set $data_addr = $esi - else - if ((($edi >> 0x18) == 0x40) || (($edi >> 0x18) == 0x08) || (($edi >> 0x18) == 0xBF)) - set $data_addr = $edi - else - if ((($eax >> 0x18) == 0x40) || (($eax >> 0x18) == 0x08) || (($eax >> 0x18) == 0xBF)) - set $data_addr = $eax - else - set $data_addr = $esp - end - end - end - end - end - ddump $CONTEXTSIZE_DATA -end -document datawin -Display valid address from one register in data window. -Registers to choose are: esi, edi, eax, or esp. -end - - -################################ -##### ALERT ALERT ALERT ######## -################################ -# Huge mess going here :) HAHA # -################################ -define dumpjump - if $ARM == 1 - ## Most ARM and Thumb instructions are conditional! - # each instruction is 32 bits long - # 4 bits are for condition codes (16 in total) (bits 31:28 in ARM contain the condition or 1111 if instruction is unconditional) - # 2x4 bits for destination and first operand registers - # one for the set-status flag - # an assorted number for other stuff - # 12 bits for any immediate value - # $_t_flag == 0 => ARM mode - # $_t_flag == 1 => Thumb or ThumbEE - if ($cpsr->t & 1) - set $_t_flag = 1 - else - set $_t_flag = 0 - end - - if $_t_flag == 0 - set $_lastbyte = *(unsigned char *)($pc+3) - #set $_bit31 = ($_lastbyte >> 7) & 1 - #set $_bit30 = ($_lastbyte >> 6) & 1 - #set $_bit29 = ($_lastbyte >> 5) & 1 - #set $_bit28 = ($_lastbyte >> 4) & 1 - set $_conditional = $_lastbyte >> 4 - dumpjumphelper - else - # if bits 15-12 (opcode in Thumb instructions) are equal to 1 1 0 1 (0xD) then we have a conditional branch - # bits 11-8 for the conditional execution code (check ARMv7 manual A8.3) - if ( (*(unsigned char *)($pc+1) >> 4) == 0xD ) - set $_conditional = *(unsigned char *)($pc+1) ^ 0xD0 - dumpjumphelper - end - end -##################### X86 - else - ## grab the first two bytes from the instruction so we can determine the jump instruction - set $_byte1 = *(unsigned char *)$pc - set $_byte2 = *(unsigned char *)($pc+1) - ## and now check what kind of jump we have (in case it's a jump instruction) - ## I changed the flags routine to save the flag into a variable, so we don't need to repeat the process :) (search for "define flags") - - ## opcode 0x77: JA, JNBE (jump if CF=0 and ZF=0) - ## opcode 0x0F87: JNBE, JA - if ( ($_byte1 == 0x77) || ($_byte1 == 0x0F && $_byte2 == 0x87) ) - # cf=0 and zf=0 - if ($_cf_flag == 0 && $_zf_flag == 0) - echo \033[31m - printf " Jump is taken (c=0 and z=0)" - else - # cf != 0 or zf != 0 - echo \033[31m - printf " Jump is NOT taken (c!=0 or z!=0)" - end - end - ## opcode 0x73: JAE, JNB, JNC (jump if CF=0) - ## opcode 0x0F83: JNC, JNB, JAE (jump if CF=0) - if ( ($_byte1 == 0x73) || ($_byte1 == 0x0F && $_byte2 == 0x83) ) - # cf=0 - if ($_cf_flag == 0) - echo \033[31m - printf " Jump is taken (c=0)" - else - # cf != 0 - echo \033[31m - printf " Jump is NOT taken (c!=0)" - end - end - ## opcode 0x72: JB, JC, JNAE (jump if CF=1) - ## opcode 0x0F82: JNAE, JB, JC - if ( ($_byte1 == 0x72) || ($_byte1 == 0x0F && $_byte2 == 0x82) ) - # cf=1 - if ($_cf_flag == 1) - echo \033[31m - printf " Jump is taken (c=1)" - else - # cf != 1 - echo \033[31m - printf " Jump is NOT taken (c!=1)" - end - end - ## opcode 0x76: JBE, JNA (jump if CF=1 or ZF=1) - ## opcode 0x0F86: JBE, JNA - if ( ($_byte1 == 0x76) || ($_byte1 == 0x0F && $_byte2 == 0x86) ) - # cf=1 or zf=1 - if (($_cf_flag == 1) || ($_zf_flag == 1)) - echo \033[31m - printf " Jump is taken (c=1 or z=1)" - else - # cf != 1 or zf != 1 - echo \033[31m - printf " Jump is NOT taken (c!=1 or z!=1)" - end - end - ## opcode 0xE3: JCXZ, JECXZ, JRCXZ (jump if CX=0 or ECX=0 or RCX=0) - if ($_byte1 == 0xE3) - # cx=0 or ecx=0 - if (($ecx == 0) || ($cx == 0)) - echo \033[31m - printf " Jump is taken (cx=0 or ecx=0)" - else - echo \033[31m - printf " Jump is NOT taken (cx!=0 or ecx!=0)" - end - end - ## opcode 0x74: JE, JZ (jump if ZF=1) - ## opcode 0x0F84: JZ, JE, JZ (jump if ZF=1) - if ( ($_byte1 == 0x74) || ($_byte1 == 0x0F && $_byte2 == 0x84) ) - # ZF = 1 - if ($_zf_flag == 1) - echo \033[31m - printf " Jump is taken (z=1)" - else - # ZF = 0 - echo \033[31m - printf " Jump is NOT taken (z!=1)" - end - end - ## opcode 0x7F: JG, JNLE (jump if ZF=0 and SF=OF) - ## opcode 0x0F8F: JNLE, JG (jump if ZF=0 and SF=OF) - if ( ($_byte1 == 0x7F) || ($_byte1 == 0x0F && $_byte2 == 0x8F) ) - # zf = 0 and sf = of - if (($_zf_flag == 0) && ($_sf_flag == $_of_flag)) - echo \033[31m - printf " Jump is taken (z=0 and s=o)" - else - echo \033[31m - printf " Jump is NOT taken (z!=0 or s!=o)" - end - end - ## opcode 0x7D: JGE, JNL (jump if SF=OF) - ## opcode 0x0F8D: JNL, JGE (jump if SF=OF) - if ( ($_byte1 == 0x7D) || ($_byte1 == 0x0F && $_byte2 == 0x8D) ) - # sf = of - if ($_sf_flag == $_of_flag) - echo \033[31m - printf " Jump is taken (s=o)" - else - echo \033[31m - printf " Jump is NOT taken (s!=o)" - end - end - ## opcode: 0x7C: JL, JNGE (jump if SF != OF) - ## opcode: 0x0F8C: JNGE, JL (jump if SF != OF) - if ( ($_byte1 == 0x7C) || ($_byte1 == 0x0F && $_byte2 == 0x8C) ) - # sf != of - if ($_sf_flag != $_of_flag) - echo \033[31m - printf " Jump is taken (s!=o)" - else - echo \033[31m - printf " Jump is NOT taken (s=o)" - end - end - ## opcode 0x7E: JLE, JNG (jump if ZF = 1 or SF != OF) - ## opcode 0x0F8E: JNG, JLE (jump if ZF = 1 or SF != OF) - if ( ($_byte1 == 0x7E) || ($_byte1 == 0x0F && $_byte2 == 0x8E) ) - # zf = 1 or sf != of - if (($_zf_flag == 1) || ($_sf_flag != $_of_flag)) - echo \033[31m - printf " Jump is taken (zf=1 or sf!=of)" - else - echo \033[31m - printf " Jump is NOT taken (zf!=1 or sf=of)" - end - end - ## opcode 0x75: JNE, JNZ (jump if ZF = 0) - ## opcode 0x0F85: JNE, JNZ (jump if ZF = 0) - if ( ($_byte1 == 0x75) || ($_byte1 == 0x0F && $_byte2 == 0x85) ) - # ZF = 0 - if ($_zf_flag == 0) - echo \033[31m - printf " Jump is taken (z=0)" - else - # ZF = 1 - echo \033[31m - printf " Jump is NOT taken (z!=0)" - end - end - ## opcode 0x71: JNO (OF = 0) - ## opcode 0x0F81: JNO (OF = 0) - if ( ($_byte1 == 0x71) || ($_byte1 == 0x0F && $_byte2 == 0x81) ) - # OF = 0 - if ($_of_flag == 0) - echo \033[31m - printf " Jump is taken (o=0)" - else - # OF != 0 - echo \033[31m - printf " Jump is NOT taken (o!=0)" - end - end - ## opcode 0x7B: JNP, JPO (jump if PF = 0) - ## opcode 0x0F8B: JPO (jump if PF = 0) - if ( ($_byte1 == 0x7B) || ($_byte1 == 0x0F && $_byte2 == 0x8B) ) - # PF = 0 - if ($_pf_flag == 0) - echo \033[31m - printf " Jump is NOT taken (p=0)" - else - # PF != 0 - echo \033[31m - printf " Jump is taken (p!=0)" - end - end - ## opcode 0x79: JNS (jump if SF = 0) - ## opcode 0x0F89: JNS (jump if SF = 0) - if ( ($_byte1 == 0x79) || ($_byte1 == 0x0F && $_byte2 == 0x89) ) - # SF = 0 - if ($_sf_flag == 0) - echo \033[31m - printf " Jump is taken (s=0)" - else - # SF != 0 - echo \033[31m - printf " Jump is NOT taken (s!=0)" - end - end - ## opcode 0x70: JO (jump if OF=1) - ## opcode 0x0F80: JO (jump if OF=1) - if ( ($_byte1 == 0x70) || ($_byte1 == 0x0F && $_byte2 == 0x80) ) - # OF = 1 - if ($_of_flag == 1) - echo \033[31m - printf " Jump is taken (o=1)" - else - # OF != 1 - echo \033[31m - printf " Jump is NOT taken (o!=1)" - end - end - ## opcode 0x7A: JP, JPE (jump if PF=1) - ## opcode 0x0F8A: JP, JPE (jump if PF=1) - if ( ($_byte1 == 0x7A) || ($_byte1 == 0x0F && $_byte2 == 0x8A) ) - # PF = 1 - if ($_pf_flag == 1) - echo \033[31m - printf " Jump is taken (p=1)" - else - # PF = 0 - echo \033[31m - printf " Jump is NOT taken (p!=1)" - end - end - ## opcode 0x78: JS (jump if SF=1) - ## opcode 0x0F88: JS (jump if SF=1) - if ( ($_byte1 == 0x78) || ($_byte1 == 0x0F && $_byte2 == 0x88) ) - # SF = 1 - if ($_sf_flag == 1) - echo \033[31m - printf " Jump is taken (s=1)" - else - # SF != 1 - echo \033[31m - printf " Jump is NOT taken (s!=1)" - end - end - end -end -document dumpjump -Display if conditional jump will be taken or not. -end - -define dumpjumphelper - # 0000 - EQ: Z == 1 - if ($_conditional == 0x0) - if ($_z_flag == 1) - echo \033[31m - printf " Jump is taken (z==1)" - else - echo \033[31m - printf " Jump is NOT taken (z!=1)" - end - end - # 0001 - NE: Z == 0 - if ($_conditional == 0x1) - if ($_z_flag == 0) - echo \033[31m - printf " Jump is taken (z==0)" - else - echo \033[31m - printf " Jump is NOT taken (z!=0)" - end - end - # 0010 - CS: C == 1 - if ($_conditional == 0x2) - if ($_c_flag == 1) - echo \033[31m - printf " Jump is taken (c==1)" - else - echo \033[31m - printf " Jump is NOT taken (c!=1)" - end - end - # 0011 - CC: C == 0 - if ($_conditional == 0x3) - if ($_c_flag == 0) - echo \033[31m - printf " Jump is taken (c==0)" - else - echo \033[31m - printf " Jump is NOT taken (c!=0)" - end - end - # 0100 - MI: N == 1 - if ($_conditional == 0x4) - if ($_n_flag == 1) - echo \033[31m - printf " Jump is taken (n==1)" - else - echo \033[31m - printf " Jump is NOT taken (n!=1)" - end - end - # 0101 - PL: N == 0 - if ($_conditional == 0x5) - if ($_n_flag == 0) - echo \033[31m - printf " Jump is taken (n==0)" - else - echo \033[31m - printf " Jump is NOT taken (n!=0)" - end - end - # 0110 - VS: V == 1 - if ($_conditional == 0x6) - if ($_v_flag == 1) - echo \033[31m - printf " Jump is taken (v==1)" - else - echo \033[31m - printf " Jump is NOT taken (v!=1)" - end - end - # 0111 - VC: V == 0 - if ($_conditional == 0x7) - if ($_v_flag == 0) - echo \033[31m - printf " Jump is taken (v==0)" - else - echo \033[31m - printf " Jump is NOT taken (v!=0)" - end - end - # 1000 - HI: C == 1 and Z == 0 - if ($_conditional == 0x8) - if ($_c_flag == 1 && $_z_flag == 0) - echo \033[31m - printf " Jump is taken (c==1 and z==0)" - else - echo \033[31m - printf " Jump is NOT taken (c!=1 or z!=0)" - end - end - # 1001 - LS: C == 0 or Z == 1 - if ($_conditional == 0x9) - if ($_c_flag == 0 || $_z_flag == 1) - echo \033[31m - printf " Jump is taken (c==0 or z==1)" - else - echo \033[31m - printf " Jump is NOT taken (c!=0 or z!=1)" - end - end - # 1010 - GE: N == V - if ($_conditional == 0xA) - if ($_n_flag == $_v_flag) - echo \033[31m - printf " Jump is taken (n==v)" - else - echo \033[31m - printf " Jump is NOT taken (n!=v)" - end - end - # 1011 - LT: N != V - if ($_conditional == 0xB) - if ($_n_flag != $_v_flag) - echo \033[31m - printf " Jump is taken (n!=v)" - else - echo \033[31m - printf " Jump is NOT taken (n==v)" - end - end - # 1100 - GT: Z == 0 and N == V - if ($_conditional == 0xC) - if ($_z_flag == 0 && $_n_flag == $_v_flag) - echo \033[31m - printf " Jump is taken (z==0 and n==v)" - else - echo \033[31m - printf " Jump is NOT taken (z!=0 or n!=v)" - end - end - # 1101 - LE: Z == 1 or N != V - if ($_conditional == 0xD) - if ($_z_flag == 1 || $_n_flag != $_v_flag) - echo \033[31m - printf " Jump is taken (z==1 or n!=v)" - else - echo \033[31m - printf " Jump is NOT taken (z!=1 or n==v)" - end - end -end -document dumpjumphelper -Helper function to decide if conditional jump will be taken or not, for ARM and Thumb. -end - - -# _______________process context______________ -# initialize variable -set $displayobjectivec = 0 - -define context - echo \033[34m - if $SHOWCPUREGISTERS == 1 - printf "----------------------------------------" - printf "----------------------------------" - if ($64BITS == 1) - printf "---------------------------------------------" - end - echo \033[34m\033[1m - printf "[regs]\n" - echo \033[0m - reg - echo \033[36m - end - if $SHOWSTACK == 1 - echo \033[34m - if ($64BITS == 1) - printf "[0x%04X:0x%016lX]", $ss, $rsp - else - printf "[0x%04X:0x%08X]", $ss, $esp - end - echo \033[34m - printf "-------------------------" - printf "-----------------------------" - if ($64BITS == 1) - printf "-------------------------------------" - end - echo \033[34m\033[1m - printf "[stack]\n" - echo \033[0m - set $context_i = $CONTEXTSIZE_STACK - while ($context_i > 0) - set $context_t = $sp + 0x10 * ($context_i - 1) - hexdump $context_t - set $context_i-- - end - end - # show the objective C message being passed to msgSend - if $SHOWOBJECTIVEC == 1 - #FIXME: X64 and ARM - # What a piece of crap that's going on here :) - # detect if it's the correct opcode we are searching for - if $ARM == 0 - set $__byte1 = *(unsigned char *)$pc - set $__byte = *(int *)$pc - if ($__byte == 0x4244489) - set $objectivec = $eax - set $displayobjectivec = 1 - end - - if ($__byte == 0x4245489) - set $objectivec = $edx - set $displayobjectivec = 1 - end - - if ($__byte == 0x4244c89) - set $objectivec = $ecx - set $displayobjectivec = 1 - end - else - set $__byte1 = 0 - end - # and now display it or not (we have no interest in having the info displayed after the call) - if $__byte1 == 0xE8 - if $displayobjectivec == 1 - echo \033[34m - printf "--------------------------------------------------------------------" - if ($64BITS == 1) - printf "---------------------------------------------" - end - echo \033[34m\033[1m - printf "[ObjectiveC]\n" - echo \033[0m\033[30m - x/s $objectivec - end - set $displayobjectivec = 0 - end - if $displayobjectivec == 1 - echo \033[34m - printf "--------------------------------------------------------------------" - if ($64BITS == 1) - printf "---------------------------------------------" - end - echo \033[34m\033[1m - printf "[ObjectiveC]\n" - echo \033[0m\033[30m - x/s $objectivec - end - end - echo \033[0m -# and this is the end of this little crap - - if $SHOWDATAWIN == 1 - datawin - end - - echo \033[34m - printf "--------------------------------------------------------------------------" - if ($64BITS == 1) - printf "---------------------------------------------" - end - echo \033[34m\033[1m - printf "[code]\n" - echo \033[0m - set $context_i = $CONTEXTSIZE_CODE - if ($context_i > 0) - if ($SETCOLOUR1STLINE == 1) - echo \033[32m - x /i $pc - echo \033[0m - else - x /i $pc - end - set $context_i-- - end - while ($context_i > 0) - x /i - set $context_i-- - end - echo \033[34m - printf "----------------------------------------" - printf "----------------------------------------" - if ($64BITS == 1) - printf "---------------------------------------------\n" - else - printf "\n" - end - echo \033[0m -end -document context -Print context window, i.e. regs, stack, ds:esi and disassemble cs:eip. -end - - -define context-on - set $SHOW_CONTEXT = 1 - printf "Displaying of context is now ON\n" -end -document context-on -Enable display of context on every program break. -end - - -define context-off - set $SHOW_CONTEXT = 0 - printf "Displaying of context is now OFF\n" -end -document context-off -Disable display of context on every program break. -end - - -# _______________process control______________ -define n - if $argc == 0 - nexti - end - if $argc == 1 - nexti $arg0 - end - if $argc > 1 - help n - end -end -document n -Step one instruction, but proceed through subroutine calls. -If NUM is given, then repeat it NUM times or till program stops. -This is alias for nexti. -Usage: n -end - - -define go - if $argc == 0 - stepi - end - if $argc == 1 - stepi $arg0 - end - if $argc > 1 - help go - end -end -document go -Step one instruction exactly. -If NUM is given, then repeat it NUM times or till program stops. -This is alias for stepi. -Usage: go -end - - -define pret - finish -end -document pret -Execute until selected stack frame returns (step out of current call). -Upon return, the value returned is printed and put in the value history. -end - - -define init - set $SHOW_NEST_INSN = 0 - tbreak _init - r -end -document init -Run program and break on _init(). -end - - -define start - set $SHOW_NEST_INSN = 0 - tbreak _start - r -end -document start -Run program and break on _start(). -end - - -define sstart - set $SHOW_NEST_INSN = 0 - tbreak __libc_start_main - r -end -document sstart -Run program and break on __libc_start_main(). -Useful for stripped executables. -end - - -define main - set $SHOW_NEST_INSN = 0 - tbreak main - r -end -document main -Run program and break on main(). -end - - -# FIXME64 -#### WARNING ! WARNING !! -#### More more messy stuff starting !!! -#### I was thinking about how to do this and then it ocurred me that it could be as simple as this ! :) -define stepoframework - if $ARM == 1 - # bl and bx opcodes - # bx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 0 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 0 - # blx Rn => ARM bits 27-20: 0 0 0 1 0 0 1 0 , bits 7-4: 0 0 1 1 ; Thumb bits: 15-7: 0 1 0 0 0 1 1 1 1 - # bl # => ARM bits 27-24: 1 0 1 1 ; Thumb bits: 15-11: 1 1 1 1 0 - # blx # => ARM bits 31-25: 1 1 1 1 1 0 1 ; Thumb bits: 15-11: 1 1 1 1 0 - set $_nextaddress = 0 - - # ARM Mode - if ($_t_flag == 0) - set $_branchesint = *(unsigned int*)$pc - set $_bit31 = ($_branchesint >> 0x1F) & 1 - set $_bit30 = ($_branchesint >> 0x1E) & 1 - set $_bit29 = ($_branchesint >> 0x1D) & 1 - set $_bit28 = ($_branchesint >> 0x1C) & 1 - set $_bit27 = ($_branchesint >> 0x1B) & 1 - set $_bit26 = ($_branchesint >> 0x1A) & 1 - set $_bit25 = ($_branchesint >> 0x19) & 1 - set $_bit24 = ($_branchesint >> 0x18) & 1 - set $_bit23 = ($_branchesint >> 0x17) & 1 - set $_bit22 = ($_branchesint >> 0x16) & 1 - set $_bit21 = ($_branchesint >> 0x15) & 1 - set $_bit20 = ($_branchesint >> 0x14) & 1 - set $_bit7 = ($_branchesint >> 0x7) & 1 - set $_bit6 = ($_branchesint >> 0x6) & 1 - set $_bit5 = ($_branchesint >> 0x5) & 1 - set $_bit4 = ($_branchesint >> 0x4) & 1 - - # set $_lastbyte = *(unsigned char *)($pc+3) - # set $_bits2724 = $_lastbyte & 0x1 - # set $_bits3128 = $_lastbyte >> 4 - # if ($_bits3128 == 0xF) - # set $_bits2724 = $_lastbyte & 0xA - # set $_bits2724 = $_bits2724 >> 1 - # end - # set $_previousbyte = *(unsigned char *)($pc+2) - # set $_bits2320 = $_previousbyte >> 4 - # printf "bits2724: %x bits2320: %x\n", $_bits2724, $_bits2320 - - if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 0 && $_bit4 == 1) - printf "Found a bx Rn\n" - set $_nextaddress = $pc+0x4 - end - if ($_bit27 == 0 && $_bit26 == 0 && $_bit25 == 0 && $_bit24 == 1 && $_bit23 == 0 && $_bit22 == 0 && $_bit21 == 1 && $_bit20 == 0 && $_bit7 == 0 && $_bit6 == 0 && $_bit5 == 1 && $_bit4 == 1) - printf "Found a blx Rn\n" - set $_nextaddress = $pc+0x4 - end - if ($_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1 && $_bit24 == 1) - printf "Found a bl #\n" - set $_nextaddress = $pc+0x4 - end - if ($_bit31 == 1 && $_bit30 == 1 && $_bit29 == 1 && $_bit28 == 1 && $_bit27 == 1 && $_bit26 == 0 && $_bit25 == 1) - printf "Found a blx #\n" - set $_nextaddress = $pc+0x4 - end - # Thumb Mode - else - # 32 bits instructions in Thumb are divided into two half words - set $_hw1 = *(unsigned short*)($pc) - set $_hw2 = *(unsigned short*)($pc+2) - - # bl/blx (immediate) - # hw1: bits 15-11: 1 1 1 1 0 - # hw2: bits 15-14: 1 1 ; BL bit 12: 1 ; BLX bit 12: 0 - if ( ($_hw1 >> 0xC) == 0xF && (($_hw1 >> 0xB) & 1) == 0) - if ( ((($_hw2 >> 0xF) & 1) == 1) && ((($_hw2 >> 0xE) & 1) == 1) ) - set $_nextaddress = $pc+0x4 - end - end - end - # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue - if ($_nextaddress != 0) - tbreak *$_nextaddress - continue - printf "[StepO] Next address will be %x\n", $_nextaddress - # else we just single step - else - nexti - end -###################################### X86 - else - ## we know that an opcode starting by 0xE8 has a fixed length - ## for the 0xFF opcodes, we can enumerate what is possible to have - # first we grab the first 3 bytes from the current program counter - set $_byte1 = *(unsigned char *)$pc - set $_byte2 = *(unsigned char *)($pc+1) - set $_byte3 = *(unsigned char *)($pc+2) - # and start the fun - # if it's a 0xE8 opcode, the total instruction size will be 5 bytes - # so we can simply calculate the next address and use a temporary breakpoint ! Voila :) - set $_nextaddress = 0 - # this one is the must useful for us !!! - if ($_byte1 == 0xE8) - set $_nextaddress = $pc + 0x5 - else - # just other cases we might be interested in... maybe this should be removed since the 0xE8 opcode is the one we will use more - # this is a big fucking mess and can be improved for sure :) I don't like the way it is ehehehe - if ($_byte1 == 0xFF) - # call *%eax (0xFFD0) || call *%edx (0xFFD2) || call *(%ecx) (0xFFD1) || call (%eax) (0xFF10) || call *%esi (0xFFD6) || call *%ebx (0xFFD3) || call DWORD PTR [edx] (0xFF12) - if ($_byte2 == 0xD0 || $_byte2 == 0xD1 || $_byte2 == 0xD2 || $_byte2 == 0xD3 || $_byte2 == 0xD6 || $_byte2 == 0x10 || $_byte2 == 0x11 || $_byte2 == 0xD7 || $_byte2 == 0x12) - set $_nextaddress = $pc + 0x2 - end - # call *0x??(%ebp) (0xFF55??) || call *0x??(%esi) (0xFF56??) || call *0x??(%edi) (0xFF5F??) || call *0x??(%ebx) - # call *0x??(%edx) (0xFF52??) || call *0x??(%ecx) (0xFF51??) || call *0x??(%edi) (0xFF57??) || call *0x??(%eax) (0xFF50??) - if ($_byte2 == 0x55 || $_byte2 == 0x56 || $_byte2 == 0x5F || $_byte2 == 0x53 || $_byte2 == 0x52 || $_byte2 == 0x51 || $_byte2 == 0x57 || $_byte2 == 0x50) - set $_nextaddress = $pc + 0x3 - end - # call *0x????????(%ebx) (0xFF93????????) || - if ($_byte2 == 0x93 || $_byte2 == 0x94 || $_byte2 == 0x90 || $_byte2 == 0x92 || $_byte2 == 0x95) - set $_nextaddress = $pc + 6 - end - # call *0x????????(%ebx,%eax,4) (0xFF94??????????) - if ($_byte2 == 0x94) - set $_nextaddress = $pc + 7 - end - end - end - # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue - if ($_nextaddress != 0) - if ($arg0 == 1) - thbreak *$_nextaddress - else - tbreak *$_nextaddress - end - continue - # else we just single step - else - nexti - end - end -end -document stepoframework -Auxiliary function to stepo command. -end - -define stepo - stepoframework 0 -end -document stepo -Step over calls (interesting to bypass the ones to msgSend). -This function will set a temporary breakpoint on next instruction after the call so the call will be bypassed. -You can safely use it instead nexti or n since it will single step code if it's not a call instruction (unless you want to go into the call function). -end - - -define stepoh - stepoframework 1 -end -document stepoh -Same as stepo command but uses temporary hardware breakpoints. -end - - -# FIXME: ARM -define skip - x/2i $pc - set $instruction_size = (int)($_ - $pc) - set $pc = $pc + $instruction_size - if ($SKIPEXECUTE == 1) - if ($SKIPSTEP == 1) - stepo - else - stepi - end - else - context - end -end -document skip -Skip over the instruction located at EIP/RIP. By default, the instruction will not be executed! -Some configurable options are available on top of gdbinit to override this. -end - - -# _______________eflags commands______________ -# conditional flags are -# negative/less than (N), bit 31 of CPSR -# zero (Z), bit 30 -# Carry/Borrow/Extend (C), bit 29 -# Overflow (V), bit 28 - -# negative/less than (N), bit 31 of CPSR -define cfn - if $ARM == 1 - set $tempflag = $cpsr->n - if ($tempflag & 1) - set $cpsr->n = $tempflag&~0x1 - else - set $cpsr->n = $tempflag|0x1 - end - end -end -document cfn -Change Negative/Less Than Flag. -end - - -define cfc -# Carry/Borrow/Extend (C), bit 29 - if $ARM == 1 - set $tempflag = $cpsr->c - if ($tempflag & 1) - set $cpsr->c = $tempflag&~0x1 - else - set $cpsr->c = $tempflag|0x1 - end - else - if ($eflags & 1) - set $eflags = $eflags&~0x1 - else - set $eflags = $eflags|0x1 - end - end -end -document cfc -Change Carry Flag. -end - - -define cfp - if (($eflags >> 2) & 1) - set $eflags = $eflags&~0x4 - else - set $eflags = $eflags|0x4 - end -end -document cfp -Change Parity Flag. -end - - -define cfa - if (($eflags >> 4) & 1) - set $eflags = $eflags&~0x10 - else - set $eflags = $eflags|0x10 - end -end -document cfa -Change Auxiliary Carry Flag. -end - - -define cfz -# zero (Z), bit 30 - if $ARM == 1 - set $tempflag = $cpsr->z - if ($tempflag & 1) - set $cpsr->z = $tempflag&~0x1 - else - set $cpsr->z = $tempflag|0x1 - end - else - if (($eflags >> 6) & 1) - set $eflags = $eflags&~0x40 - else - set $eflags = $eflags|0x40 - end - end -end -document cfz -Change Zero Flag. -end - - -define cfs - if (($eflags >> 7) & 1) - set $eflags = $eflags&~0x80 - else - set $eflags = $eflags|0x80 - end -end -document cfs -Change Sign Flag. -end - - -define cft - if (($eflags >>8) & 1) - set $eflags = $eflags&~0x100 - else - set $eflags = $eflags|0x100 - end -end -document cft -Change Trap Flag. -end - - -define cfi - if (($eflags >> 9) & 1) - set $eflags = $eflags&~0x200 - else - set $eflags = $eflags|0x200 - end -end -document cfi -Change Interrupt Flag. -Only privileged applications (usually the OS kernel) may modify IF. -This only applies to protected mode (real mode code may always modify IF). -end - - -define cfd - if (($eflags >>0xA) & 1) - set $eflags = $eflags&~0x400 - else - set $eflags = $eflags|0x400 - end -end -document cfd -Change Direction Flag. -end - - -define cfo - if (($eflags >> 0xB) & 1) - set $eflags = $eflags&~0x800 - else - set $eflags = $eflags|0x800 - end -end -document cfo -Change Overflow Flag. -end - - -# Overflow (V), bit 28 -define cfv - if $ARM == 1 - set $tempflag = $cpsr->v - if ($tempflag & 1) - set $cpsr->v = $tempflag&~0x1 - else - set $cpsr->v = $tempflag|0x1 - end - end -end -document cfv -Change Overflow Flag. -end - - -# ____________________patch___________________ -# the usual nops are mov r0,r0 for arm (0xe1a00000) -# and mov r8,r8 in Thumb (0x46c0) -# armv7 has other nops -# FIXME: make sure that the interval fits the 32bits address for arm and 16bits for thumb -# status: works, fixme -define nop - if ($argc > 2 || $argc == 0) - help nop - end - - if $ARM == 1 - if ($argc == 1) - if ($cpsr->t &1) - # thumb - set *(short *)$arg0 = 0x46c0 - else - # arm - set *(int *)$arg0 = 0xe1a00000 - end - else - set $addr = $arg0 - if ($cpsr->t & 1) - # thumb - while ($addr < $arg1) - set *(short *)$addr = 0x46c0 - set $addr = $addr + 2 - end - else - # arm - while ($addr < $arg1) - set *(int *)$addr = 0xe1a00000 - set $addr = $addr + 4 - end - end - end - else - if ($argc == 1) - set *(unsigned char *)$arg0 = 0x90 - else - set $addr = $arg0 - while ($addr < $arg1) - set *(unsigned char *)$addr = 0x90 - set $addr = $addr + 1 - end - end - end -end -document nop -Usage: nop ADDR1 [ADDR2] -Patch a single byte at address ADDR1, or a series of bytes between ADDR1 and ADDR2 to a NOP (0x90) instruction. -ARM or Thumb code will be patched accordingly. -end - - -define null - if ( $argc >2 || $argc == 0) - help null - end - - if ($argc == 1) - set *(unsigned char *)$arg0 = 0 - else - set $addr = $arg0 - while ($addr < $arg1) - set *(unsigned char *)$addr = 0 - set $addr = $addr +1 - end - end -end -document null -Usage: null ADDR1 [ADDR2] -Patch a single byte at address ADDR1 to NULL (0x00), or a series of bytes between ADDR1 and ADDR2. -end - -# FIXME: thumb breakpoint ? -define int3 - if $argc != 1 - help int3 - else - if $ARM == 1 - set $ORIGINAL_INT3 = *(unsigned int *)$arg0 - set $ORIGINAL_INT3ADDRESS = $arg0 - set *(unsigned int*)$arg0 = 0xe7ffdefe - else - # save original bytes and address - set $ORIGINAL_INT3 = *(unsigned char *)$arg0 - set $ORIGINAL_INT3ADDRESS = $arg0 - # patch - set *(unsigned char *)$arg0 = 0xCC - end - end -end -document int3 -Patch byte at address ADDR to an INT3 (0xCC) instruction or the equivalent software breakpoint for ARM. -Usage: int3 ADDR -end - - -define rint3 - if $ARM == 1 - set *(unsigned int *)$ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3 - set $pc = $ORIGINAL_INT3ADDRESS - else - set *(unsigned char *)$ORIGINAL_INT3ADDRESS = $ORIGINAL_INT3 - if $64BITS == 1 - set $rip = $ORIGINAL_INT3ADDRESS - else - set $eip = $ORIGINAL_INT3ADDRESS - end - end -end -document rint3 -Restore the original byte previous to int3 patch issued with "int3" command. -end - - -# ____________________cflow___________________ -define print_insn_type - if $argc != 1 - help print_insn_type - else - if ($arg0 < 0 || $arg0 > 5) - printf "UNDEFINED/WRONG VALUE" - end - if ($arg0 == 0) - printf "UNKNOWN" - end - if ($arg0 == 1) - printf "JMP" - end - if ($arg0 == 2) - printf "JCC" - end - if ($arg0 == 3) - printf "CALL" - end - if ($arg0 == 4) - printf "RET" - end - if ($arg0 == 5) - printf "INT" - end - end -end -document print_insn_type -Print human-readable mnemonic for the instruction type (usually $INSN_TYPE). -Usage: print_insn_type INSN_TYPE_NUMBER -end - - -define get_insn_type - if $argc != 1 - help get_insn_type - else - set $INSN_TYPE = 0 - set $_byte1 = *(unsigned char *)$arg0 - if ($_byte1 == 0x9A || $_byte1 == 0xE8) - # "call" - set $INSN_TYPE = 3 - end - if ($_byte1 >= 0xE9 && $_byte1 <= 0xEB) - # "jmp" - set $INSN_TYPE = 1 - end - if ($_byte1 >= 0x70 && $_byte1 <= 0x7F) - # "jcc" - set $INSN_TYPE = 2 - end - if ($_byte1 >= 0xE0 && $_byte1 <= 0xE3 ) - # "jcc" - set $INSN_TYPE = 2 - end - if ($_byte1 == 0xC2 || $_byte1 == 0xC3 || $_byte1 == 0xCA || \ - $_byte1 == 0xCB || $_byte1 == 0xCF) - # "ret" - set $INSN_TYPE = 4 - end - if ($_byte1 >= 0xCC && $_byte1 <= 0xCE) - # "int" - set $INSN_TYPE = 5 - end - if ($_byte1 == 0x0F ) - # two-byte opcode - set $_byte2 = *(unsigned char *)($arg0 + 1) - if ($_byte2 >= 0x80 && $_byte2 <= 0x8F) - # "jcc" - set $INSN_TYPE = 2 - end - end - if ($_byte1 == 0xFF) - # opcode extension - set $_byte2 = *(unsigned char *)($arg0 + 1) - set $_opext = ($_byte2 & 0x38) - if ($_opext == 0x10 || $_opext == 0x18) - # "call" - set $INSN_TYPE = 3 - end - if ($_opext == 0x20 || $_opext == 0x28) - # "jmp" - set $INSN_TYPE = 1 - end - end - end -end -document get_insn_type -Recognize instruction type at address ADDR. -Take address ADDR and set the global $INSN_TYPE variable to -0, 1, 2, 3, 4, 5 if the instruction at that address is -unknown, a jump, a conditional jump, a call, a return, or an interrupt. -Usage: get_insn_type ADDR -end - - -define step_to_call - set $_saved_ctx = $SHOW_CONTEXT - set $SHOW_CONTEXT = 0 - set $SHOW_NEST_INSN = 0 - - set logging file /dev/null - set logging redirect on - set logging on - - set $_cont = 1 - while ($_cont > 0) - stepi - get_insn_type $pc - if ($INSN_TYPE == 3) - set $_cont = 0 - end - end - - set logging off - - if ($_saved_ctx > 0) - context - end - - set $SHOW_CONTEXT = $_saved_ctx - set $SHOW_NEST_INSN = 0 - - set logging file ~/gdb.txt - set logging redirect off - set logging on - - printf "step_to_call command stopped at:\n " - x/i $pc - printf "\n" - set logging off - -end -document step_to_call -Single step until a call instruction is found. -Stop before the call is taken. -Log is written into the file ~/gdb.txt. -end - - -define trace_calls - - printf "Tracing...please wait...\n" - - set $_saved_ctx = $SHOW_CONTEXT - set $SHOW_CONTEXT = 0 - set $SHOW_NEST_INSN = 0 - set $_nest = 1 - set listsize 0 - - set logging overwrite on - set logging file ~/gdb_trace_calls.txt - set logging on - set logging off - set logging overwrite off - - while ($_nest > 0) - get_insn_type $pc - # handle nesting - if ($INSN_TYPE == 3) - set $_nest = $_nest + 1 - else - if ($INSN_TYPE == 4) - set $_nest = $_nest - 1 - end - end - # if a call, print it - if ($INSN_TYPE == 3) - set logging file ~/gdb_trace_calls.txt - set logging redirect off - set logging on - - set $x = $_nest - 2 - while ($x > 0) - printf "\t" - set $x = $x - 1 - end - x/i $pc - end - - set logging off - set logging file /dev/null - set logging redirect on - set logging on - stepi - set logging redirect off - set logging off - end - - set $SHOW_CONTEXT = $_saved_ctx - set $SHOW_NEST_INSN = 0 - - printf "Done, check ~/gdb_trace_calls.txt\n" -end -document trace_calls -Create a runtime trace of the calls made by target. -Log overwrites(!) the file ~/gdb_trace_calls.txt. -end - - -define trace_run - - printf "Tracing...please wait...\n" - - set $_saved_ctx = $SHOW_CONTEXT - set $SHOW_CONTEXT = 0 - set $SHOW_NEST_INSN = 1 - set logging overwrite on - set logging file ~/gdb_trace_run.txt - set logging redirect on - set logging on - set $_nest = 1 - - while ( $_nest > 0 ) - - get_insn_type $pc - # jmp, jcc, or cll - if ($INSN_TYPE == 3) - set $_nest = $_nest + 1 - else - # ret - if ($INSN_TYPE == 4) - set $_nest = $_nest - 1 - end - end - stepi - end - - printf "\n" - - set $SHOW_CONTEXT = $_saved_ctx - set $SHOW_NEST_INSN = 0 - set logging redirect off - set logging off - - # clean up trace file - shell grep -v ' at ' ~/gdb_trace_run.txt > ~/gdb_trace_run.1 - shell grep -v ' in ' ~/gdb_trace_run.1 > ~/gdb_trace_run.txt - shell rm -f ~/gdb_trace_run.1 - printf "Done, check ~/gdb_trace_run.txt\n" -end -document trace_run -Create a runtime trace of target. -Log overwrites(!) the file ~/gdb_trace_run.txt. -end - -#define ptraceme -# catch syscall ptrace -# commands -# if ($64BITS == 0) -# if ($ebx == 0) -# set $eax = 0 -# continue -# end -# else -# if ($rdi == 0) -# set $rax = 0 -# continue -# end -# end -# end -# set $ptrace_bpnum = $bpnum -#end -#document ptraceme -#Hook ptrace to bypass PTRACE_TRACEME anti debugging technique -#end - -define rptraceme - if ($ptrace_bpnum != 0) - delete $ptrace_bpnum - set $ptrace_bpnum = 0 - end -end -document rptraceme -Remove ptrace hook. -end - - -# ____________________misc____________________ -define hook-stop -# Display instructions formats - if $ARM == 1 - if $ARMOPCODES == 1 - set arm show-opcode-bytes 1 - else - set arm show-opcode-bytes 1 - end - else - if $X86FLAVOR == 0 - set disassembly-flavor intel - else - set disassembly-flavor att - end - end - - # this makes 'context' be called at every BP/step - if ($SHOW_CONTEXT > 0) - context - end - if ($SHOW_NEST_INSN > 0) - set $x = $_nest - while ($x > 0) - printf "\t" - set $x = $x - 1 - end - end -end -document hook-stop -!!! FOR INTERNAL USE ONLY - DO NOT CALL !!! -end - - -# original by Tavis Ormandy (http://my.opera.com/taviso/blog/index.dml/tag/gdb) (great fix!) -# modified to work with Mac OS X by fG! -# seems nasm shipping with Mac OS X has problems accepting input from stdin or heredoc -# input is read into a variable and sent to a temporary file which nasm can read -define assemble - # dont enter routine again if user hits enter - dont-repeat - if ($argc) - if (*$arg0 = *$arg0) - # check if we have a valid address by dereferencing it, - # if we havnt, this will cause the routine to exit. - end - printf "Instructions will be written to %#x.\n", $arg0 - else - printf "Instructions will be written to stdout.\n" - end - printf "Type instructions, one per line." - echo \033[1m - printf " Do not forget to use NASM assembler syntax!\n" - echo \033[0m - printf "End with a line saying just \"end\".\n" - - if ($argc) - if ($64BITS == 1) - # argument specified, assemble instructions into memory at address specified. - shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \ - echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME - source /tmp/gdbassemble - # all done. clean the temporary file - shell /bin/rm -f /tmp/gdbassemble - else - # argument specified, assemble instructions into memory at address specified. - shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \ - echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/hexdump -ve '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' >/tmp/gdbassemble ; /bin/rm -f /tmp/$GDBASMFILENAME - source /tmp/gdbassemble - # all done. clean the temporary file - shell /bin/rm -f /tmp/gdbassemble - end - else - if ($64BITS == 1) - # no argument, assemble instructions to stdout - shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \ - echo -e "BITS 64\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/local/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/local/bin/ndisasm -i -b64 /dev/stdin ; \ - /bin/rm -f /tmp/$GDBASMFILENAME - else - # no argument, assemble instructions to stdout - shell ASMOPCODE="$(while read -ep '>' r && test "$r" != end ; do echo -E "$r"; done)" ; GDBASMFILENAME=$RANDOM; \ - echo -e "BITS 32\n$ASMOPCODE" >/tmp/$GDBASMFILENAME ; /usr/bin/nasm -f bin -o /dev/stdout /tmp/$GDBASMFILENAME | /usr/bin/ndisasm -i -b32 /dev/stdin ; \ - /bin/rm -f /tmp/$GDBASMFILENAME - end - end -end -document assemble -Assemble instructions using nasm. -Type a line containing "end" to indicate the end. -If an address is specified, insert/modify instructions at that address. -If no address is specified, assembled instructions are printed to stdout. -Use the pseudo instruction "org ADDR" to set the base address. -end - - -define asm - if $argc == 1 - assemble $arg0 - else - assemble - end -end -document asm -Shortcut to the asssemble command. -end - - -define assemble_gas - printf "\nType code to assemble and hit Ctrl-D when finished.\n" - printf "You must use GNU assembler (AT&T) syntax.\n" - - shell filename=$(mktemp); \ - binfilename=$(mktemp); \ - echo -e "Writing into: ${filename}\n"; \ - cat > $filename; echo ""; \ - as -o $binfilename < $filename; \ - objdump -d -j .text $binfilename; \ - rm -f $binfilename; \ - rm -f $filename; \ - echo -e "temporaly files deleted.\n" -end -document assemble_gas -Assemble instructions to binary opcodes. Uses GNU as and objdump. -Usage: assemble_gas -end - - -define dump_hexfile - dump ihex memory $arg0 $arg1 $arg2 -end -document dump_hexfile -Write a range of memory to a file in Intel ihex (hexdump) format. -The range is specified by ADDR1 and ADDR2 addresses. -Usage: dump_hexfile FILENAME ADDR1 ADDR2 -end - - -define dump_binfile - dump memory $arg0 $arg1 $arg2 -end -document dump_binfile -Write a range of memory to a binary file. -The range is specified by ADDR1 and ADDR2 addresses. -Usage: dump_binfile FILENAME ADDR1 ADDR2 -end - - -define dumpmacho - if $argc != 2 - help dumpmacho - end - set $headermagic = *$arg0 - # the || operator isn't working as it should, wtf!!! - if $headermagic != 0xfeedface - if $headermagic != 0xfeedfacf - printf "[Error] Target address doesn't contain a valid Mach-O binary!\n" - help dumpmacho - end - end - set $headerdumpsize = *($arg0+0x14) - if $headermagic == 0xfeedface - dump memory $arg1 $arg0 ($arg0+0x1c+$headerdumpsize) - end - if $headermagic == 0xfeedfacf - dump memory $arg1 $arg0 ($arg0+0x20+$headerdumpsize) - end -end -document dumpmacho -Dump the Mach-O header to a file. -You need to input the start address (use info shared command to find it). -Usage: dumpmacho STARTADDRESS FILENAME -end - - -define cls - shell clear -end -document cls -Clear screen. -end - - -define search - set $start = (char *) $arg0 - set $end = (char *) $arg1 - set $pattern = (short) $arg2 - set $p = $start - while $p < $end - if (*(short *) $p) == $pattern - printf "pattern 0x%hx found at 0x%x\n", $pattern, $p - end - set $p++ - end -end -document search -Search for the given pattern beetween $start and $end address. -Usage: search -end - - -# _________________user tips_________________ -# The 'tips' command is used to provide tutorial-like info to the user -define tips - printf "Tip Topic Commands:\n" - printf "\ttip_display : Automatically display values on each break\n" - printf "\ttip_patch : Patching binaries\n" - printf "\ttip_strip : Dealing with stripped binaries\n" - printf "\ttip_syntax : AT&T vs Intel syntax\n" -end -document tips -Provide a list of tips from users on various topics. -end - - -define tip_patch - printf "\n" - printf " PATCHING MEMORY\n" - printf "Any address can be patched using the 'set' command:\n" - printf "\t`set ADDR = VALUE` \te.g. `set *0x8049D6E = 0x90`\n" - printf "\n" - printf " PATCHING BINARY FILES\n" - printf "Use `set write` in order to patch the target executable\n" - printf "directly, instead of just patching memory\n" - printf "\t`set write on` \t`set write off`\n" - printf "Note that this means any patches to the code or data segments\n" - printf "will be written to the executable file\n" - printf "When either of these commands has been issued,\n" - printf "the file must be reloaded.\n" - printf "\n" -end -document tip_patch -Tips on patching memory and binary files. -end - - -define tip_strip - printf "\n" - printf " STOPPING BINARIES AT ENTRY POINT\n" - printf "Stripped binaries have no symbols, and are therefore tough to\n" - printf "start automatically. To debug a stripped binary, use\n" - printf "\tinfo file\n" - printf "to get the entry point of the file\n" - printf "The first few lines of output will look like this:\n" - printf "\tSymbols from '/tmp/a.out'\n" - printf "\tLocal exec file:\n" - printf "\t `/tmp/a.out', file type elf32-i386.\n" - printf "\t Entry point: 0x80482e0\n" - printf "Use this entry point to set an entry point:\n" - printf "\t`tbreak *0x80482e0`\n" - printf "The breakpoint will delete itself after the program stops as\n" - printf "the entry point\n" - printf "\n" -end -document tip_strip -Tips on dealing with stripped binaries. -end - - -define tip_syntax - printf "\n" - printf "\t INTEL SYNTAX AT&T SYNTAX\n" - printf "\tmnemonic dest, src, imm mnemonic src, dest, imm\n" - printf "\t[base+index*scale+disp] disp(base, index, scale)\n" - printf "\tregister: eax register: %%eax\n" - printf "\timmediate: 0xFF immediate: $0xFF\n" - printf "\tdereference: [addr] dereference: addr(,1)\n" - printf "\tabsolute addr: addr absolute addr: *addr\n" - printf "\tbyte insn: mov byte ptr byte insn: movb\n" - printf "\tword insn: mov word ptr word insn: movw\n" - printf "\tdword insn: mov dword ptr dword insn: movd\n" - printf "\tfar call: call far far call: lcall\n" - printf "\tfar jump: jmp far far jump: ljmp\n" - printf "\n" - printf "Note that order of operands in reversed, and that AT&T syntax\n" - printf "requires that all instructions referencing memory operands \n" - printf "use an operand size suffix (b, w, d, q)\n" - printf "\n" -end -document tip_syntax -Summary of Intel and AT&T syntax differences. -end - - -define tip_display - printf "\n" - printf "Any expression can be set to automatically be displayed every time\n" - printf "the target stops. The commands for this are:\n" - printf "\t`display expr' : automatically display expression 'expr'\n" - printf "\t`display' : show all displayed expressions\n" - printf "\t`undisplay num' : turn off autodisplay for expression # 'num'\n" - printf "Examples:\n" - printf "\t`display/x *(int *)$esp` : print top of stack\n" - printf "\t`display/x *(int *)($ebp+8)` : print first parameter\n" - printf "\t`display (char *)$esi` : print source string\n" - printf "\t`display (char *)$edi` : print destination string\n" - printf "\n" -end -document tip_display -Tips on automatically displaying values when a program stops. -end - -# bunch of semi-useless commands - -# enable and disable shortcuts for stop-on-solib-events fantastic trick! -define enablesolib - set stop-on-solib-events 1 - printf "Stop-on-solib-events is enabled!\n" -end -document enablesolib -Shortcut to enable stop-on-solib-events trick. -end - - -define disablesolib - set stop-on-solib-events 0 - printf "Stop-on-solib-events is disabled!\n" -end -document disablesolib -Shortcut to disable stop-on-solib-events trick. -end - - -# enable commands for different displays -define enableobjectivec - set $SHOWOBJECTIVEC = 1 -end -document enableobjectivec -Enable display of objective-c information in the context window. -end - - -define enablecpuregisters - set $SHOWCPUREGISTERS = 1 -end -document enablecpuregisters -Enable display of cpu registers in the context window. -end - - -define enablestack - set $SHOWSTACK = 1 -end -document enablestack -Enable display of stack in the context window. -end - - -define enabledatawin - set $SHOWDATAWIN = 1 -end -document enabledatawin -Enable display of data window in the context window. -end - - -# disable commands for different displays -define disableobjectivec - set $SHOWOBJECTIVEC = 0 -end -document disableobjectivec -Disable display of objective-c information in the context window. -end - - -define disablecpuregisters - set $SHOWCPUREGISTERS = 0 -end -document disablecpuregisters -Disable display of cpu registers in the context window. -end - - -define disablestack - set $SHOWSTACK = 0 -end -document disablestack -Disable display of stack information in the context window. -end - - -define disabledatawin - set $SHOWDATAWIN = 0 -end -document disabledatawin -Disable display of data window in the context window. -end - - -define 32bits - set $64BITS = 0 - if $X86FLAVOR == 0 - set disassembly-flavor intel - else - set disassembly-flavor att - end -end -document 32bits -Set gdb to work with 32bits binaries. -end - - -define 64bits - set $64BITS = 1 - if $X86FLAVOR == 0 - set disassembly-flavor intel - else - set disassembly-flavor att - end -end -document 64bits -Set gdb to work with 64bits binaries. -end - - -define arm - if $ARMOPCODES == 1 - set arm show-opcode-bytes 1 - else - set arm show-opcode-bytes 1 - end - set $ARM = 1 - set $64BITS = 0 -end -document arm -Set gdb to work with ARM binaries. -end - - -define enablelib - set stop-on-solib-events 1 -end -document enablelib -Activate stop-on-solib-events. -end - - -define disablelib - set stop-on-solib-events 0 -end -document disablelib -Deactivate stop-on-solib-events. -end - - -define intelsyntax - if $ARM == 0 - set disassembly-flavor intel - set $X86FLAVOR = 0 - end -end -document intelsyntax -Change disassembly syntax to intel flavor. -end - - -define attsyntax - if $ARM == 0 - set disassembly-flavor att - set $X86FLAVOR = 1 - end -end -document attsyntax -Change disassembly syntax to at&t flavor. -end - -#EOF - -# Older change logs: -# -# Version 7.4.4 (02/01/2012) -# - Added the "skip" command. This will jump to the next instruction after EIP/RIP without executing the current one. -# Thanks to @bSr43 for the tip to retrieve the current instruction size. -# -# Version 7.4.3 (04/11/2011) -# - Modified "hexdump" command to support a variable number of lines (optional parameter) -# - Removed restrictions on type of addresses in the "dd" command - Thanks to Plouj for the warning :-) -# I don't know what was the original thinking behind those :-) -# - Modified the assemble command to support 64bits - You will need to recompile nasm since the version shipped with OS X doesn't supports 64bits (www.nasm.us). -# Assumes that the new binary is installed at /usr/local/bin - modify the variable at the top if you need so. -# It will assemble based on the target arch being debugged. If you want to use gdb for a quick asm just use the 32bits or 64bits commands to set your target. -# Thanks to snare for the warning and original patch :-) -# - Added "asm" command - it's a shortcut to the "assemble" command. -# - Added configuration variable for colorized prompt. Plouj reported some issues with Ubuntu's gdb 7.2 if prompt is colorized. -# -# Version 7.4.2 (11/08/2011) -# Small fix to a weird bug happening on FreeBSD 8.2. It doesn't like a "if(" instruction, needs to be "if (". Weird! -# Many thanks to Evan for reporting and sending the patch :-) -# Added the ptraceme/rptraceme commands to bypass PTRACE_TRACME anti-debugging technique. -# Grabbed this from http://falken.tuxfamily.org/?p=171 -# It's commented out due to a gdb problem in OS X (refer to http://reverse.put.as/2011/08/20/another-patch-for-apples-gdb-the-definecommands-problem/ ) -# Just uncomment it if you want to use in ptrace enabled systems. -# -# Version 7.4.1 (21/06/2011) - fG! -# Added patch sent by sbz, more than 1 year ago, which I forgot to add :-/ -# This will allow to search for a given pattern between start and end address. -# On sbz words: "It's usefull to find call, ret or everything like that." :-) -# New command is "search" -# -# Version 7.4 (20/06/2011) - fG! -# When registers change between instructions the colour will change to red (like it happens in OllyDBG) -# This is the default behavior, if you don't like it, modify the variable SHOWREGCHANGES -# Added patch sent by Philippe Langlois -# Colour the first disassembly line - change the setting below on SETCOLOUR1STLINE - by default it's disabled -# -# Version 7.3.2 (21/02/2011) - fG! -# Added the command rint3 and modified the int3 command. The new command will restore the byte in previous int3 patch. -# -# Version 7.3.1 (29/06/2010) - fG! -# Added enablelib/disablelib command to quickly set the stop-on-solib-events trick -# Implemented the stepoh command equivalent to the stepo but using hardware breakpoints -# More fixes to stepo -# -# Version 7.3 (16/04/2010) - fG! -# Support for 64bits targets. Default is 32bits, you should modify the variable or use the 32bits or 64bits to choose the mode. -# I couldn't find another way to recognize the type of binary… Testing the register doesn't work that well. -# TODO: fix objectivec messages and stepo for 64bits -# Version 7.2.1 (24/11/2009) - fG! -# Another fix to stepo (0xFF92 missing) -# -# Version 7.2 (11/10/2009) - fG! -# Added the smallregisters function to create 16 and 8 bit versions from the registers EAX, EBX, ECX, EDX -# Revised and fixed all the dumpjump stuff, following Intel manuals. There were some errors (thx to rev who pointed the jle problem). -# Small fix to stepo command (missed a few call types) -# -# Version 7.1.7 - fG! -# Added the possibility to modify what's displayed with the context window. You can change default options at the gdb options part. For example, kernel debugging is much slower if the stack display is enabled... -# New commands enableobjectivec, enablecpuregisters, enablestack, enabledatawin and their disable equivalents (to support realtime change of default options) -# Fixed problem with the assemble command. I was calling /bin/echo which doesn't support the -e option ! DUH ! Should have used bash internal version. -# Small fixes to colours... -# New commands enablesolib and disablesolib . Just shortcuts for the stop-on-solib-events fantastic trick ! Hey... I'm lazy ;) -# Fixed this: Possible removal of "u" command, info udot is missing in gdb 6.8-debian . Doesn't exist on OS X so bye bye !!! -# Displays affected flags in jump decisions -# -# Version 7.1.6 - fG! -# Added modified assemble command from Tavis Ormandy (further modified to work with Mac OS X) (shell commands used use full path name, working for Leopard, modify for others if necessary) -# Renamed thread command to threads because thread is an internal gdb command that allows to move between program threads -# -# Version 7.1.5 (04/01/2009) - fG! -# Fixed crash on Leopard ! There was a If Else condition where the else had no code and that made gdb crash on Leopard (CRAZY!!!!) -# Better code indention -# -# Version 7.1.4 (02/01/2009) - fG! -# Bug in show objective c messages with Leopard ??? -# Nop routine support for single address or range (contribution from gln [ghalen at hack.se]) -# Used the same code from nop to null routine -# -# Version 7.1.3 (31/12/2008) - fG! -# Added a new command 'stepo'. This command will step a temporary breakpoint on next instruction after the call, so you can skip over -# the call. Did this because normal commands not always skip over (mainly with objc_msgSend) -# -# Version 7.1.2 (31/12/2008) - fG! -# Support for the jump decision (will display if a conditional jump will be taken or not) -# -# Version 7.1.1 (29/12/2008) - fG! -# Moved gdb options to the beginning (makes more sense) -# Added support to dump message being sent to msgSend (easier to understand what's going on) -# -# Version 7.1 -# Fixed serious (and old) bug in dd and datawin, causing dereference of -# obviously invalid address. See below: -# gdb$ dd 0xffffffff -# FFFFFFFF : Cannot access memory at address 0xffffffff -# -# Version 7.0 -# Added cls command. -# Improved documentation of many commands. -# Removed bp_alloc, was neither portable nor usefull. -# Checking of passed argument(s) in these commands: -# contextsize-stack, contextsize-data, contextsize-code -# bp, bpc, bpe, bpd, bpt, bpm, bhb,... -# Fixed bp and bhb inconsistencies, look at * signs in Version 6.2 -# Bugfix in bhb command, changed "break" to "hb" command body -# Removed $SHOW_CONTEXT=1 from several commands, this variable -# should only be controlled globally with context-on and context-off -# Improved stack, func, var and sig, dis, n, go,... -# they take optional argument(s) now -# Fixed wrong $SHOW_CONTEXT assignment in context-off -# Fixed serious bug in cft command, forgotten ~ sign -# Fixed these bugs in step_to_call: -# 1) the correct logging sequence is: -# set logging file > set logging redirect > set logging on -# 2) $SHOW_CONTEXT is now correctly restored from $_saved_ctx -# Fixed these bugs in trace_calls: -# 1) the correct logging sequence is: -# set logging file > set logging overwrite > -# set logging redirect > set logging on -# 2) removed the "clean up trace file" part, which is not needed now, -# stepi output is properly redirected to /dev/null -# 3) $SHOW_CONTEXT is now correctly restored from $_saved_ctx -# Fixed bug in trace_run: -# 1) $SHOW_CONTEXT is now correctly restored from $_saved_ctx -# Fixed print_insn_type -- removed invalid semicolons!, wrong value checking, -# Added TODO entry regarding the "u" command -# Changed name from gas_assemble to assemble_gas due to consistency -# Output from assemble and assemble_gas is now similar, because i made -# both of them to use objdump, with respect to output format (AT&T|Intel). -# Whole code was checked and made more consistent, readable/maintainable. -# -# Version 6.2 -# Add global variables to allow user to control stack, data and code window sizes -# Increase readability for registers -# Some corrections (hexdump, ddump, context, cfp, assemble, gas_asm, tips, prompt) -# -# Version 6.1-color-user -# Took the Gentoo route and ran sed s/user/user/g -# -# Version 6.1-color -# Added color fixes from -# http://gnurbs.blogsome.com/2006/12/22/colorizing-mamons-gdbinit/ -# -# Version 6.1 -# Fixed filename in step_to_call so it points to /dev/null -# Changed location of logfiles from /tmp to ~ -# -# Version 6 -# Added print_insn_type, get_insn_type, context-on, context-off commands -# Added trace_calls, trace_run, step_to_call commands -# Changed hook-stop so it checks $SHOW_CONTEXT variable -# -# Version 5 -# Added bpm, dump_bin, dump_hex, bp_alloc commands -# Added 'assemble' by elaine, 'gas_asm' by mong -# Added Tip Topics for aspiring users ;) -# -# Version 4 -# Added eflags-changing insns by pusillus -# Added bp, nop, null, and int3 patch commands, also hook-stop -# -# Version 3 -# Incorporated elaine's if/else goodness into the hex/ascii dump -# -# Version 2 -# Radix bugfix by elaine