diff --git a/gdbutil b/gdbutil
new file mode 100644
index 0000000000000000000000000000000000000000..e0c362fbdb7d5acd8b774e7256a2aec2aeba4e89
--- /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