291 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| # -*- 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
 | 
