# -*- 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