diff options
| -rw-r--r-- | gdbutil | 291 | 
1 files changed, 291 insertions, 0 deletions
| @@ -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 | 
