summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <[email protected]>2009-11-23 17:47:57 -0500
committerAustin Clements <[email protected]>2009-11-23 17:47:57 -0500
commitb0170c4b821aaeffd7775597d1e35f201e1508ba (patch)
treea3d16d9b51f1c9201a536ab5f9e2e02577856144
parentf4c12f116d328c0b56eabac327a9cc4882c57128 (diff)
downloadxv6-labs-b0170c4b821aaeffd7775597d1e35f201e1508ba.tar.gz
xv6-labs-b0170c4b821aaeffd7775597d1e35f201e1508ba.tar.bz2
xv6-labs-b0170c4b821aaeffd7775597d1e35f201e1508ba.zip
GDB utilities
-rw-r--r--gdbutil291
1 files changed, 291 insertions, 0 deletions
diff --git a/gdbutil b/gdbutil
new file mode 100644
index 0000000..e0c362f
--- /dev/null
+++ b/gdbutil
@@ -0,0 +1,291 @@
+# -*- gdb-script -*-
+
+# Utility functions to pretty-print x86 segment/interrupt descriptors.
+# To load this file, run "source gdbutil" in gdb.
+# printdesc and printdescs are the main entry points.
+
+# IA32 2007, Volume 3A, Table 3-2
+set $STS_T16A = 0x1
+set $STS_LDT = 0x2
+set $STS_T16B = 0x3
+set $STS_CG16 = 0x4
+set $STS_TG = 0x5
+set $STS_IG16 = 0x6
+set $STS_TG16 = 0x7
+set $STS_T32A = 0x9
+set $STS_T32B = 0xB
+set $STS_CG32 = 0xC
+set $STS_IG32 = 0xE
+set $STS_TG32 = 0xF
+
+define outputsts
+ while 1
+ if $arg0 == $STS_T16A
+ echo STS_T16A
+ loop_break
+ end
+ if $arg0 == $STS_LDT
+ echo STS_LDT\
+ loop_break
+ end
+ if $arg0 == $STS_T16B
+ echo STS_T16B
+ loop_break
+ end
+ if $arg0 == $STS_CG16
+ echo STS_CG16
+ loop_break
+ end
+ if $arg0 == $STS_TG
+ echo STS_TG\ \
+ loop_break
+ end
+ if $arg0 == $STS_IG16
+ echo STS_IG16
+ loop_break
+ end
+ if $arg0 == $STS_TG16
+ echo STS_TG16
+ loop_break
+ end
+ if $arg0 == $STS_T32A
+ echo STS_T32A
+ loop_break
+ end
+ if $arg0 == $STS_T32B
+ echo STS_T32B
+ loop_break
+ end
+ if $arg0 == $STS_CG32
+ echo STS_CG32
+ loop_break
+ end
+ if $arg0 == $STS_IG32
+ echo STS_IG32
+ loop_break
+ end
+ if $arg0 == $STS_TG32
+ echo STS_TG32
+ loop_break
+ end
+ echo Reserved
+ loop_break
+ end
+end
+
+# IA32 2007, Volume 3A, Table 3-1
+set $STA_X = 0x8
+set $STA_E = 0x4
+set $STA_C = 0x4
+set $STA_W = 0x2
+set $STA_R = 0x2
+set $STA_A = 0x1
+
+define outputsta
+ if $arg0 & $STA_X
+ # Code segment
+ echo code
+ if $arg0 & $STA_C
+ echo |STA_C
+ end
+ if $arg0 & $STA_R
+ echo |STA_R
+ end
+ else
+ # Data segment
+ echo data
+ if $arg0 & $STA_E
+ echo |STA_E
+ end
+ if $arg0 & $STA_W
+ echo |STA_W
+ end
+ end
+ if $arg0 & $STA_A
+ echo |STA_A
+ else
+ printf " "
+ end
+end
+
+# xv6-specific
+set $SEG_KCODE = 1
+set $SEG_KDATA = 2
+set $SEG_KCPU = 3
+set $SEG_UCODE = 4
+set $SEG_UDATA = 5
+set $SEG_TSS = 6
+
+define outputcs
+ if ($arg0 & 4) == 0
+ if $arg0 >> 3 == $SEG_KCODE
+ printf "SEG_KCODE<<3"
+ end
+ if $arg0 >> 3 == $SEG_KDATA
+ printf "SEG_KDATA<<3"
+ end
+ if $arg0 >> 3 == $SEG_KCPU
+ printf "SEG_KCPU<<3"
+ end
+ if $arg0 >> 3 == $SEG_UCODE
+ printf "SEG_UCODE<<3"
+ end
+ if $arg0 >> 3 == $SEG_UDATA
+ printf "SEG_UDATA<<3"
+ end
+ if $arg0 >> 3 == $SEG_TSS
+ printf "SEG_TSS<<3"
+ end
+ if ($arg0 >> 3 < 1) + ($arg0 >> 3 > 6)
+ printf "GDT[%d]", $arg0 >> 3
+ end
+ else
+ printf "LDT[%d]", $arg0 >> 3
+ end
+ if ($arg0 & 3) > 0
+ printf "|"
+ outputdpl ($arg0&3)
+ end
+end
+
+define outputdpl
+ if $arg0 == 0
+ printf "DPL_KERN"
+ else
+ if $arg0 == 3
+ printf "DPL_USER"
+ else
+ printf "DPL%d", $arg0
+ end
+ end
+end
+
+define printdesc
+ if $argc != 1
+ echo Usage: printdesc expr
+ else
+ _printdesc ((uint*)&($arg0))[0] ((uint*)&($arg0))[1]
+ printf "\n"
+ end
+end
+
+document printdesc
+Print an x86 segment or gate descriptor.
+printdesc EXPR
+EXPR must evaluate to a descriptor value. It can be of any C type.
+end
+
+define _printdesc
+ _printdesc1 $arg0 $arg1 ($arg1>>15&1) ($arg1>>13&3) ($arg1>>12&1) ($arg1>>8&15)
+end
+
+define _printdesc1
+ # 2:P 3:DPL 4:S 5:Type
+ if $arg2 == 0
+ printf "P = 0 (Not present)"
+ else
+ printf "type = "
+ if $arg4 == 0
+ # System segment
+ outputsts $arg5
+ printf " (0x%x) ", $arg5
+ _printsysdesc $arg0 $arg1 $arg5
+ else
+ # Code/data segment
+ outputsta $arg5
+ printf " "
+ _printsegdesc $arg0 $arg1
+ end
+
+ printf " DPL = "
+ outputdpl $arg3
+ printf " (%d)", $arg3
+ end
+end
+
+define _printsysdesc
+ # 2:Type
+ # GDB's || is buggy
+ if ($arg2 == $STS_TG) + (($arg2&7) == $STS_IG16) + (($arg2&7) == $STS_TG16)
+ # Gate descriptor
+ _printgate $arg2 ($arg0>>16) ($arg0&0xFFFF) ($arg1>>16)
+ else
+ # System segment descriptor
+ _printsegdesc $arg0 $arg1
+ end
+end
+
+define _printgate
+ # IA32 2007, Voume 3A, Figure 5-2
+ # 0:Type 1:CS 2:Offset 15..0 3:Offset 31..16
+ printf "CS = "
+ outputcs $arg1
+ printf " (%d)", $arg1
+
+ if (($arg0&7) == $STS_IG16) + (($arg0&7) == $STS_TG16)
+ printf " Offset = "
+ output/a $arg3 << 16 | $arg2
+ end
+end
+
+define _printsegdesc
+ # IA32 20007, Volume 3A, Figure 3-8 and Figure 4-1
+ _printsegdesc1 ($arg0>>16) ($arg1&0xFF) ($arg1>>24) ($arg0&0xFFFF) ($arg1>>16&15) ($arg1>>23&1)
+ if ($arg1>>12&1) == 1
+ printf " AVL = %d", $arg1>>20&1
+ if ($arg1>>11&1) == 0
+ # Data segment
+ if ($arg1>>22&1) == 0
+ printf " B = small (0) "
+ else
+ printf " B = big (1) "
+ end
+ else
+ # Code segment
+ printf " D = "
+ if ($arg1>>22&1) == 0
+ printf "16-bit (0)"
+ else
+ printf "32-bit (1)"
+ end
+ end
+ end
+end
+
+define _printsegdesc1
+ # 0:Base 0..15 1:Base 16..23 2:Base 24..32 3:Limit 0..15 4:Limit 16..19 5:G
+ printf "base = 0x%08x", $arg0 | ($arg1<<16) | ($arg2<<24)
+ printf " limit = 0x"
+ if $arg5 == 0
+ printf "%08x", $arg3 | ($arg4<<16)
+ else
+ printf "%08x", (($arg3 | ($arg4<<16)) << 12) | 0xFFF
+ end
+end
+
+define printdescs
+ if $argc < 1 || $argc > 2
+ echo Usage: printdescs expr [count]
+ else
+ if $argc == 1
+ _printdescs ($arg0) (sizeof($arg0)/sizeof(($arg0)[0]))
+ else
+ _printdescs ($arg0) ($arg1)
+ end
+ end
+end
+
+document printdescs
+Print an array of x86 segment or gate descriptors.
+printdescs EXPR [COUNT]
+EXPR must evaluate to an array of descriptors.
+end
+
+define _printdescs
+ set $i = 0
+ while $i < $arg1
+ printf "[%d] ", $i
+ printdesc $arg0[$i]
+ set $i = $i + 1
+ end
+end