9 Kernel Debugger
under construction
This chapter tries to describe the kernel debugger functionality and
interface. 9.1 Entering and Leaving the Kernel Debugger
There are several methods to enter kernel debugger. You can
- execute a L3 system call (SysDebug)
- raise a kernel error
- press scroll lock on keyboard
For the last method you have to have a debug version of the L3
kernel.
You can leave the kernel debugger by pressing `g` (go). 9.2 Entering Commands
The kernel debugger provides several commands. They usually consist of
a letter and some additional parameter. If a command consists of only
one letter, the command is executed by pressing the letter on the
keyboard.
If there are parameters for the command, you have to type the full
number of characters, space or enter to execute the command. For
instance the command `show thread control block` (t) can have no
parameter and a thread number. The thread number can be a short one or
a long one. So depending on the parameter you would have to type:
- no parameter: t[ <space> | <enter> ]
- a thread number: t5[ <space> | <enter> ]
- a long thread number: t12345
9.3 Tracing some Kernel Information
The kernel provides mechanisms for continously displaying of kernel
events like page faults, messages, idle times and other things.
- L+/L-
- Enable/Disable autolog. This funtion provides continous information
about kernel events on a statistical base.
- P+/P-
- Enable/Disable page fault display. This function provides a continous
display of page faults.
- T+/T-
- Enable/Disable tracing. (I don't know, what this function really does,
but you have to enable tracing to send output to the hercules screen.)
9.4 Information about kernel modules and addresses
The kernel debugger provides information about the L3 kernel modules, versions
and associated addresses. You can use this information to set breakpoint
base adresses or to find the associated address and module for a given
address.
- a
- Show all modules with name, offset and version. The output has the
format:
<offset> <modul name> <date>,<version>
- a<address>
- Look for module and the associated address within that modul for the
given address <address>. The output has the format:
<offset> <modul name> <date>,<version>
9.5 Breakpoints
The kernel debugger allows to set one (only one) breakpoint to an
arbitrary address. There are three different kinds of breakpoints,
- instruction breakpoints
- write access breakpoints
- (read/write) access breakpoints
You can combine a breakpoint with an additional condition or restrict
it to a distinct thread.
For ease of use you can use breakpoint offsets to set a breakpoint
within a module. If there is an offset in use, it will be displayed
while entering a breakpoint.
- b<enter>
- Show current breakpoint if there is one.
- bb<break point address>
- Set breakpoint base. This address serves as a base for all
following breakpoints and allows easier handling of breakpoints within
kernel modules. If you want to set a breakpoint within the kernel, you
have to add 0xf0000000 to the output of command m or an address
of kernel listings.
- bi<breakpoint address>
- Set an instruction breakpoint. The breakpoint is triggered before the
instruction is executed.
- bw, ba
- Set a write/access breakpoint. The breakpoint is triggered after
the instruction is executed. Breakpoints are attributed by size (1 (byte),
2 (word), 4 (dword)). The default size is byte.
You enter a breakpoint like follows:
ba/bw[<size> | <space>]at: [<breakpunkt base>+]<breakpoint address>
- b-
- Disable Breakpoint.
- bt<thread id>
- Restrict breakpoint to a distinct thread with id <thread id>. To
remove restriction enter bt0.
- bx
- Add a condition to a breakpoint. The breakpoint is only triggered if
the condition is true.
bx<size>monit:<address><space>[<value1>,<value2><space>]
Conditions are related to contents of memory allowing monitoring of a
distinct address. They are attributed with size. The breakpoint is
triggered if the memory contains a value within or out of a specified
range.
It depends on the values given to bx if the meaning is
within or out of.
- value1 < value2
- The breakpoint is triggered if for the content of memory holds
<value1> <= <content of memory> <= <value2>.
- value1 > value2
- The breakpoint is triggered if for the contents of memory holds
<value2> <= <content of memory> || <content of memory>
<= <value1>
9.6 Informationen about threads (tcb's, register contents, stack
contents, ...)
The kernel debugger provides mechanisms to examine the state of
threads. It supplies information like thread state, contents of wait
queues, register contents, stack contents and more.
While visiting the kernel stack you can change the visible area
by virtally changing the esp register using cursor keys. You can
virtually set register contents to the state just before kernel entry
using the <enter> key. The debugger executes a popa.
- t
- Show TCB of current thread.
- t<thread id>
- Show TCB of thread <thread id>
9.7 Inspecting Mappings
To fill up its own virtual memory a task has to map dataspaces. You
can inspect these mappings using the kernel debugger. There should be
at least three mappings, the mapping of the standard dataspace and two
mappings supplied by the kernel.
- m
- Show mappings of task of current thread. Thsi command provides
information about the memory mode of the task, about io permissions
and current mappings. The display looks like follows:
task:<task no> (<number> Threads, Root:<i don't know>)
mode:<mem mode, io mode> Limit:<number>
maphw base:<number>
hwmap max :<number> wrlck max:<number>
prsent lnk:
regions
[number] : [<start>,<end>] <map mode> ds:<number> mvec:<address>
...
Values of entries:
- mem mode
- Memory mode can have the following values:
- io mode
- Every task has its own io priviledges. That can be:
- unlimited io
- <no entry> - no io priviledges
- map mode
- Dataspaces can be mapped with two different modes, read write and read
only. There is an additional mode, which is specified for kernel
supplied mappings. There are no map vectors for standard dataspace and
kernel supplied mappings.
- rw - read write
- ro - read only
- XX - kernel area
- m<thread id>
- Show mappings of task of thread <thread id>.
- Cursor Keys
- Scroll through mappings.
9.8 Inspecting Memory
There are several mechanisms to inspect memory. You can inspect
address spaces, search for hex and ascii strings, change memory
contents and calculate the associated physical address for a given
virtual address.
There are two major modes for inspecting memory, disabled task
switching and enabled task switching. While task switching is disabled
you can only inspect virtual addresses, which are currently in
physical memory. To inspect any virtual address or any dataspace you
have to enable task switching to allow the pager to transfer the
necessary information from disk to memory.
- i/I
- Enter inspecting memory. Using i you enter memory inspection with
disabled task switching, using I with enabled task switching.
Commands for inspecting memory:
- i
- Specify a thread id. Format: <thread id>i<enter>
- l
- Specify a length to be displayed. Format: <length>l<enter>
- p
- Specify an address display starts with. Format: <address>p<enter>
- <enter>
- Redisplay block.
- +
- Go forward in steps of length l.
- -
- Go backward in steps of length l.
- :
- Set base address. Format: <address>:<enter>
- Cursor Keys
- Move within the displayed block. Once you have reached the desired
position you can change contents of memory entering arbitrary
values. By pressing <enter> you go back to normal memory inspection.
- x
- Search for memory contents. You can search for hex or asci strings.
- xh<hex value>{<space><hex value>}*<enter>
- Search for hex string <hex value>{<space><hex value>}*
- xc<ascii string><enter>
- Search for ascii string.
- <enter>
- Repeat last search operation.
- T
- Invoke nested kernel debugger, for instance to inspect a tcb without
leaving memory inspection. You can leave the nested kernel debug using
key h.
- t
- Invoke spvertest. You can leave spvertest with the key h.
Additional commands if task switch is enabled (I).
- s
- Specify a dataspace id. Format: <dataspace id>s<enter>
- k
- Load a block from backing storage. ???
- m
- Write a block to backing storage ???
- q
- Access task root ???
Marion Schalm, Jean Wolter, Michael Hohmuth
26.12.1995 (unfinished)