home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
prgramer
/
info
/
kdebug.doc
< prev
next >
Wrap
Text File
|
1992-09-14
|
187KB
|
5,390 lines
IBM OS/2 2.0
KERNEL DEBUGGER
PRELIMINARY DRAFT
September 14, 1992
Issued by: David E. Reich
IBM Boca Raton
Tie line 982-0329
DREICH at BCRVMPC1
Prepared by: David E. Reich & Edd Doutre
+--- NOTE -----------------------------------------------------------+
| |
| Before using this information and the product it supports, be sure |
| to read the general information under "Notices" on page v. |
| |
+--------------------------------------------------------------------+
FIRST EDITION (APRIL 1992)
THE FOLLOWING PARAGRAPH DOES NOT APPLY TO THE UNITED KINGDOM OR ANY
COUNTRY WHERE SUCH PROVISIONS ARE INCONSISTENT WITH LOCAL LAW: INTER-
NATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS
IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do
not allow disclaimer of express or implied warranties in certain
transactions, therefore, this statement may not apply to you.
This publication could include technical inaccuracies or typographical
errors. Changes are periodically made to the information herein;
these changes will be incorporated in new editions of the publication.
IBM may make improvements and/or changes in the product(s) and/or the
program(s) described in this publication at any time.
It is possible that this publication may contain reference to, or
information about, IBM products (machines and programs), programming,
or services that are not announced in your country. Such references
or information must not be construed to mean that IBM intends to
announce such IBM products, programming, or services in your country.
Requests for technical information about IBM products should be made
to your IBM Authorized Dealer or your IBM Marketing Representative.
IBM may have patents or pending patent applications covering subject
matter in this document. The furnishing of this document does not
give you any license to these patents. You can send license
inquiries, in writing, to the IBM Director of Commercial Relations,
IBM Corporation, Purchase, NY 10577.
COPYRIGHT LICENSE: This publication contains printed sample applica-
tion programs in source language, which illustrate OS/2 programming
techniques. You may copy and distribute these sample programs in any
form without payment to IBM, for the purposes of developing, using,
marketing or distributing application programs conforming to the OS/2
application programming interface.
Each copy of any portion of these sample programs or any derivative
work, which is distributed to others, must include a copyright notice
as follows: "(C) (your company name) (year) All Rights Reserved."
(C) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 1992. ALL
RIGHTS RESERVED.
Note to U.S. Government Users -- Documentation related to restricted
rights -- Use, duplication or disclosure is subject to restrictions
set forth in GSA ADP Schedule Contract with IBM Corp.
CONTENTS
________
INTRODUCTION 1
Conventions and Symbols 2
Entering the Debugger 2
Expressions 3
Numbers 7
Strings 8
Symbol Files 8
TIPS FOR USING THE KERNEL DEBUGGER 11
KERNEL DEBUGGER COMMANDS 15
Breakpoint Commands 15
BREAKPOINT (BP) 15
COMPARE 17
DUMP 17
ENTER 20
FILL 21
GO 21
Help/Print Expression 22
HEX 22
INPUT 22
List Near Symbol 22
List Groups 23
List Maps 23
List Absolute Symbols 23
List Symbols 23
Add/Remove Active Map 23
Conditional Execution 23
Stack Trace 24
MOVE 24
OUTPUT 25
PTRACE 25
REGISTER 26
SEARCH 28
TRACE 28
UNASSEMBLE 29
Interrupt and Trap Vector 30
Debugger Option 31
Default Command Lines 32
External Debugger Commands 33
Help 33
COM Port Baud Rate 33
Dump ABIOS Common Data Area 33
Dump OS/2 Data Structures 34
Swap in TSD or Page 34
User Stack Trace 35
Print MTE Segment Table 35
Memory Arena Record Dump 36
Contents iii
Memory Context Record Dump 37
Memory Alias Record Dump 37
Memory Object Record Dump 38
Memory Page Frame Dump 39
Memory Virtual Page Structure Dump 40
Print Process Status 40
User Register 41
REBOOT 41
Task Context Change 41
RAS Trace Buffer Print 42
ADVANCED KERNEL DEBUGGER TECHNIQUES 43
Setting Useful Breakpoints 43
Debugging Kernel Device Drivers 52
Debugging VM Start Sessions 53
Debugging CMD.EXE 54
SETUP FOR REMOTE DEBUGGING 55
Items Required to Set Up a System for Remote
Debugging 55
Target System 55
IBM 5853 Modem 56
Modem Data Cable 56
Analog Dial-in Telephone Line 57
Communications Software 57
The Configuration Process 57
Limitations of this Setup 60
Problem Determination 60
APPENDIX A. SAMPLE DEBUGGING SESSION 63
INDEX 69
iv OS/2 Kernel Debugger
NOTICES
_______
References in this publication to IBM products, programs,
or services do not imply that IBM intends to make these
available in all countries in which IBM operates. Any
reference to an IBM product, program, or service is not
intended to state or imply that only IBM's product,
program, or service may be used. Any functionally equiv-
alent product, program, or service that does not infringe
any of IBM's intellectual property rights or other
legally protectible rights may be used instead of the IBM
product, program, or service. Evaluation and verifica-
tion of operation in conjunction with other products,
programs, or services, except those expressly designated
by IBM, are the user's responsibility.
TRADEMARKS
__________
The following terms, denoted by an asterisk (*) in this
publication, are trademarks of the IBM Corporation in the
United States or other countries, or both:
IBM
Operating System/2
OS/2
PS/2
The following terms, denoted by a double asterisk (**) in
this publication, are trademarks of another company as
follows:
Hayes Hayes Microcomputer Products, Inc.
Intel Intel Corporation
80286 Intel Corporation
80287 Intel Corporation
80386 Intel Corporation
Windows Microsoft Corporation
DOUBLE-BYTE CHARACTER SET (DBCS)
________________________________
Throughout this publication, you will see references to
specific values for character strings. The values are
for the single-byte character set (SBCS). If you use the
double-byte character set (DBCS), note that one DBCS
character equals two SBCS characters.
Notices v
vi OS/2 Kernel Debugger
PREFACE
_______
ABOUT THIS BOOK
_______________
This document describes the use of the kernel debugger
functions in the OS/2 2.0 system.
This release of the OS/2 2.0 toolkit contains a copy of
the OS/2 2.0 debugging kernel. It is included to assist
you in debugging your applications and drivers until
higher-level debuggers such as IPMD can provide adequate
debugging functions in complex situations.
The kernel debugger is a low-level debugger oriented
toward system and device-driver debugging.
The use of this kernel is supported as an aid in debug-
ging your software. We offer support for the installa-
tion and use of the debugging kernel and its commands and
syntax.
ORGANIZATION OF THIS BOOK
_________________________
"INTRODUCTION" ON PAGE 1
This chapter contains information about:
o Conventions and Symbols
o Entering the Debugger
o Expressions
o Numbers
o Strings
o Symbol Files
"TIPS FOR USING THE KERNEL DEBUGGER" ON PAGE 11
This chapter contains tips for using the kernel
debugger.
"KERNEL DEBUGGER COMMANDS" ON PAGE 15
This chapter describes the commands of the
kernel debugger.
"ADVANCED KERNEL DEBUGGER TECHNIQUES" ON PAGE 43
This chapter describes some advanced techniques
for using the kernel debugger.
Preface vii
"SETUP FOR REMOTE DEBUGGING" ON PAGE 55
This chapter describes how to set up a system
for remote debugging.
APPENDIX A, "SAMPLE DEBUGGING SESSION" ON PAGE 63
This appendix shows a sample debugging session.
viii OS/2 Kernel Debugger
INTRODUCTION
____________
The kernel debugger is derived from the DEBUG and SYMDEB
debuggers, with enhancements to handle both real-mode and
protected-mode operation. Most of the commands and
structure of this debugger are the same as for DEBUG and
SYMDEB. This document describes most of the kernel
debugger's commands and new features.
The kernel debugger is actually a version of the
OS/2(*) 2.0 kernel that has a user interface included in
the kernel itself. This interface always gets its input
from an asynchronous port, usually COM2 or COM1, and
always prints its output to the same asynchronous port.
The debugger and user interface actually amount to about
80KB (where KB equals 1024 bytes) of code and data.
However, there are two versions of the debug kernel - the
'AllStrict' kernel and the 'HStrict' kernel.
The 'HStrict' kernel is about 795KB, and is simply the
retail kernel with the debugger interface added. The
retail kernel is about 710KB.
The 'AllStrict' kernel is about 965KB. The additional
170KB is error checking code and messages to catch errors
and cause an IPE (Internal Processing Error) when a
retail or HStrict kernel would have let the error pass,
or would have returned it to the application program.
This results in a very "picky" operating system, from an
applications point of view, but it is important to catch
these types of problems early and provide error recovery
code in the retail versions. All this error checking
makes it much easier to find and fix problems when the
testers are running the 'AllStrict' kernel.
The debugger normally uses COM2 for its input and output,
but if no COM2 exists, it looks for a COM1 port. If
neither COM1 or COM2 exists, it looks for any other COM
port in the ROM data area (40:0). A three-wire null
modem cable is all that is needed, with pins 2 and 3
switched on one end of the cable. A full null modem
cable works as well.
An asynchronous modem can be used to set up a remote
debugging session. In a remote debugging session, you
---------------
(*) Trademark of the IBM Corporation.
Introduction 1
call over a telephone line to the system that has the
problem. This allows you to solve problems at remote
locations, using the kernel debugger. For example, prob-
lems in Germany, England, Spain, South America, and Iowa
have been solved with remote debugging sessions.
See "Setup for Remote Debugging" on page 55 for more
information about remote debugging.
CONVENTIONS AND SYMBOLS
Most commands are one or two characters, with one-
character options. The semicolon character (;) is the
command separator, and the comma (,) or a blank is the
operand separator.
When the syntax of the command is shown, the following
conventions are used:
o Arguments between square brackets ([ ]) are optional.
o A horizontal bar (|) indicates that either argument
is acceptable.
The definitions of some of the arguments used in the com-
mands are as follows:
<range> = <addr> [<word>] | [<addr>] [L <word>]
<addr> = [& | #][<word>:]<word> | %<dword>
<list> = <byte>, <byte>, ... | "string"
<string> = "char" | 'char'
<dword>, <word>, <byte> = expressions that evaluate
to the size indicated in the symbols <>.
ENTERING THE DEBUGGER
There are various ways to get into the debugger. The
first way is during initialization. If the following
keys are pressed at the debugger's console, the debugger
is entered:
o "r" - (lowercase r) enters the debugger at the begin-
ning of system kernel initialization in real mode.
This is very early in system initialization.
o "p" - enters the debugger after we have gone into
protected mode for the first time. Symbols have not
been loaded yet.
2 OS/2 Kernel Debugger
o "<space-bar>" - enters the debugger after most of the
kernel has been initialized. Symbols for the system
kernel have been loaded.
After initialization is complete, the debugger can be
entered at any time by pressing Ctrl+C at the debugger's
console. The debugger is entered when and where the next
timer tick is taken after the keys were pressed.
An NMI (non-maskable interrupt) switch allows you to
break into the debugger even if interrupts are disabled.
Pressing Ctrl+C does not allow this.
An "INT 3" in the kernel or in a program also causes the
debugger to stop.
When a kernel panic occurs, a message is sent to both the
screen and the debugger port. Before sending the message
to the screen, the screen is cleared and set to text
mode. This can be a problem if you need to see how far a
test case got before crashing. If you set the byte flag
fDebugOnly to nonzero, the message goes to the debug port
__________
only, and the screen is left unchanged.
After symbols are loaded, an initialization file named
KDB.INI is read and executed. Any debugger command or
list of debugger commands can be in the KDB.INI file. A
"G" command should be at the end of the commands unless
you want the debugger to stop after the KDB.INI file is
executed.
EXPRESSIONS
The expression evaluator has been enhanced to provide
support for four types of addresses - real mode
(&segment:offset), protected mode (#selector:offset),
linear address (%dword) and physical address (%%dword).
The symbols "&", "#", "%", and "%%" override the current
address type, allowing selectors to be used in real mode,
segments to be used in protected mode, and so on. The
"%" linear address and the "%%" physical address operator
actually convert other address types to a linear or phys-
ical address. For example, %(#001F:0220) looks up
selector 1F's linear address in the current LDT, and adds
hex 0220 to it. Linear and physical addresses are the
same, unless paging is enabled on an 80386(**) processor.
o ? <expr> | "<string>"
---------------
(**) Trademark of the Intel Corporation.
Introduction 3
This command evaluates the expression, and prints it in
all the standard numerical bases, along with the ASCII
character for the value and an address' physical address.
It also prints an indication of whether the expression
evaluated to TRUE (nonzero) or FALSE (zero). It prints a
string if the string is surrounded by single or double
quotation marks.
#1F:02C0 Protected Mode address
&3450:1234 Real Mode address
%310230 Linear address
%%310230 Physical address
Addresses can be used in any mode. In real mode, you can
use protected mode addresses as long as there is an over-
ride. The default depends on the current debugger mode.
There are keywords that return the value of registers,
breakpoints, and so on in expressions. Here is a list of
them:
o AX, BX, CX, DX, SI, DI, BP, DS, ES, SS, CS, SP, IP -
register values
o FLG - value of the flags
o GDTB - value of the GDT base as a physical address
o GDTL - value of the GDT limit
o IDTB - value of the IDT base as a physical address
o IDTL - value of the IDT limit
o TR, LDTR, MSW - value of the TR, LDTR, and MSW regis-
ters
o BR0, BR1,..., BR9 - the address at that breakpoint.
The 80386 keywords are (in addition to the above):
o EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP -
extended register values
o FS, GS - segment registers
o EFLG - value of extend flags
o CR0, CR2, CR3 - control register values
o DR0, DR1, DR2, DR3, DR6, DR7 - debug register values
4 OS/2 Kernel Debugger
o TR6, TR7 - test register values.
These register names are searched for first, before the
symbol table is searched. The "@" character can override
the register name lookup, and cause a search of the
symbol table for the name. The term "@ax" causes a
search for a symbol called "ax", instead of evaluating to
the register value.
The operators that can be used in expressions are docu-
mented in the SYMDEB manual, except for the address oper-
ators (&, #, %) and the new relational operators. The
precedence of the operators has been changed to be more
like "C".
Operators in precedence order
1. ( )
2. | :
3. & # % %% - ! NOT SEG OFF BY WO DW POI
PORT WPORT (all unary operators)
4. * / MOD
5. + -
6. > < >= <=
7. == !=
8. AND XOR OR
9. && ||
Binary operator definitions
( ) Parentheses, used to change order of evalu-
ation
: Address binder, binds segment/selector and
offsets
* Multiplication
/ Division
MOD Modulo (remainder)
+ Addition
Introduction 5
- Subtraction
> Greater than relational operator
< Less than relational operator
>= Greater than or equal to relational oper-
ator
<= Less than or equal to relational operator
== Equal to operator
!= Not equal to relational operator
AND Bitwise AND
XOR Bitwise exclusive OR
OR Bitwise inclusive OR
&& Logical AND
|| Logical OR
Unary operator definitions
| Task number/address operator
& Address type is segment:offset
# Address type is selector:offset
% Address type is linear
%% Address type is physical
- Two's complement
! Logical NOT operator
NOT Bitwise one's complement
SEG Returns the segment portion
OFF Returns the offset portion
BY 1-byte value from the address
WO 2-byte value from the address
DW 4-byte value from the address
6 OS/2 Kernel Debugger
POI 4-byte address from the address
PORT 1-byte value from an 8-bit I/O port
WPORT 2-byte value from a 16-bit I/O port
If two or more operators have the same precedence, the
expression is evaluated from left to right, even for
unary operators. "C" evaluates unary operators from
right to left, which is more intuitive and easier to use.
Expressions such as "poi #60:133" must be written as
"poi (#60:133)" because of the way the debugger handles
unary operators.
Ranges are an address and either a length or an end.
"4544:0 L5" is address (4544:0) and a length of 5
objects. If you are dumping words, 5 words are dumped.
"#8:32 50" is a range of bytes from address "8:32" to and
including "8:50".
NOTE: On <ranges>, if the second address has a unary
operator such as "&" or "#", then it must be separated by
a comma from the first. Parentheses work as well, for
example:
>DB DS:40,%40000 Correct
>DB DS:40 (%40000) Correct
>DB DS:40 %40000 Incorrect
This is because of the way the expression evaluator
parses the input.
NUMBERS
The default base for numbers in the kernel debugger is 16
(hexadecimal). You can add a one-letter suffix to the
digits of a number to indicate the base of the number, as
shown in the following table. The term "nnnnnn" repres-
ents a number that consists of a variable number of
digits.
Introduction 7
+--------------+------------------+---------------------+
| Number | Base | Valid digits |
______ ____ ____________
+--------------+------------------+---------------------+
| nnnnnnY | Binary | 0 1 |
+--------------+------------------+---------------------+
| nnnnnnO | Octal | 0 1 2 3 4 5 6 7 |
+--------------+------------------+---------------------+
| nnnnnnQ | Octal | 0 1 2 3 4 5 6 7 |
+--------------+------------------+---------------------+
| nnnnnnT | Decimal | 0 1 2 3 4 5 6 7 8 9 |
+--------------+------------------+---------------------+
| nnnnnnH | Hexadecimal | 0 1 2 3 4 5 6 7 8 9 |
| | | A B C D E F |
+--------------+------------------+---------------------+
STRINGS
A string can be represented as follows:
o 'characters'
o "characters"
A string represents a list of ASCII values. It can be
any number of and combination of characters enclosed in
single (') or double (") quotation marks. The starting
and ending quotation marks must be the same type. If a
matching quotation mark appears inside the string, it
must be given twice to prevent the debugger from ending
the string too soon.
Examples:
o 'This is a string'
o "This is a string"
o 'This ''string'' is okay'
o "This ""string"" is okay"
SYMBOL FILES
The kernel debugger supports symbolic debugging. The
MAPSYM utility program converts a .MAP file to a .SYM
file. When a symbol file (generated with MAPSYM) is
loaded by the operating system, the debugger can use
public symbols in the operating system, executable pro-
grams, dynamic link libraries, or any device driver as
part of an expression. The disassembler and the BL
command also display addresses symbolically if the symbol
exists for the address.
8 OS/2 Kernel Debugger
The debugger uses the MAPSYM format for the symbol file.
The statement "MAPSYM MAPFILE.MAP" generates the .SYM
file "MAPFILE.SYM". The kernel's symbols must be on the
system boot drive in the root directory, in a file named
OS2KRNL.SYM. For device drivers, the .SYM file must be
in the same directory as the device driver file with the
.SYM extension.
To load symbols for a program or module, the .SYM file
must be in the same directory as the .EXE or .DLL file,
and the symbols will be loaded automatically.
The file name of the .SYM file must match that of the
executable (program, device driver or DLL) it corresponds
to.
There can be more than one symbol file loaded at one
time, and more than one currently "active". The "WA",
"WR" and "LM" commands control and list the currently
active map files. The term "map file" refers to the .SYM
file generated by MAPSYM. Each newly-loaded map file
starts in the active state.
The message "Symbols Linked (xxxxxxxx)" is printed when
there is a successful load of a symbol file. The
"xxxxxxx" is the map name listed in the "LM" command.
The message "Symbols Unlinked (xxxxxxxxx)" is printed
when a program that has loaded symbols exits and the
symbol file is removed.
Symbols are case insensitive. The "@" forces the string
to be looked up as a symbol rather than as a register
name.
Introduction 9
10 OS/2 Kernel Debugger
TIPS FOR USING THE KERNEL DEBUGGER
__________________________________
The kernel debugger is a compiled part of the kernel.
Connect a terminal to communications port 2 (COM2) to
receive output from the kernel debugger. To interrupt
the kernel debugger at any time, press Control and C
(Ctrl+C) on the terminal.
For more detailed information about these commands, see
"Kernel Debugger Commands" on page 15.
o ?
This command gets you a help screen, and '.?' gets you a
help screen for the extended commands.
o .P
This command displays all of the processes running in the
system. The left-hand column of this display shows the
'slot number', which is important for the '.ss' command.
When you set a breakpoint in an application, the current
debugger 'context' must be changed to that process. For
example, if you press Ctrl+C and you interrupt while
'BAR.EXE' is executing, but you want to set a breakpoint
in 'FOO.EXE', you must change the debugger context to
'FOO.EXE'.
o .SS [slot number]
Type '.p', find out the slot number of 'FOO.EXE', and
type '.ss [slot number]'. Now you can set breakpoints in
'FOO.EXE'. Since .DLLs have no 'process' associated with
them, in order to set a breakpoint in a .DLL you need to
be in the context of an application that is dynamically
linked to that .DLL.
o BP [addr]
This sets a break point at the address [addr]. [addr]
can be symbolic or numerical. For 32-bit applications,
this is a 32-bit address. For 16-bit applications, this
is a 16-bit address.
o BC [bp number]
o BD [bp number]
o BC *
Tips for Using the Kernel Debugger 11
o BD *
'BC [bp number]' clears a breakpoint, while 'BD' disables
it. 'BC *' clears all breakpoints, while 'BD *' disables
all breakpoints.
o DA [addr]
o DB [addr]
o DW [addr]
o DD [addr]
These stand for 'dump ASCII', 'dump byte', 'dump word'
and 'dump doubleword', respectively. These commands
display memory starting at address [addr]. 'DW [addr] L
20' displays hex 20 words starting at [addr].
o E [addr]
This allows you to edit memory (change memory contents)
at [addr].
o K
This gives a stack-frame backtrace of the current appli-
cation (even at ring 0).
o .K [slot number]
This gives a stack-frame backtrace of the thread in this
slot. If you are in ring 0, this causes a ring-3 back-
trace.
o DD SS:ESP
This dumps the stack data at the current top of the
stack. 'ESP' always points to the last thing pushed onto
the stack.
o DD SS:EBP
This is what links 'C' stack-frames together at any time.
The 'EBP' register points on the stack to where the old
'EBP' is saved. After 'EBP' on the stack, you get the
return address and then the parameters passed to the
function that is currently executing. References to
[EBP+n] refer to passed parameters, while references to
[EBP-n] refer to local variables.
o G
This means 'go' or execute.
12 OS/2 Kernel Debugger
o R
This dumps the register set. To set a register, type 'r
[reg] = value'. For example, 'r EAX = 6' puts 6 into
register EAX. To execute some code over again or jump
ahead in code, reset the instruction pointer by typing 'r
EIP=[addr]'.
o P
This process-steps through the code. This uses the "INT
3" type of stepping. This steps over function calls.
____
NOTE: If a function exits to an address other than the
return address (where the "INT 3" is waiting), you may
get unexpected results. Also watch out for conditional
jumps, loops, and reps.
o T
This single-steps through the code. This does not use
the "INT 3" type of stepping as 'p' does, but actually
steps into any function calls.
Tips for Using the Kernel Debugger 13
14 OS/2 Kernel Debugger
KERNEL DEBUGGER COMMANDS
________________________
There are many kernel debugger commands. These can
control execution of the system under test. This chapter
describes these commands.
BREAKPOINT COMMANDS
___________________
These commands are executed when a breakpoint is hit.
BREAKPOINT (BP)
There are two kinds of breakpoints in the kernel
debugger: temporary (sometimes called GO breakpoints) and
sticky. Temporary breakpoints are set when the GO
command is executed, and go away when the debugger is
entered again for any reason (hitting a GO or sticky
breakpoint, a trap or fault, and so on). Sticky break-
points are created, removed, and disabled with the com-
mands listed below.
If you set a breakpoint in an LDT segment when a thread
other than thread 1 is running, that breakpoint will be
moved to thread 1 when the current thread ends (so that
it can still be addressed). When thread 1 ends, the
breakpoint will be disabled, and its address marked as
invalid. When that task slot is reused, the breakpoint
can be enabled again, but it is not advisable to do so
unless you are sure that the new task has the same code
____
at that spot.
On an 80386 processor, the debug registers can be used in
a sticky breakpoint. See the BR command.
o BP[n] [<address>] [<passcount>] [<breakpoint com-
mands>]
This command sets a new breakpoint, or changes an old
sticky breakpoint. The "n" is an optional breakpoint
number to select an old breakpoint for changing or
forcing a new breakpoint to a certain number. If the
breakpoint number is omitted, the first available break-
point number is used. The number must be just after the
"BP", with no intervening space. It must be a digit from
'0' to '9'. There must be a space after the number. Up
to 10 breakpoints can be set. The address is required
for all new breakpoints. Either an address or a break-
point number can be used to change an existing break-
Kernel Debugger Commands 15
point. A breakpoint command or passcount can be added or
changed with commands such as BP0 "DB DS:ESI;R" or BP2 5.
A breakpoint command is a string of any debugger commands
that are executed when that breakpoint is hit. Semico-
lons (;) separate commands from one another. Everything
is forced to uppercase unless surrounded by single quota-
tion marks. Two single or double quotation marks remove
their special meaning.
A passcount greater than zero means that this breakpoint
must be executed that many times before the debugger
actually breaks. The default for passcount is zero.
o BR[<bp>] E|W|R|1|2|4 [<addr>] [<passcnt>] ["<bp
cmds>"]
This command sets an 80386 debug register. Debug regis-
ters can be used to break on data reads and writes, and
instruction execution (which is the same as a regular
breakpoint). Up to four debug registers can be set and
enabled at one time. Disabled BR breakpoints do not use
up a debug register. The flag definitions are:
Flag Description
____ ___________
1 One-byte length (default)
2 Word length on a word boundary
4 Doubleword length on a doubleword boundary
E Break on instruction execution only (one-byte
length only)
W Break on writes only
R Break on reads and writes
For one-byte breakpoints, the linear address alignment
does not matter, but for word-length breakpoints the
linear address must be on a word boundary. For a
doubleword-length breakpoint, the linear address must be
on a doubleword boundary. The debugger converts the
address to linear, and prints an error message if the
alignment is incorrect.
Only addresses that can be converted to linear (segment,
selector, and linear, but not physical) can be used in
the BR command address. The rest of the arguments are
exactly like a BP command.
o BT[<n>] [<address>]
16 OS/2 Kernel Debugger
This command sets a time-stamping breakpoint.
o BS
This command shows the time stamp entries.
o BL
This command lists the currently set breakpoints along
with the current and original passcount and the break-
point command, if any. An "e" after the breakpoint
number means that the breakpoint is enabled; a "d" means
that it is disabled. After either one of those, there
may be an "I" which indicates that the address was
invalid the last time the debugger tried to set or clear
the breakpoint.
o BC[n],[n],...
Removes (clears) the list of breakpoint numbers from the
debugger's breakpoint table.
o BE[n],[n],...
Enables the list of breakpoint numbers.
o BD[n],[n],...
Disables the list of breakpoint numbers, so the break-
point is not actually put into the code, but is saved
until it is enabled.
COMPARE
o C <range> <addr>
This command compares the bytes in the memory location
specified by <range> with the corresponding bytes in the
memory locations beginning at <addr>. If all corre-
sponding bytes match, the kernel debugger displays its
prompt and waits for the next command. If one or more
corresponding bytes do not match, each pair of mismatched
bytes is displayed.
DUMP
o D [<range>]
Dumps memory in the last format used.
o DA [<range>]
Kernel Debugger Commands 17
Dumps memory in ASCII format only.
o DB [<range>]
Dumps memory in bytes and ASCII.
o DW [<range>]
Dumps memory in words.
o DD [<range>]
Dumps memory in doublewords.
o DG[A] [<range>]
This command dumps the global descriptor table (GDT).
The "A" option causes all the entries to be dumped (not
just the valid entries). The default is to display only
the valid GDT entries. A range of entries or just one
GDT entry can be displayed. If the command is passed an
LDT selector, it displays "LDT" and the appropriate LDT
entry.
o DI[A] [<range>]
This command dumps the interrupt descriptor table. The
"A" option causes all the entries to be dumped (not just
the valid entries). The default is to display just the
valid IDT entries. A range of entries or just one IDT
entry can be displayed.
o DL[A|P|S|H] [<range>]
This command dumps the local descriptor table. The "A"
option causes all the entries to be dumped (not just the
valid entries). The default is to display just the valid
LDT entries. A range of entries or just one LDT entry
can be displayed. If the command is passed a GDT
selector, it displays "GDT" and the appropriate GDT
entry.
The options P, S, and H are used to dump private, shared,
or huge segment selectors respectively. To dump the huge
segment selectors, give the shadow selector, followed by
the maximum number of selectors reserved for that
segment, plus 1.
o DP[A|D] [<range>]
This command dumps the page directory and page tables.
Page tables are always skipped if the corresponding page
directory entry is not present. Page directory entries
appear with an asterisk next to the page frame, and are
18 OS/2 Kernel Debugger
dumped once preceding a 4-megabyte region. As a general
rule, you can ignore any lines beginning with an
asterisk.
The "A" option dumps all present page directory and page
table entries; the default is to skip page directory and
page table entries that are zero. A zero page table
entry means that the page is uncommitted.
The "D" option dumps only page directory entries. If a
count is given as part of the optional range, it is
interpreted as a page directory entry count. For
example:
##dp ff000 l4
linaddr frame pteframe state res Dc Au CD WT Us rW Pn state
%000ff000* 00343 frame=00343 2 0 D A U W P resident
%000ff000 000ff frame=000ff 1 0 c A U W P uvirt
%00100000 002ae frame=002ae 0 0 c A U W P pageable
%00101000 00215 vp id=0083c 0 0 c u U W n pageable
%00102000 vp id=0083d 0 0 c u U W n pageable
bit bit
set clear
--- -----
key: D c Dirty / clean
A u Accessed / unaccessed
U s User / supervisor
W r Writable / read-only
P n Present / not-present
The PTEFRAME field contains the contents of the high-
order 20 bits in the PTE. If the page is present, that
value is the high-order 20 bits of the physical address
that the page maps. To find out information about that
physical address, you can issue the .MP command. If the
page is not present, the PTEFRAME field contains an index
into the Virtual Page (VP) structure. The .MV command
can dump information from that structure. A non-present
page may still be cross-linked to a page of physical
memory via the VP, and if it is, that physical address is
in the FRAME column.
An exception is that uvirt pages (noted in the STATE
_____
column) are direct mappings of physical memory, without
any other page manager structures associated with them.
o DT [<addr>]
This command dumps the TSS. If no address is given, it
dumps the current TSS pointed to by the TR register,
extracting the type (16-bit or 32-bit) from the
Kernel Debugger Commands 19
descriptor access byte. If an address is given, the type
is extracted from the 386env flag.
o DX
This command dumps the 80286(**) loadall buffer.
ENTER
o E <addr> [<list>]
This command enters one or more byte values into memory
at the specified <addr>. If the optional <list> is
given, the command replaces the byte at the given address
and the bytes at each subsequent address until all values
in the list have been used. If no <list> is given, the
command prompts for a replacement value.
If an error occurs, all byte values remain unchanged.
If you do not supply a <list>, the kernel debugger
prompts for a new value at <addr> by displaying this
address and its current value followed by a dot (.). You
can then replace the value, skip to the next value,
return to a previous value, or exit the command by fol-
lowing these steps:
1. To replace the byte value, simply type the new value
after the current value. Make sure you type a
1-digit or 2-digit hexadecimal number. The command
ignores extra trailing digits or other characters.
2. To skip to the next byte, press the Spacebar. Once
you have skipped to the next byte, you can change its
value or skip to the next byte. If you skip beyond
an 8-byte boundary, the kernel debugger starts a new
display line by displaying the new address and value.
3. To return to the preceding byte, type a hyphen (-).
When you return to the preceding byte, the kernel
debugger starts a new display line with the address
and value of that byte.
4. To exit the E command, press Return. You can exit
the command at any time.
---------------
(**) Trademark of the Intel Corporation.
20 OS/2 Kernel Debugger
FILL
o F <range> <list>
This command fills the addresses in the given <range>
with the values in the <list>. If the range specifies
more bytes than the number of values in the list, the
list is repeated until all bytes in the range are filled.
If <list> has more values than the number of bytes in the
range, the command ignores any extra values.
GO
o G[S][T][=<start-address>][<break-address>],,,
This command passes execution control to the program at
the given <start-address>. Execution continues to the
end of the code or until a <break-address> is encount-
ered. The debuggee code also stops at any breakpoints
set using the Breakpoint Set command.
If no <start-address> is given, the command passes exe-
cution to the address specified by the current values of
CS and IP registers. The equal sign (=) may be used only
when a <start-address> is given.
If a <break-address> is given, it must specify an
instruction address (that is, the address must contain
the first byte of an instruction opcode). Up to ten
addresses can be given at one time. The addresses can be
given in any order. Only the first address encountered
during execution causes a break. All others are ignored.
If you attempt to set more than ten breakpoints, an error
message is displayed.
The "S" option prints the time (in PERFVIEW timer ticks)
from when the system is started with GS until the next
entry to the debugger. No attempt is made to calculate
and remove debugger overhead from the measurement.
The "T" option allows trapped exceptions to resume at the
original trap handler address without having to unhook
the exception. Instead of issuing the "vcp d; t; vsp d"
commands, you can use the "T" option of the GO command.
When execution of the debuggee code reaches a breakpoint,
the kernel debugger normally displays the current values
of the registers and flags. It also displays the next
instruction to be executed. If the default command (Z)
has been changed to something other than the REGISTER (R)
command, the debugger executes the command list set by
the last ZS command.
Kernel Debugger Commands 21
HELP/PRINT EXPRESSION
o ?[<expr>]|'string'
This command prints help if no arguments are given. If
an expression is given, it prints the value of the evalu-
ated expression in all bases. If a string is given, it
prints the string on the console.
HEX
o H <value1> <value2>
This command displays the sum and difference of two
hexadecimal numbers. The debugger adds <value1> to
<value2> and displays the result. It then subtracts
<value2> from <value1> and displays that result. The
results are displayed on one line, and are always in
hexadecimal. See the Help/Print Expression command for a
more general expression display.
INPUT
o I <port>
This command reads and displays one byte from the given
input <port>. The <port> can be any 16-bit port address.
LIST NEAR SYMBOL
o LN [<addr>]
This command lists the nearest symbol both forward from
and back to the address passed. The default is the
current disassembly address. All the active maps are
searched.
There is the possibility that there will be duplicates
when <addr> is specified as a selector:offset. Make sure
that you have selected the correct slot (with the .S
command) before you issue the LN command with a
selector:offset.
22 OS/2 Kernel Debugger
LIST GROUPS
o LG [<mapname>]
This command lists the selector or segment and the name
for each group in the active maps or the specified map.
LIST MAPS
o LM
This command lists all the current symbol files that are
loaded, and shows which ones are active.
LIST ABSOLUTE SYMBOLS
o LA [<mapname>]
This command lists all the absolute symbols in the active
maps or the specified map.
LIST SYMBOLS
o LS <addr>
This command lists all the symbols in the group that the
address is in.
ADD/REMOVE ACTIVE MAP
o WA <mapname> | *
o WR <mapname> | *
"WA" adds a map to the active list. "WR" removes it.
The "LM" command displays the names of map files that are
available. "*" means all maps. All maps start actively
when first linked.
CONDITIONAL EXECUTION
o J <expr> [<command list>]
This command executes the command list if the expression
evaluates to TRUE (nonzero). Otherwise, it continues to
the next command in the command line (not including the
ones in the "command list"). The command list must be in
single or double quotation marks if there is more than
more command (separated by ";"). A single command, or no
Kernel Debugger Commands 23
command, can also be used without quotation marks. This
command can be used in breakpoint commands to condi-
tionally break when an expression becomes true, or even
in the default command (Z).
The command BP 167:1454 "J AX == 0;G" breaks when AX
equals zero when this breakpoint is hit.
The command BP 167:1452 "J BY (DS:SI+3) == 40 'R;G';DG
DS" prints the registers and continues execution, if when
this breakpoint is hit the byte pointed to by "DS:SI+3"
is equal to 40. Otherwise, it prints the descriptor
table entry in DS.
The command BP 156:1455 "J (MSW AND 1) == 1 'G'" breaks
when the breakpoint is reached in real mode. BP 156:1455
"J (MSW AND 1)" is a shortcut that does the same thing
(like "C" boolean expressions).
See the default command (Z) for more examples.
STACK TRACE
o K[S|B] [<SS:EBP>] [<CS:EIP>]
This command threads through the BP chain on the stack
and prints the address, 4 words or doublewords of parame-
ters, and any symbol found for the address. The starting
stack frame address (SS:EBP) and the initial code segment
(CS:EIP) can be specified. Defaults are SS:EBP and
CS:EIP. The "S" (Small) option indicates that the frame
is 16 bits wide, and the "B" (Big) option indicates that
the frame is 32 bits wide. The default depends on the D
bit in the CS selector.
MOVE
o M <range> <addr>
This command moves the block of memory specified by
<range> to the location starting at <addr>.
All moves are guaranteed to be performed without data
loss, even when the source and destination blocks
overlap. This means the destination block is always an
exact duplicate of the original source block. If the
destination block overlaps some portion of the source
block, the original source is changed.
To prevent data loss, this command copies data from the
source block's lowest address first whenever the source
is at a higher address than the destination. If the
24 OS/2 Kernel Debugger
source is at a lower address, this command copies data
from the source's highest address first.
OUTPUT
o O <port> <byte>
This command sends the given <byte> to the specified
output <port>. The <port> can be any 16-bit port
address.
PTRACE
o P[N|T] [=<start-address>] [<count>]
This command executes the instruction at the given
<start-address>, and then displays the current values of
the all the registers and flags (or whatever the Z
command has been set to).
The difference between PTRACE and TRACE commands is that
PTRACE stops after instructions such as CALL, REP MOVSB,
and so on, instead of tracing into the call or each rep
string operation.
If the optional <start-address> is given, the command
starts execution at the given address. Otherwise, it
starts execution at the instruction pointed to by the
current CS and IP registers. The equal sign (=) may be
used only if a <start-address> is given.
If the optional <count> is given, the command continues
to execute <count> instructions before stopping. The
command displays the current values of the registers and
flags for each instruction before executing the next.
The "N" option suppresses the register display, so that
only the assembly line is displayed. This only works if
the "default command" (see the Z command) is an "R" (the
normal setting).
The "T" option allows the original trap handler address
to be traced into without having to unhook the exception.
Instead of issuing the "vcp d; t; vsp d" commands, you
can use the "T" option of the PTRACE command.
Kernel Debugger Commands 25
REGISTER
o R[T][<register-name> [<value>]]
This command displays the contents of a CPU register, and
allows the contents to be changed to a new value.
The "T" option toggles the "regterse" flag (see the Y
command).
If no <register-name> is given, the command displays all
the registers, flags, and the instruction at the address
pointed to by the current CS and IP register values.
If a <register-name> is given, the command displays the
current value of the given register, and prompts for a
new value. If both a <register-name> and <value> are
given, the command changes the register to the given
value.
The <register-name> can be any one of the following
names:
o AX, BX, CX, DX, SI, DI, BP, SP, IP, PC - general reg-
isters.
o DS, ES, SS, CS - segment registers.
o GDTB - GDT base as a linear address.
o GDTL - GDT limit.
o IDTB - IDT base as a linear address.
o IDTL - IDT limit.
o TR, LDTR - TR, LDTR registers.
o IOPL - input/output privilege level portion of flag
registers.
o F - flag register.
o MSW - Machine status word.
The 80386 <register-names> are the following (in addition
to the above):
o EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP -
extended general registers.
o FS, GS - segment registers.
o EF - extended flag register.
26 OS/2 Kernel Debugger
o CR0, CR2, CR3 - control registers.
o DR0, DR1, DR2, DR3, DR6, DR7 - debug registers.
o TR6, TR7 - test registers.
IP and PC name the same register - the Instruction
Pointer. F is a special name for the Flags register.
To change a register value, supply name of the register
when you enter the REGISTER command. If you do not also
supply a value, the command displays the name of the reg-
ister, its current value, and a colon prompt. Type the
new value, and press Return. If you do not want to
change the value, just press Return. If you enter an
illegal name, the command displays an error message.
To change a flag value, supply the register name "F" when
you enter the REGISTER command. The command displays the
current value of each flag as a two-letter name. The
following is a table of flag values:
+----------------------------------------------------------------+
| Table 1. Values for the Flag Register |
+------------------+----------------------+----------------------+
| FLAG | SET | CLEAR |
+------------------+----------------------+----------------------+
| Overflow | OV | NV |
+------------------+----------------------+----------------------+
| Direction | DN (Decrement) | UP (Increment) |
+------------------+----------------------+----------------------+
| Interrupt | EI (Enabled) | DI (Disabled) |
+------------------+----------------------+----------------------+
| Sign | NG (Negative) | PL (Plus) |
+------------------+----------------------+----------------------+
| Zero | ZR | NZ |
+------------------+----------------------+----------------------+
| Aux Carry | AC | NA |
+------------------+----------------------+----------------------+
| Parity | PE (Even) | PO (Odd) |
+------------------+----------------------+----------------------+
| Carry | CY | NC |
+------------------+----------------------+----------------------+
| Nested Task | NT | (toggles) |
+------------------+----------------------+----------------------+
At the end of the list of values, the command displays a
hyphen (-). When you see the hyphen, enter new values
for the flags you want to change, then press Return. You
can enter flag values in any order. Spaces between
values are not required. Flags for which new values are
not entered remain unchanged. If you do not want to
change any flags, just press Return.
Kernel Debugger Commands 27
If you enter a name other than those shown above, the
command prints an error message. The flags up to the
error are changed; flags at and after the error are not.
Changing the MSW (Machine Status Word) is the same as
changing the flag registers, but with the following flag
names:
+------------------------------------------------------------+
| Table 2. Values for the Machine Status Word |
+----------------------------------+--------+----------------+
| FLAG | SET | CLEAR |
+----------------------------------+--------+----------------+
| Protected Mode | PM | (toggles) |
+----------------------------------+--------+----------------+
| Monitor Processor Extension | MP | (toggles) |
+----------------------------------+--------+----------------+
| Emulate Processor Extension | EM | (toggles) |
+----------------------------------+--------+----------------+
| Task Switched | TS | (toggles) |
+----------------------------------+--------+----------------+
"Toggles" means that if the flag is set, using the flag
name in the REGISTER command clears it. If the flag is
clear, using the flag name in the REGISTER command sets
it.
SEARCH
o S <range> <list>
This command searches the given <range> of memory
locations for the byte values given in <list>. If the
bytes in the list are found, the command displays the
address of each occurrence of the list. Otherwise, it
displays nothing.
The <list> can have any number of bytes. Each must be
separated by a space or comma. If the list contains more
than one byte, this command does not display an address
unless the bytes beginning at that address exactly match
the value and order of the bytes in the list.
TRACE
o T[A|C|N|S|T|X][=<start-address>][<count>][<addr>]
This command executes the instruction at the given
<start-address>, then displays the current values of all
the registers and flags.
28 OS/2 Kernel Debugger
If the optional <start-address> is given, the command
starts execution at the given address. Otherwise, it
starts execution at the instruction pointed to by the
current CS and IP registers. The equal sign (=) may be
used only if a <start-address> is given.
If the optional <count> is given, the command continues
to execute a number of instructions equal to <count>
before stopping. The command displays the current values
of the registers and flags for each instruction before
executing the next instruction.
The "A" option allows the user to specify an ending
address for the trace. Instructions are traced until
[<addr>] is reached.
The "C" option suppresses all output, and counts
instructions traced. An end address is required for this
command.
The "N" option suppresses the register display, so that
only the assembly line is displayed. This only works if
the "default command" (see the Z command) is an "R" (the
normal setting).
The "S" (special trace) option is identical to the "C"
option, except that the instruction and count are dis-
played for every call and the return from that call.
The "T" option allows original trap handler address to be
traced into without having to unhook the exception.
Instead of issuing the "vcp d; t; vsp d" commands, you
can use the "T" option of the TRACE command.
The "X" option forces the debugger to trace regions of
code known to be untraceable (for example,
_PGSwitchContext).
UNASSEMBLE
o U [<range>]
This command displays the instructions in a mnemonic
format. All the 80386(**) and 80387(**) opcodes can be
displayed.
If given a <range>, the specified address is displayed
for the number of bytes specified. If the <range> con-
---------------
(**) Trademark of the Intel Corporation.
Kernel Debugger Commands 29
tains the "L" option (for example, u 90:234 l3), this
specifies the number of lines to display.
INTERRUPT AND TRAP VECTOR
o VL[N | P | V | R | F]
This command lists the real and protected mode vectors
that the debugger intercepts. Vectors that have been set
with VT (rather than with VS) are printed with an
asterisk following the vector number. VLR lists only the
real mode vectors, and VLP lists only the protect mode
vectors. VL lists both, as follows:
R 0 1 2 3 4 5 6
V 0 1 2
P 0 1 2 3 4 5 6 7 8* 9 A B
The "N" (Noisy) option lists the traps that beep when
hit.
The "F" (Fatal) option causes the kernel to route the
faults that are fatal to a process to the debugger
instead of displaying the popup message. For GP faults,
"VSF D" is the same a "VSP D". For page faults, "VSP E"
traps all ring 3 and ring 2 page faults, and "VSF E"
traps only the invalid page faults.
o VT[N | P | V | R | F] n[,n,..]
This command adds a new vector that the debugger inter-
cepts. VTR installs a debugger handler in the real mode
IDT. VTP installs a debugger handler in the protected
mode IDT. VSV or VTV intercepts V86 mode exceptions or
traps.
The "N" option causes the intercepted traps to beep when
hit.
The "F" (Fatal) option causes the kernel to route the
faults that are fatal to a process to the debugger
instead of displaying the popup message. For GP faults,
"VSF D" is the same a "VSP D". For page faults, "VSP E"
traps all ring 3 and ring 2 page faults, and "VSF E"
traps only the invalid page faults.
o VS[N | P | V | R | F] n[,n,..]
This command is the same as VT, except that VS does not
intercept ring 0 interrupts. The VSV and VTV commands
intercept V86 mode exceptions or traps.
30 OS/2 Kernel Debugger
The "N" option causes the intercepted traps to beep when
hit.
The "F" (Fatal) option causes the kernel to route the
faults that are fatal to a process to the debugger
instead of displaying the popup message. For GP faults,
"VSF D" is the same a "VSP D". For page faults, "VSP E"
traps all ring 3 and ring 2 page faults, and "VSF E"
traps only the invalid page faults.
o VC[N | P | V | R | F] n,[n],..
This command clears the vectors indicated, reinstalling
whatever address was in the vector before the debugger
obtained the vector.
The "N" option causes the affected traps to not beep when
hit. It does not clear the trap itself.
The "F" (Fatal) option causes the kernel to route the
faults that are fatal to a process to the debugger
instead of displaying the popup message. For GP faults,
"VSF D" is the same a "VSP D". For page faults, "VSP E"
traps all ring 3 and ring 2 page faults, and "VSF E"
traps only the invalid page faults.
NOTE: If you want to intercept general protection faults
before the operating system does, then you can issue "VTP
D" before the fault is hit, examine the information about
the fault, and issue "VCP D" and "G" to let the system GP
handler get control and end the process. Alternatively,
you can issue the "VCP D" command after hitting the
fault, and trace into the exception handler. The "TT"
and "GT" commands do this automatically.
DEBUGGER OPTION
o Y[?] [386env|dislwr|regterse]
This command allows the debugger configuration to be
changed. The "?" prints the current options supported.
The "Y" command by itself prints the current state of the
options. The "Y" command and a flag name sets or toggles
an options flag. The flags are as follows:
386ENV 32-bit environment (toggles)
DISLWR lowercase disassembly (toggles)
REGTERSE terse register set (toggles)
All these flags toggle their state when set, and are
printed only when the option is on.
Kernel Debugger Commands 31
The "386env" flag controls the size of addresses, regis-
ters, and so on when displayed. When this option is on,
addresses, registers, and so on are printed in 32-bit
formats; otherwise they are printed in the 16-bit
formats. This flag has nothing to do with the processor
that the debugger is executing in. It only concerns the
display sizes.
The "dislwr" flag controls the disassembler's lowercase
option. When the flag is on, disassembly is in lower-
case.
The "regterse" flag controls the number of registers dis-
played in the register dump command. In the 32-bit
format, when the "regterse" flag is on, only the first
three lines are displayed (instead of the normal six-line
plus disassembly-line display). In the 16-bit format
(386env off), only the first two lines of the normal
three-line display (plus the disassembly line) are
printed.
DEFAULT COMMAND LINES
o Z
This command executes the default command. The default
command is a string of debugger commands that are exe-
cuted any time the debugger is entered and there is no
breakpoint command attached to the entry. It starts as
only the "R" command, but any string of commands can be
used.
o ZL
List the default command.
o ZS <string>
Change the default command. If there are any errors (too
long), it returns to the "R" command.
If you want to just "GO" on all the "INT 3s" in your
application or test program, here is what you do:
ZS "J (BY CS:EIP) == CC 'G&csq;R."
This restarts execution every time you enter the debugger
on an "INT 3".
A watchpoint can be set up as follows:
ZS "J (WO 40:1234) == 0EED 'r';t"
32 OS/2 Kernel Debugger
This command traces until the word at 40:1234 is equal to
hex 0EED. This will not work if you are tracing through
the mode-switching code in the operating system or other
sections of code that cannot be traced.
EXTERNAL DEBUGGER COMMANDS
__________________________
These commands are part of the debugger, but are specific
to the environment the debugger is running in. The fol-
lowing commands are for the OS/2 2.0 environment.
HELP
o .?
This command prints the help menu for the external
debugger commands.
COM PORT BAUD RATE
o .B <baud rate> [<port addr>]
This command sets the baud rate of the debugging port.
Valid values for the baud rate are 150, 300, 600, 1200,
2400, 4800, 9600 and 19200. Since the default base of
numbers for the debugger is 16, you must add the suffix
"T" to a decimal (base 10) number to indicate a decimal
value. For example, if you want to debug over a
1200-baud line, the correct command is:
.B 1200T
The port address option can be "1" for COM1, or "2" for
COM2. Anything else is taken as a base port address.
During initialization, if there is no COM2, the debugger
checks for COM1 and then any other COM port address in
the ROM data area, and uses it as the console.
DUMP ABIOS COMMON DATA AREA
o .C
This command dumps the ABIOS common data area.
Kernel Debugger Commands 33
DUMP OS/2 DATA STRUCTURES
o .D <data structure name> [<addr>]
This command displays a few common OS/2 data structures.
The data structures supported are:
Name Description
____ ___________
SFT System file table entry
VPB Volume parameter block
DPB Disk parameter block
CDS Current Directory Structure
KSEM Internal Kernel Semaphore
DT Disk Trace
DEV Device driver header
REQ Device driver request packet
MFT Master file table entry
BUF File system buffer
BPB BIOS parameter block
SEM32 32-bit Semaphore structure
MUXQ 32-bit Semaphore MuxQ chain
OPENQ 32-bit Semaphore OpenQ chain
SWAP IN TSD OR PAGE
o .I[D|B] [<addr>]
o .IT[D|B] [<slot>]
If only ".I" is given, the page enclosing that address is
swapped in. The address may include an optional task
slot number override, as in %3|20000. The ".IT" command
swaps in the corresponding task's TSD. The "D" option
queues a single swap-in request to be acted upon at task
time by the KDB daemon thread. If the "D" option is not
given, this command is restricted to being executed in
user mode (ring 3 or ring 2) or kernel mode if it is not
interrupt time, if the thread is not blocked, swapping or
34 OS/2 Kernel Debugger
leaving the kernel (InDos is 0). The ".I[T]" command
checks for all these conditions, and prints an error.
USER STACK TRACE
o .K[S|B] [<slot> | # | *]
This command threads through the BP chain on the user
stack of the slot specified, and prints the address, 4
words or doublewords of parameters, and any symbol found
for the address. The default starting point is taken
from the user SS:EBP and CS:EIP of the debugger's default
slot (the one selected with .S). The "S" (Small) option
indicates that the frame is 16 bits wide, and the "B"
(Big) option indicates that the frame is 32 bits wide.
The default depends on the D bit in the user's CS.
PRINT MTE SEGMENT TABLE
o .LM[O][L|P|V|X] <hobmte|laddr|"modulename"]
This command prints module table entries (MTEs) and their
associated object and segment table entries.
The "O" option suppresses the object or segment table
display.
The "L" option displays only library (.DLL) MTEs.
The "P" option displays only Physical Device Driver (PDD)
MTEs.
The "V" option displays only Virtual Device Driver (VDD)
MTEs.
The "X" option displays only executable (.EXE) MTEs.
If a nonzero HOBMTE is given, only those MTEs with a
matching HOBMTE are printed. If a nonzero linear address
is given, only the MTE pointed to by the linear address
is printed. If a quoted string is given, only those MTEs
with a matching module name are printed. The module
names for A:\BAR.DLL and C:\FOO\BAR.EXE are both "BAR".
No drive, path or extension information should be given.
Kernel Debugger Commands 35
MEMORY ARENA RECORD DUMP
o .MA[A|B|C|F|H|L|M|R] [<har|laddr>] | [<har|laddr>
L<number of entries>]
This command displays the virtual memory manager's arena
records. If no handle or linear address is given, the
entire table is displayed. If a linear address is given,
it is considered a pointer to an arena record. One
record or a range of records can be displayed.
The "A" option displays all contexts (the default is the
current context only).
The "B" option displays only busy (allocated) entries.
This is the default.
The "F" option displays only free (unallocated) entries.
The "C" option finds the corresponding object record, and
displays the arena, object, alias and context record
chains.
The "H" option follows hash links, displaying entries.
The "L" option follows forward links, displaying entries.
The "R" option follows reverse links, displaying entries.
The "M" option causes all arena records whose linear
address range encloses the given linear address to be
displayed. A linear address must also be given, and no
count is allowed. Context information is ignored, so if
the linear address is valid in multiple contexts, mul-
tiple arena records are displayed. A physical address
may be given instead of a linear address to allow non-
present linear addresses to get past the debugger's
expression analyzer. If a selector address type is used,
it must be converted to a linear address on the command
line.
If you ever need to find out who owns a selector because
of a GP fault in some unknown LDT or GDT segment or
memory object, the following command is useful:
.M
or
.MAMC CS:EIP
This command displays the arena record and memory object
record (and the owner) of the code segment. It also
follows the context record chains and displays them. The
"CS" can be substituted with any selector, and the "EIP"
36 OS/2 Kernel Debugger
with any offset. This command converts the
selector:offset into a linear address automatically, so
the resulting address can be used to find and interpret
the arena records and memory object records.
Since ".M" defaults to ".MAMC" when no options are given,
and since specifying the "M" option to any ".M" command
uses "CS:EIP" for the default, ".M" is the same as ".MAMC
CS:EIP".
MEMORY CONTEXT RECORD DUMP
o .MC[B|C|F] [<hco|laddr>] | [<hco|laddr> L<number of
entries>]
This command displays the virtual memory manager's
context records. If no handle or linear address is
given, the entire table is displayed. If a linear
address is given, it is considered a pointer to a context
record. One record or a range of records can be dis-
played.
The "B" option displays only busy (allocated) entries.
This is the default.
The "F" option displays only free (unallocated) entries.
The "C" option also follows context record chains and
displays them.
MEMORY ALIAS RECORD DUMP
o .ML[C] [<hal|laddr>] | [<hal|laddr> L<number of
entries>]
This command displays the virtual memory manager's alias
records. If no handle or linear address is given, the
entire table is displayed. If a linear address is given,
it is considered a pointer to an alias record. One
record or a range of records can be displayed.
The "B" option displays only busy (allocated) entries.
This is the default.
The "F" option displays only free (unallocated) entries.
The "C" option finds the corresponding object record, and
displays the arena, object, alias and context record
chains.
Kernel Debugger Commands 37
MEMORY OBJECT RECORD DUMP
o .MO[B|C|F|M|N|P|S|V] [<hob|laddr>] | [<hob|laddr>
L<number of entries>]
This command displays the virtual memory manager's memory
object records. If no handle or linear address is given,
the entire table is displayed. If a linear address is
given, it is considered a pointer to an object record.
One record or a range of records can be displayed.
This command attempts to display which process, MTE or
PTDA owns the segment. It displays the owner as a short
ASCII string when appropriate. It displays the PID of
the process and, if possible, the name of the module that
owns this segment. Code segments normally have only the
module name and no process ID. If the segment is an MTE,
PTDA or LDT, this command displays the object name, the
process ID (if the segment is a PTDA) and the module
name, if possible.
Here are a few examples of the owners that this command
can display:
Owner Description
_____ ___________
FREE Free memory
DEVHLP Allocated by the AllocPhys devhlp
IDEVICE Installable device driver memory
SYSTEM System owned memory
DOSEXE The initial memory arena when the operating
system started. This includes all of the
system code and data segments.
MTE A module table entry
PTDA A per task data arena
LDT A local descriptor table
If it only has a PID or a module name, then this piece of
memory is owned by the process or module.
The "B" option causes in-use (busy) object records to be
displayed.
The "F" option causes free object records to be dis-
played.
38 OS/2 Kernel Debugger
The "C" option displays the arena, object, alias and
context record chains.
The "M" option causes all pseudo object records with an
exactly matching linear address to be displayed. A
linear address must also be given, and no count is
allowed. If a selector address type is used, it must be
converted to a linear address on the command line. A
physical address may be given instead of a linear address
to allow non-present linear addresses to get past the
debugger's expression analyzer.
The "N" option causes non-pseudo object records to be
displayed.
The "P" option causes pseudo object records to be dis-
played.
The "S" option causes object records with the semaphore
busy or wanted to be displayed.
The "V" option causes object record linear addresses to
be displayed. It also disables the owner interpretation.
MEMORY PAGE FRAME DUMP
o .MP[B|F|H|L|R|S] [<frame|laddr>] | [<frame|laddr>
L<number of entries>]
This command displays the page manager's page frame
structures. If no handle or linear address is given, the
entire table is displayed. If a linear address is given,
it is considered a pointer to a page frame structure.
One record or a range of records can be displayed.
The "B" option displays only busy (allocated) entries.
This is the default.
The "F" option displays only free (unallocated) entries.
The "H" option follows hash links, displaying entries.
The "L" option follows forward links, displaying entries.
The "R" option follows reverse links, displaying entries.
This data structure contains per-physical-page informa-
tion. To find out the owner of a particular physical
page, issue ".MP FrameNumber", where FrameNumber is the
physical address shifted right by 12 bits (take off 3 hex
zeros). If the page is not free, the "pVP" field con-
tains a flat pointer to the virtual page structure.
Issue ".MV %pVP", where pVP is the value from the .MP
Kernel Debugger Commands 39
dump, to get the contents of the VP. The "Hob" field of
the VP is a handle to the Object Record. Issue ".MO Hob"
to dump it. This displays a readable string for the
owner on the right of the display (see the .MO command).
Issuing the .MA command for the "Har" field in the object
record gives the base virtual address of the object con-
taining the page (under "va"). Use the "HobPg" field of
the VP to get the page offset within the object.
MEMORY VIRTUAL PAGE STRUCTURE DUMP
o .MV[B|F|L|R] [<vpid|laddr>] | [<swapid|laddr>
L<number of entries>]
This command displays the swap manager's swap frame
structures. If no handle or linear address is given, the
entire table is displayed. If a linear address is given,
it is considered a pointer to a swap frame structure.
One record or a range of records can be displayed.
See the .MP command for an example.
The "B" option displays only busy (allocated) entries.
This is the default.
The "F" option displays only free (unallocated) entries.
The "L" option follows forward links, displaying entries.
The "R" option follows reverse links, displaying entries.
PRINT PROCESS STATUS
o .P[B|U] [<slot> | # | *]
This command displays the current status of the process
and thread. The asterisk (*) by the slot number means
the currently executing task or the last task to have
blocked. The number sign (#) marks what the debugger
thinks the current task is (set by the .S command). If
"#", "*", or a slot number is used on the command line,
only the corresponding slot's information is displayed.
Without the "B" or "U" option, this command prints the
PID, parent PID, command subtree number, thread number,
state, priority, block ID, PTDA address, TCB offset, dis-
patch ESP, screen group and name of the process or
thread.
The "B" option displays the detailed blocked information.
The HANDLESEM entry is for the current virtual memory
manager handle semaphores owned by this process. The
40 OS/2 Kernel Debugger
CHILD entry is for a child process that is being exe-
cuted. It is printed after all the threads in the exe-
cuting task (and their HANDLESEM entries) have been
printed.
The "U" option displays user state information, which
includes the CS:EIP and SS:ESP at the time the kernel was
entered, along with the number of arguments that were
passed, their PTDA offset, and the offset of the register
stack frame.
USER REGISTER
o .R [<slot> | # | *]
The .R command displays the contents of the user's CPU
registers, flags, and the next instruction to be executed
for a specified slot. This is for the user at the time
of entry to the kernel.
If no parameter is given, or if "#" is on the command
line, the debugger's current slot (selected by the .S
command) is used. If "*" is on the command line, the
currently scheduled slot (or the last one to block) is
used. Alternatively, if there is a number on the command
line, it is taken as the slot to use.
REBOOT
o .REBOOT
This command warm-starts the machine. The whole string
".REBOOT" must be typed.
TASK CONTEXT CHANGE
o .S[S] [<slot> | *]
This command changes what the debugger thinks the current
task context is. If no slot number is passed, it prints
the current task number. This allows dumping of some
process-specific data (the LDT or stack) for other than
the current task. The "S" option also changes the SS and
ESP to the new task's PTDA selector and dispatch ESP
value. The original SS and ESP are automatically
restored when the debugger exits, or when the ".SS"
command is used to switch back to the current task. The
"*" slot number changes the debugger's current task
number to the real system task number.
Kernel Debugger Commands 41
RAS TRACE BUFFER PRINT
o .T [<count>] [maj=<xx> [min=<yy>]]
This command dumps the RAS trace buffer, optionally
dumping only events with the specified major and minor
event codes.
42 OS/2 Kernel Debugger
ADVANCED KERNEL DEBUGGER TECHNIQUES
___________________________________
SETTING USEFUL BREAKPOINTS
There are many things that can be done when you use a
combination of these debugger commands. You can easily
set up the debugger to stop at a certain label, print
information about the current system millisecond, current
process, and executing file, and then continue. For
example, this would be very useful in analyzing the per-
formance of a subsystem .DLL. Another example is to set
a breakpoint on a file-read label in the file system, and
dump information about which file is being read, where it
is being read from, how much of the file is being read,
and who is reading it.
In order to do this, you must know some internal informa-
tion about the kernel and other system components, such
as labels of various Application Program Interface (API)
functions or worker routines.
One way to keep some release independence is to base
breakpoints from function labels with an offset. These
change much less often than the linear addresses of the
functions. An example is as follows:
BP _LDRGetMte + 63 "DA %EDX L EAX + 1; G"
This command places a breakpoint at the symbol
_LDRGetMte, offset by hex 63. Whenever that breakpoint
is hit, the debugger dumps (in ASCII) the memory at the
linear address stored in register EDX, for a length con-
tained in register EAX plus one byte. The program then
continues executing.
Of course this offset within the function may change, but
it is easier to find the new offset if it does than to
use linear addresses for your breakpoints.
The effect of this breakpoint is to display the name of
any executable file (for example, with file types .EXE,
.DLL, or .SYS) that is started with DosExecPgm,
DosStartSession, or DosLoadModule, or imported from any
other executable file. This is very useful when debug-
____
ging problems in applications.
Advanced Kernel Debugger Techniques 43
A breakpoint that can help you profile your code to see
how often you are taking page faults on pieces of code is
as follows:
1. Unassemble at the label _ldrgetpage for approxi-
mately 30 instructions
2. Look for a call to _ldrvalidatemtehandle
3. Set a breakpoint on the instruction immediately fol-
lowing that call (where execution would go upon
return from the call) as follows:
bp %address ".lm %eax;g"
This breakpoint will cause the loader to display the name
of the code module (DLL or EXE) that code is being read
from. This of course needs to be looked at in perspec-
tive. For example, all code that is ever executed is ref-
erenced at least once (the first time it is loaded).
However, if you are seeing excessively long code load
times and a large amount of what looks to be thrashing,
you may want to look here. Also, if you have code
residing on remote drives, you may want to look here to
see how much you are hitting the code on the remote drive
to possible reconfigure it.
A breakpoint you can use to profile (timestamp test) your
code is:
BP xxxxxx "DD SISData+4 L1;g"
where xxxxxx is the address or label you wish to profile.
This breakpoint will give you a runnin millisecond
counter in hexadecimal. If you want to tell the time it
takes between two points in the code, add this to the
breakpoints and the time will be displayed when it hits
the points. This will help in narrowing down the slow
area of code. Be careful when analyzing the results,
however, as although the timer is reported in millisec-
onds, it is only updated every 16 milliseconds.
Another useful breakpoint is one that tells you what
kernel calls you are executing. There is a routine called
"sci" that is used in all OS/2 kernel calls. By setting
the following breakpoint you can have it report what
kernel calls you are making.
bp sci+d4 "ln cs:bp+4;g"
44 OS/2 Kernel Debugger
This breakpoint says to break on sci+d4 and list the near
symbol representing the name of the kernel call. This is
more effective than just stopping and listing near
symbols because this displays just the name of the
routine and makes tracing a series of kernel calls much
easier.
If you need to look into the functions dealing with the
graphics engine (especially if you are writing a Presen-
tation Driver such as a printer or display driver) you
can set the following breakpoint:
bp dispatch32
This breakpoint is in PMGRE.DLL. When this breakpoint is
hit, you should look at the return address. Then, unas-
semble at that address MINUS approximately 20 bytes. What
you are looking for is the first doubleword pushed onto
the stack before the call. This should be the doubleword
representing the command flags and the engine function
number. The command flags are the high order word and
the function number is the low order word of the
doubleword. You could look at the stack frame to get
this, but since this is the first dword pushed, it is the
last dword in the frame due to the 32 bit calling con-
ventions. Since the DDI stack frames are variable sized,
you may have to do some searching to find the end of the
frame. You can do this too, but unassembling before the
call works just as well and may be easier.
For 16-bit presentation drivers, you would want to set
the breakpoint as follows:
bp dispatch16
Since the 16-bit calling conventions put the function
number first, you can simply look at the stack frame on
this one.
Another useful breakpoint is as follows:
BP _LDRNewExe "G %(DW(SS:ESP)); DD _pgSwappablePages L 3; G"
This command places a breakpoint at the symbol
_LDRNewExe. When that breakpoint is reached, the program
continues executing until the caller is returned to. The
debugger then displays the number of pages of swappable
memory in the system, followed by the number of fixed
(resident) pages, followed by the number of pages of
discardable memory (read-only or execute-only pages).
The program then continues executing.
Advanced Kernel Debugger Techniques 45
The effect of this breakpoint is to display the hex
number of pages that are in use by the whole system after
every executable program is started.
The term "G %(DW(SS:ESP))" means "Go (G) to the linear
address (%) that is the doubleword (DW) at the top of the
stack (SS:ESP) and stop". The operators "WO" and "BY"
are similar to "DW". "WO" means "word," and "BY" means
"byte." This type of setup can be useful when displaying
parameters for a function call as well, for example:
BP _LdrOpenNewExe "DA %(DW(SS:ESP+4)); G"
When this breakpoint is executed, the debugger dumps
ASCII (DA) starting at the linear address (%) given in
the doubleword (DW) at SS:ESP plus 4 bytes (the
doubleword at the top of the stack is the address for
_LdrOpenNewExe to return to). The program then continues
executing.
The effect of this breakpoint is to display (in ASCII)
the name of every executable loaded module that actually
opens a file. The difference between this breakpoint and
the one given earlier is that the earlier one displays
the names even if the module was attached to instead of
_____________________________________________
newly opened and loaded. This breakpoint only gives the
_______________________
newly opened names. By setting both breakpoints and sub-
__________________
tracting the names, you can determine the imported
modules.
A series of commands that can be useful in determining
the amount of memory an application requires is as
follows:
.PU (pick a thread that is in the process you wish to examine)
.SS n (where 'n' is the thread or slot number you picked)
DL (list all valid LDT selectors (all 16-bit segments))
If the DL command listing stops with an address not
present or invalid, issue the ".ID x" command (where 'x'
is the address) and then the G (Go) command. When the
system stops again, the LDT page will be present.
Reissue the ".SS n" and DL commands, and you will get a
more complete listing of the LDT selectors. An example
of the output follows:
46 OS/2 Kernel Debugger
# .PU
... (generates a lot of information like...)
Slot Pid Ord pPTDA Name pstkframe CS:EIP SS:ESP cbargs
0012 0006 0012 7d31ccb0 FOO.EXE 7d102f50 d02f:00002501 0b3f:00007eee 0008
... ... ... ... ... ... ... ... ...
# .SS 12
# DL
... (try it and stop at %7b176000...)
# .ID %7b176000
task|addr 0012|7b176000 queued, g to continue
# G
... (stops at INT3 in tasking...)
0170:fff629f4 cc int 3
# .SS 12
# DL
0007 Data Bas=7b175000 Lim=0000ffff DPL=3 P RO
000f Data Bas=00010000 Lim=00001677 DPL=3 P RW A
0017 Code Bas=00020000 Lim=00003197 DPL=3 P RE A
001f Data Bas=00030000 Lim=00001fff DPL=3 P RW A
... ... ... ... ... . .. .
The first entry (0007 Data ...) points to the process'
LDT itself, and should not be counted when adding up the
amount of memory the application itself is using.
However, it is part of the system overhead that is used
for the process, and should be attributed as such.
The following breakpoints give you a great deal of infor-
mation about the startup of an application:
BP G_TKEXECPGM "? 'ExecPgm'; G"
BP G_W_LOADMODULE "? 'LoadModule'; G"
BP H_W_QAPPTYPE "? 'QryApplType'; DA DS:DX;
G"
BP _LDRGETMTE + 63 "DA %EDX ; G"
BP _LDROPENNEWEXE "DA %(DW(SS:ESP+4)) ;
G"
BP _LOAD_ERROR "DD SS:ESP L 3; G"
BP H_W_GETPROCADDR "? 'GetProcAddr'; G"
BP H_W_GETPROCADDR + 23 "? 'by ordinal'; ? DI; G"
BP H_W_GETPROCADDR + 25 "? 'by name'; DA AX:DI; G"
These nine breakpoints give the programmer using the
kernel debugger a great deal of information about how a
Advanced Kernel Debugger Techniques 47
program loads and starts executing. These breakpoints
can be placed into a KDB.INI file on a machine under test
to allow you to determine which binary files are loaded
and executed. Please again note that these offsets may
change in subsequent releases of the OS/2 kernel and
loader. Some of the possible types of files are the
following:
48 OS/2 Kernel Debugger
File Type File
_________ ____
.DLL Dynamic Link Library
.EXE Executable program
.FON Static Font File
.PSF Dynamic Font File
.QPR Queue Printer Driver
.PDR Printer Driver
.SYS Physical Device Driver
.VDD Virtual Device Driver
The next two breakpoints inform the debugger that the
specified label was passed. This allows you to interpret
the successive breakpoints accurately.
1. bp g_tkExecPgm "? 'DosExecPgm'; G"
2. bp g_w_loadmodule "? 'DosLoadModule'; G"
The next breakpoint prints the name of the routine being
executed, and prints the name of the file being queried.
3. bp h_w_QAppType "? 'DosQueryAppType'; DA DS:DX; G"
A program issues DosQueryAppType (QAT) when it has to
determine the application type of an executable file.
For example, when you type 'FREDDY' at a command prompt
and press Enter, the system program CMD.EXE has to find
out whether the file 'FREDDY' is a .EXE file, a .CMD
file, a .COM file, or some other type of file.
Some information can be derived from the file's exten-
sion. The DOS command processor works this way.
However, you may still need to determine whether a .EXE
file is a DOS application, a 16-bit OS/2 Version 1.3
application, a 32-bit OS/2 Version 2.0 application, or a
Windows(**) application. DosQueryAppType (QAT) attempts
to determine this in a way that is very similiar to what
happens when the program is actually loaded and executed.
Sometimes, DosQueryAppType (QAT) is issued to verify that
the file exists. For example, SysInit (the thread that
---------------
(**) Trademark of the Microsoft Corporation.
Advanced Kernel Debugger Techniques 49
loads all the device drivers) has to determine whether a
device driver exists, and whether the file contains a
valid device driver. SysInit issues DosQueryAppType
(QAT) for all of the BASEDEV= and DEVICE= statements in
the CONFIG.SYS file.
Sometimes, the QAT type does not need to open the file.
If the Shell queries the type of a file several times in
quick succession, the first QAT call determines the type
of the file, and then saves it for a few cycles. If
another QAT call is made immediately for the same file,
____
the previously-determined type is returned. This value
is cleared when any other file-system access is made,
such as when a file is deleted.
To see whether a file was actually opened for a loader or
tasking call, see breakpoint number 5.
Breakpoint number 4 prints the name of any file being
loaded, read, attached to, or otherwise referred to (for
example, imported) in the loader.
4. bp _ldrGetMte + 63 "DA %EDX ; G"
If breakpoint number 1, 2, or 3 immediately precedes
breakpoint number 4, then breakpoint number 4 indicates
the name of the primary module being executed by
DosExecPgm, or loaded by DosLoadModule (DLM), or queried
by DosQueryAppType (QAT). If breakpoint number 4 does
not follow one of the labelling breakpoints, then this
___
indicates that a module is being imported.
________
Breakpoint number 5 displays the name of any file being
opened for execution by the loader. This breakpoint,
along with breakpoint number 6, allows the debugger to
find a large number of observed problems.
5. bp _ldrOpenNewExe "DA %(DW(SS:ESP+4)) ; G"
6. bp _load_error "DD SS:ESP L 3; G"
Breakpoint number 6 is the error handler for this area.
Many error codes are not returned through a base-pointer
chained stack frame through several levels of function
calls. Instead, a special stack frame is created when
the loader is entered, and the stack offset to this frame
is preserved. When an error occurs, _load_error() is
called with two parameters - error code and an optional
MTE handle. In breakpoint number 6, the debugger dis-
plays the return address from where the error was
detected, the error code for what happened, and either a
zero or a module table entry (MTE) handle for where the
error was found. File BSEERR.H contains the Control
50 OS/2 Kernel Debugger
Program error codes. Common error codes are 2
(ERROR_FILE_NOT_FOUND) and 193 (ERROR_BAD_EXE_FORMAT).
If an MTE handle is supplied, issue the '.lm[o] handle'
command to obtain more information.
After _load_error() finishes processing, it clears the
stack of everything above the special stack frame. It
then returns directly to the original caller, without
executing any intervening code. This is efficient, and
it avoids a large amount of error-handling code in each
function.
The next three breakpoints are used to determine what is
being retrieved from a .DLL after a successful call to
DosLoadModule (DLM). Breakpoint number 7 displays the
label 'DosGetProcAddr', followed by information about the
.DLL being queried, including its name.
Breakpoint number 8 displays the ordinal number of the
______________
code or data being sought in the .DLL. Breakpoint number
9 displays the name of the code or data being sought in
____
the .DLL. Breakpoints number 8 and 9 are mutually exclu-
sive.
7. bp h_w_getprocaddr "? 'DosGetProcAddr'; .LM EAX; G"
8. bp h_w_getprocaddr + 23 "? 'by ordinal'; ? DI; G"
9. bp h_w_getprocaddr + 25 "? 'by name'; DA AX:DI; G"
Breakpoints number 7, 8, and 9 do not tell you anything
about information that is being imported from a .DLL. To
________
do this, more information about the internal operation of
the loader is required.
The following is an example of using these breakpoints:
LoadModule
C:\OS2\DLL\TIMESNRM.PSF
43 3a 5c 4f 53 32 5c 44-4c 4c 5c 54 49 4d 45 53 C:\OS2\DLL\TIMESNRM.PSF.
QryApplType
C:\OS2\PMSHELL.EXE
43 3a 5c 4f 53 32 5c 50-4d 53 48 45 4c 4c 2e 45 C:\OS2\PMSHELL.EXE
QryApplType
04a8:00000002 C:\OS2\PMSHELL.EXE
QryApplType
04a8:00000002 C:\OS2\PMSHELL.EXE
ExecPgm
C:\OS2\PMSHELL.EXE
LoadModule
Advanced Kernel Debugger Techniques 51
BVSCALLS
GetProcAddr
by ordinal
0003H 3T 3Q 0000000000000011Y '.' TRUE
LoadModule
PMSDMRI
LoadModule
C:\OS2\DLL\PMATM.DLL
GetProcAddr
by name
04a8:00000002 FONT_DRIVER_DISPATCH_TABLE
LoadModule
DISPLAY
LoadModule
C:\OS2\DLL\DISPLAY.DLL
LoadModule
PMCTLS
LoadModule
SPL1B
LoadModule
SPL1D
53 50 4c 31 44 SPL1D
0030:00006724 fff8b6c3 00000002 00000000 (this is what _load_error() displays)
DEBUGGING KERNEL DEVICE DRIVERS
There are some structures in the kernel debugger that are
useful when you are debugging a kernel device driver.
You can issue the following commands to refer to these
structures.
o .D DEV DS:0
This command displays the header of the device
driver. It helps you determine which device driver
you are debugging.
o .D REQ ES:BX
52 OS/2 Kernel Debugger
This command displays the kernel request packet.
This packet is passed between the file system and a
kernel device driver. Issue this command at the
strategy entry point or exit point of the device
driver. This command helps you determine which
request the device driver has just finished proc-
essing, or is about to process.
o .MAMC
This command displays the module name of the program
that is currently executing. This helps you deter-
mine the owner of the process that trapped.
o VSF*
This command sets the trap vectors. This causes the
kernel debugger to stop at the instruction that is
about to cause a trap.
DEBUGGING VM START SESSIONS
Before you begin kernel debugging in a VM Start session,
you must establish interrupt vectors 1 and 3 again.
Issue the command "DD %%0" to see what they should be,
and then issue the commands to set them to their correct
values, for example:
E &0:4 12 67 00 1d
E &0:c 57 67 00 1d
To debug a trap 6 or incorrect-output problem, set a
breakpoint at the "VMINT21" entry point.
You can find the segment of FSFILTER by looking at the
"INT 20h" or "INT 21h" vectors (0:80 and 0:84, respec-
tively). The offset of "VMINT21" is hex 330. Trace
through all of the "INT 21" calls until the error is
observed. Run the test again to the last successful "INT
21", then begin stepping through the code until the error
is found.
A method of eliminating FSFILTER as the component with
the problem is to set up a test case that executes from
the diskette. This way, you can execute a VM Start
session without installing FSFILTER. If the problem
still occurs, then FSFILTER is not the cause of the
problem.
Advanced Kernel Debugger Techniques 53
DEBUGGING CMD.EXE
A problem that appears to be in CMD.EXE is usually
located in a different program. Due to the way the
kernel debugger works, CMD.EXE symbols are often shown
when they should not be. This can happen when a trap
occurs in an application that was started from the
command prompt.
You can issue a List Near Symbol (LN) command at the
debug terminal. However, there are probably no symbols
for the application, so the kernel debugger displays the
closest symbols. These symbols are usually from CMD.EXE
(the parent process).
Therefore, you should first issue the Print Process
Status (.P #) command. This command shows which process
actually trapped. If the line does not show "CMD" on the
right-hand side, the program that trapped is not CMD.EXE.
54 OS/2 Kernel Debugger
SETUP FOR REMOTE DEBUGGING
__________________________
The OS/2 kernel debugger allows you to diagnose a problem
quickly if you have access to the computer that has the
problem. Installing a modem on the target system allows
you to call it by telephone, and to communicate with the
system.
This chapter assumes that you have installed the OS/2
debug kernel on your system. Although the debug kernel
works with almost any modem, this chapter describes
installation of the IBM(*) 5853 modem operating at 2400
bits per second (bps).
ITEMS REQUIRED TO SET UP A SYSTEM FOR REMOTE DEBUGGING
______________________________________________________
To complete the installation, you need the following:
o A target system with both the retail kernel and the
debug kernel
o An IBM 5853 modem
o A modem data cable
o An analog dial-in telephone line
o Communications software
TARGET SYSTEM
The target system is the computer that has the problem to
_____________
be debugged. This computer should have the debug kernel
and symbols installed on it. If you configure the modem
using the target system, you may want to do this before
______
you install the debug kernel. The kernel debugger inter-
feres with communications programs that use the same
serial port. If you have another computer available, you
can configure the modem on that computer, and then move
the modem to the target system.
Setup for Remote Debugging 55
IBM 5853 MODEM
This modem is a synchronous (V.25bis) and asynchronous
(V.22bis) modem with built-in error correction and speed
buffering. The speed buffering feature is especially
helpful for remote debugging, since it allows the kernel
debugger to communicate at 9600 bps, regardless of the
true modem speed. This allows you to restart the kernel
without requiring an operator at the local console to
reset the 'dte' baud rate. The MNP-3 error correction
prevents transmission errors from interfering with the
debugging session if the modem at the other end also sup-
ports MNP-3 error correction. These features make the
IBM 5853 modem a good choice for remote debugging.
MODEM DATA CABLE
The configuration of the cable used to connect the IBM
5853 modem to the target system is not important. Any
serial data cable should have the connections required by
the debug kernel. Make sure that you do not use a null-
_____
modem cable. You will need either a 25-to-25 pin cable
_____
(for connection to the built-in serial port on a PS/2(*)
system), or a 25-to-9 pin cable (for connection to a
dual-asynchronous card).
---------------
(*) Trademark of the IBM Corporation.
56 OS/2 Kernel Debugger
The required connections for the remote debug cable are
as follows:
+----------------------------------+ +----------------------------------+
| | | |
| MODEM COMPUTER | | MODEM COMPUTER |
| DB25P DB25J | | DB25P DB9J |
| | | |
| +-+ +-+ | | +-+ +-+ |
| |2|-----------|2| | | |2|-----------|3| |
| |3|-----------|3| | | |3|-----------|2| |
| |7|-----------|7| | | |7|-----------|5| |
| +-+ +-+ | | +-+ +-+ |
| | | |
+----------------------------------+ +----------------------------------+
Figure 1. 25-to-25 Pin Cable Figure 2. 25-to-9 Pin Cable
Notice that the 25-to-9 pin cable reverses pins 2 and 3. Do not confuse this
with a null-modem cable, because the signals on a 25-to-9 pin cable are
normally reversed.
ANALOG DIAL-IN TELEPHONE LINE
In order to call the modem and connect to the target computer, you need a
standard voice-grade telephone line that can be dialed directly. A con-
nection can be made if the line must go through a switchboard, but this is
more difficult for the person who is debugging the problem. Digital tele-
phone lines do not work with the modem.
COMMUNICATIONS SOFTWARE
Any terminal software that can communicate at 9600 bps is sufficient. The
OS/2 2.0 system comes with a program named Softerm Custom that is adequate
for remote debugging.
THE CONFIGURATION PROCESS
_________________________
After you have assembled the required items, follow these steps to prepare
the target system for remote debugging:
1. RESET THE MODEM TO FACTORY DEFAULTS.
Perform the following actions:
a. Turn off the modem.
b. Press and latch in all front panel switches.
c. Move all switches on the back of the modem to the Up/On position,
except for switch number 4, which should be in the Down/Off position.
Setup for Remote Debugging 57
d. Turn on the modem.
e. Wait 5 seconds.
f. Turn off the modem.
g. Press and latch out all front panel switches, except the RL switch,
which must be latched in.
____
The modem is now reset to its factory defaults, and is ready to be pro-
grammed for remote debugging.
2. CONFIGURE THE MODEM FOR REMOTE DEBUGGING.
Using the data cable, connect the modem to the system where the communi-
cations software is installed. If this is the target system, you should
use the retail kernel to avoid a conflict with the communication port.
Set the communications software for 9600 bps operation, and turn on the
modem.
Type START and press Enter.
You must type START in uppercase. The modem should respond with "IBM
5853". If it does not, turn off the modem, and then turn it on. Check
your cable connections, and try again.
58 OS/2 Kernel Debugger
When you see "IBM 5853", press the following keys and type the following
commands:
Key and command System action
_______________ _____________
[CTRL+N]"OP 2=0" Disable modem command responses
[CTRL+N]"OP 15=1" Answer the phone on ring 1
[CTRL+N]"OP 27=7" Set 'dte' speed to 9600 bps
[CTRL+N]"SB 1" Lock 'dte' speed
[CTRL+N]"IT 0" Disable inactivity timeout
The sequence [Ctrl+N] means press and hold the Control (Ctrl) key and
press N. The first time you do this, the modem should respond with
"<COM>". These commands ensure that the modem answers incoming calls,
and stays at 9600 bps regardless of the true modem speed. Some of these
commands are already set, but doing this again ensures they are set prop-
erly in case factory defaults change.
You may now turn off the modem and move it to the target system if you
configured the modem on another system. Turning off the modem does not
erase the modem configuration. The modem is configured properly for
remote debugging until you reconfigure it.
NOTE: If you have a different modem, you can probably use it if you can
configure the modem to do the following:
o Lock the 'dte' rate at 9600 bps.
o Answer the phone when it rings.
o Ignore the state of the 'dtr' signal; always treat the target com-
puter as if it were ready to communicate.
o Use XON/XOFF as flow control between the modem and the target com-
puter.
o Disable modem result codes (that is, do not send 'ring' or 'connect'
messages when answering the telephone).
Most V.22bis modems with MNP-5 or V.42 error correction can perform these
functions. Standard V.22bis modems (without error correction) such as
the Hayes(**) Smartmodem 2400 cannot perform these functions because they
do not support locked 9600 bps 'dte' speeds. Consult the modem's manual
for information about configuration.
3. CONNECT THE MODEM TO THE TARGET SYSTEM.
---------------
(**) Trademark of Hayes Microcomputer Products, Inc.
Setup for Remote Debugging 59
After you have configured the modem, connect one end of the data cable to
the modem, and connect the other end to the serial port on the target
system. If the target system has more than one serial port, connect the
cable to the port that is configured as COM2. Use the PS/2 reference
diskette to determine which port is configured as COM2. Connect the
telephone line to the modem, and turn on the modem. The remote debug
system is ready.
When the modem phone rings, the answering modem attempts to establish an
error-free connection with the calling modem . If the calling modem does not
support MNP, a normal connection is made. You can tell that the connection
is error-free if the ECL light on the modem blinks. The person at the system
with the calling modem is then able to perform all remote debugging func-
tions, including remote restart of the system to be debugged. Since the
modem always stays at 9600 bps, there is no need to reset the debugger speed
locally.
LIMITATIONS OF THIS SETUP
Since the modem communicates with the target system at 9600 bps, but can only
communicate with the remote modem at 2400 bps, the modem must use flow
control to avoid data overruns. The only flow control supported by the debug
kernel is XON/XOFF. The only time this causes a problem is when the remote
user wants to create a pause in a continuous data display by pressing Ctrl+S.
If the modem has also sent a Ctrl+S signal, the signal from the user is
ignored. You may have to press Ctrl+S several times before the display
pauses. This is not a problem if the remote user's communication program
supports a "scroll-back buffer," because then there is no reason to create a
pause in the display by pressing Ctrl+S.
PROBLEM DETERMINATION
If you cannot establish a remote debugging connection after following these
instructions, this table may help:
60 OS/2 Kernel Debugger
+---------------------------------------------------------------------------+
| Table 3. Problem Determination for Remote Setup |
+------------------------+-------------------------+------------------------+
| SYMPTOM | PROBLEM | SOLUTION |
+------------------------+-------------------------+------------------------+
| Calling modem hears | No modem power. | Plug in the modem |
| the phone ring, but | | power cord, and turn |
| you hear nothing from | | on the power switch. |
| the modem. +-------------------------+------------------------+
| | Telephone line is not | Plug the telephone |
| | connected to the modem. | line into the modem. |
+------------------------+-------------------------+------------------------+
| Modem rings, but does | RL switch is not | Latch in the RL switch |
| not answer. | latched in. | on the front of the |
| | | modem. |
+------------------------+-------------------------+------------------------+
| Modem answers, but | Retail kernel is | Remove the retail |
| there is no response | installed. | kernel and install the |
| from the debug kernel. | | debug kernel. |
| +-------------------------+------------------------+
| | Data cable is not con- | Connect the data cable |
| | nected properly. | from the modem to the |
| | | target system. Plug |
| | | the data cable into |
| | | the COM2 port if the |
| | | target system has more |
| | | than one serial port. |
+------------------------+-------------------------+------------------------+
| User at the remote | Modem is not locked at | Perform modem config- |
| modem sees "garbage" | 9600 bps. | uration again. |
| on the screen, and is +-------------------------+------------------------+
| unable to control the | Debug kernel is not | Use the local debug |
| debugging session. | operating at 9600 bps. | console to send the |
| | | command ".B 9600t" to |
| | | the kernel, or restart |
| | | the target system. |
+------------------------+-------------------------+------------------------+
Setup for Remote Debugging 61
62 OS/2 Kernel Debugger
APPENDIX A. SAMPLE DEBUGGING SESSION
_____________________________________
This example shows a deadlock. Slot #42 waits on a
VMGetSem semaphore that slot #37 owns, and slot #37 waits
on a KSEMRequestExclusive semaphore that slot #42 owns.
Start to display current processes and threads status
with the detailed blocked information.
Appendix A. Sample Debugging Session 63
##.pb
Slot Sta BlockID Name Type Addr Symbol
0001 blk fff1a894 *ager
0002 blk fff82124 *tsd _tkTSDDaemon
0003 blk fff4c850 *ctxh _kmCTXHDaemon
0004 blk fff825f1 *kdb _tkKDBDaemon
0005 blk fff0c820 *lazyw _semLW
0006 blk fff19770 *asyncr _AsyncReadSem
0009 blk fffe000f pmshell RamSem 0743:06ac
0008 blk fffe0004 pmshell RamSem bf3f:0066
000b blk ffca0002 pmshell
000c blk fffd000c pmshell MuxWait
000d blk fffd000d pmshell MuxWait
000e blk 04000a72 pmshell DosSem 0400:0a72 CtrlNumLkQ
0007 blk fffe0008 pmshell RamSem d1a7:028e HSEMINIRUN
0011 blk fffe000a pmshell RamSem d0c7:0020
0012 blk fffd0012 pmshell MuxWait
0013 blk fffe000c pmshell RamSem d09f:0ba0 memory_pool + 127
0014 blk fffe000e pmshell RamSem d09f:0ba8 memory_pool + 12f
0015 blk fffd0015 pmshell MuxWait
0016 blk fffe000b pmshell RamSem d147:00d8 FSRSUSER + 10
*0017# blk 04000a64 pmshell DosSem 0400:0a64 SMHotKeyQ
0018 blk fffe000b pmshell RamSem d147:00d8 FSRSUSER + 10
0019 blk fffe0011 pmshell RamSem 0743:06c8
000a blk 04000a80 harderr DosSem 0400:0a80 HardErrPkt
Slot Sta BlockID Name Type Addr Symbol
000f blk 04000d94 harderr DosSem 0400:0d94 CtrlPrtScQ
0010 blk 04000db4 harderr DosSem 0400:0db4 VideoPauseFlag
001a blk fffe000b pmshell RamSem d147:00d8
001b blk fe92c2a8 pmshell Sem32 8001 0009
001c blk fffe0015 pmshell RamSem be5f:0a2c
001d blk 0f280012 pmshell hash_table + ??
001e blk 0f30000e pmshell profile_records + ??
0020 blk 0f400012 pmshell
0021 blk fffe0017 pmshell RamSem d0c7:0088
0022 blk fffe0016 pmshell RamSem 0743:06d8
001f blk ffca0005 !cmd
0023 blk fffe003d switch RamSem a8af:0004
0024 blk fe90dff4 testlog
0025 blk fffd0025 switch MuxWait
0026 blk fffe003a switch RamSem a8af:0008
0027 blk fffe0031 switch RamSem a8af:000c
0028 blk fffe003f switch RamSem a8af:0010
0029 blk fffe003c switch RamSem a8af:0014
002a blk fffe0043 switch RamSem a8af:0018
002b blk fffe0041 switch RamSem a8af:001c
002c blk fffe0048 switch RamSem a8af:0020
002d blk fffe0047 switch RamSem a8af:0024
002e blk fffe0042 switch RamSem a8af:0028
Slot Sta BlockID Name Type Addr Symbol
0035 blk fee6c060 testlog2
0037 blk fe90dfe0 cube32
0038 blk fffe0187 clock32 RamSem 0743:06dc
0042 blk fee6c060 clock32
64 OS/2 Kernel Debugger
003b blk fe90dff4 testlog2
003e blk fffe000b !gp2 RamSem d147:00d8 FSRSUSER + 10
003f blk fe90dff4 testlog2
0041 blk fe90dff4 testlog2
Use the command to switch back to a task that is blocked on the FSRUSER
semaphore. We change the debuggers current task number to the real OS2 task
number #3e.
##.ss 3e
##.pb#
Slot Sta BlockID Name Type Addr Symbol
003e# blk fffe000b !gp2 RamSem d147:00d8 FSRSUSER + 10
Display the FastRam Semaphore structure to find out who owns it.
##dw d147:d8 - e l10
d147:000000ca 0000 0046 0002 0001 0000 ffff ffff 0101
d147:000000da 000b 0000 0000 0000 0000 0000 0000 ffff
typedef struct _DOSFSRSEM ñ /* dosfsrs */
USHORT cb; 0000
PID pid; 0046
TID tid; 0002
USHORT cUsage; 0001
USHORT client; 0000
ULONG sem; ffffffff
ç DOSFSRSEM;
Display the processes and threads status to find the slot number of process
#46 and thread #2.
Appendix A. Sample Debugging Session 65
##.p
Slot Pid Ppid Csid Ord Sta Pri pTSD pPTDA pTCB Disp SG Name
0001 0001 0000 0000 0001 blk 0100 ffe44000 ffe468d4 ffe46728 1e7c 00 *ager
0002 0001 0000 0000 0002 blk 0100 7cc02000 ffe468d4 fd109020 1f3c 00 *tsd
0003 0001 0000 0000 0003 blk 0200 7cc04000 ffe468d4 fd1091cc 1f50 00 *ctxh
0004 0001 0000 0000 0004 blk 081f 7cc06000 ffe468d4 fd109378 1f48 00 *kdb
0005 0001 0000 0000 0005 blk 081f 7cc08000 ffe468d4 fd109524 1f20 00 *lazyw
0006 0001 0000 0000 0006 blk 081f 7cc0a000 ffe468d4 fd1096d0 1f3c 00 *asyncr
0009 0002 0001 0002 0001 blk 0500 7cc10000 fd13f020 fd109bd4 1eac 01 pmshell
0008 0002 0001 0002 0002 blk 0800 7cc0e000 fd13f020 fd109a28 01 pmshell
000b 0002 0001 0002 0003 blk 0800 7cc14000 fd13f020 fd109f2c 01 pmshell
000c 0002 0001 0002 0004 blk 0800 7cc16000 fd13f020 fd10a0d8 01 pmshell
000d 0002 0001 0002 0005 blk 0800 7cc18000 fd13f020 fd10a284 01 pmshell
000e 0002 0001 0002 0006 blk 0800 7cc1a000 fd13f020 fd10a430 01 pmshell
0007 0002 0001 0002 0007 blk 0800 7cc0c000 fd13f020 fd10987c 1eac 01 pmshell
0011 0002 0001 0002 0008 blk 0200 7cc20000 fd13f020 fd10a934 01 pmshell
0012 0002 0001 0002 0009 blk 0200 7cc22000 fd13f020 fd10aae0 01 pmshell
0013 0002 0001 0002 000a blk 0800 7cc24000 fd13f020 fd10ac8c 01 pmshell
0014 0002 0001 0002 000b blk 0800 7cc26000 fd13f020 fd10ae38 01 pmshell
0015 0002 0001 0002 000c blk 0800 7cc28000 fd13f020 fd10afe4 1e9c 01 pmshell
0016 0002 0001 0002 000d blk 0500 7cc2a000 fd13f020 fd10b190 1eac 01 pmshell
*0017 0002 0001 0002 000e blk 0804 7cc2c000 fd13f020 fd10b33c 1ea4 01 pmshell
0018 0002 0001 0002 000f blk 0500 7cc2e000 fd13f020 fd10b4e8 1eac 01 pmshell
0019 0002 0001 0002 0010 blk 0200 7cc30000 fd13f020 fd10b694 01 pmshell
000a 0003 0002 0003 0001 blk 0800 7cc12000 fd13f74c fd109d80 00 harderr
Slot Pid Ppid Csid Ord Sta Pri pTSD pPTDA pTCB Disp SG Name
000f 0003 0002 0003 0002 blk 0800 7cc1c000 fd13f74c fd10a5dc 00 harderr
0010 0003 0002 0003 0003 blk 0800 7cc1e000 fd13f74c fd10a788 00 harderr
001a 0004 0002 0004 0001 blk 0500 7cc32000 fd13fe78 fd10b840 1eac 10 pmshell
001b 0004 0002 0004 0002 blk 0200 7cc34000 fd13fe78 fd10b9ec 10 pmshell
001c 0004 0002 0004 0003 blk 0200 7cc36000 fd13fe78 fd10bb98 10 pmshell
001d 0004 0002 0004 0004 blk 0200 7cc38000 fd13fe78 fd10bd44 10 pmshell
001e 0004 0002 0004 0005 blk 0200 7cc3a000 fd13fe78 fd10bef0 10 pmshell
0020 0004 0002 0004 0007 blk 0800 7cc3e000 fd13fe78 fd10c248 10 pmshell
0021 0004 0002 0004 0008 blk 011f 7cc40000 fd13fe78 fd10c3f4 10 pmshell
0022 0004 0002 0004 0009 blk 0800 7cc42000 fd13fe78 fd10c5a0 10 pmshell
001f 0005 0002 0005 0001 blk 0200 7cc3c000 fd1405a4 fd10c09c 04 !cmd
0023 001f 0002 001f 0001 blk 021f 7cc44000 fd141b28 fd10c74c 11 switch
0024 001e 001d 001e 0001 blk 0214 7cc46000 fd140cd0 fd10c8f8 1df8 04 testlog
0025 001d 0005 001d 0001 blk 0214 7cc48000 fd1413fc fd10caa4 1e9c 04 switch
0026 0020 0002 0020 0001 blk 021f 7cc4a000 fd142254 fd10cc50 1eac 12 switch
0027 0021 0002 0021 0001 blk 021f 7cc4c000 fd142980 fd10cdfc 1eac 13 switch
0028 0022 0002 0022 0001 blk 021f 7cc4e000 fd1430ac fd10cfa8 1eac 14 switch
0029 0023 0002 0023 0001 blk 021f 7cc50000 fd1437d8 fd10d154 1eac 15 switch
002a 0024 0002 0024 0001 blk 021f 7cc52000 fd143f04 fd10d300 1eac 16 switch
002b 0025 0002 0025 0001 blk 021f 7cc54000 fd144630 fd10d4ac 1eac 17 switch
002c 0026 0002 0026 0001 blk 021f 7cc56000 fd144d5c fd10d658 1eac 18 switch
002d 0027 0002 0027 0001 blk 031f 7cc58000 fd145488 fd10d804 1eac 19 switch
002e 0028 0002 0028 0001 blk 021f 7cc5a000 fd145bb4 fd10d9b0 1a switch
Slot Pid Ppid Csid Ord Sta Pri pTSD pPTDA pTCB Disp SG Name
0035 0042 0020 003d 0001 blk 030b 7cc68000 fd148de8 fd10e564 1dec 12 testlog2
0037 0043 0024 0043 0001 blk 050b 7cc6c000 fd149514 fd10e8bc 1d4c 16 cube32
0038 0046 0025 0046 0001 blk 020b 7cc6e000 fd14aa98 fd10ea68 1eac 17 clock32
0042 0046 0025 0046 0002 blk 050b 7cc82000 fd14aa98 fd10fb20 1d8a 17 clock32
66 OS/2 Kernel Debugger
003b 0047 0043 0047 0001 blk 020b 7cc74000 fd14b1c4 fd10ef6c 1df8 16 testlog2
003e# 004a 0027 004a 0001 blk 050b 7cc7a000 fd14c748 fd10f470 1eac 19 !gp2
003f 004b 0046 004b 0001 blk 020b 7cc7c000 fd14ce74 fd10f61c 1df8 17 testlog2
0041 004e 004a 004e 0001 blk 030b 7cc80000 fd14dccc fd10f974 1df8 19 testlog2
Use the command to switch back to the task that owns the FSRUSER
semaphore. We change the debuggers current task number to the real OS2 task
number #42.
##.ss 42
Get the stack backtrace of the thread #2 process #45
in this slot #42.
##k
0170:fff80ac8 00000000 00006b50 00006c1a fff685a2 _TKSleep + 1a6
0170:fff685a2 fee6c060 ffffffff 00000000 00000000 _VMGetSem + 239
0170:fff63758 fff10005 00000085 7cc83e2a 7cc83eb6 _vmReserveSub + 338
0170:fff63322 00000010 14411016 00000000 fff1a2f4 _VMReserve + c8
0170:fff955dc 00000010 14411016 fd14aa98 00000000 _VMAllocMem + 2f4
0170:fff93926 00010000 000000e0 14411016 000008ba selwrk$g_selAllocSeg + 116
0170:000038b9 00000158 00006d68 004a6d6c 01587503
The first parameter of VmGetSem is a memory object 0005
We display the virtual memory manager-s memory object
records to find out who owns it.
##.mo 5
hob va flgs own hmte sown,cnt lt st xf
0005 %fff1a2f4 8000 ffe1 0000 0037 03 00 00 00 vmah
The slot number 37 owns it, we switch to its context.
##.ss 37
##.p#
Slot Pid Ppid Csid Ord Sta Pri pTSD pPTDA pTCB Disp SG Name
0037# 0043 0024 0043 0001 blk 050b 7cc6c000 fd149514 fd10e8bc 1d4c 16 cube32
##.pb#
Slot Sta BlockID Name Type Addr Symbol
0037# blk fe90dfe0 cube32
Get the stack backtrace of the thread #1 process #43 in this slot #37.
Appendix A. Sample Debugging Session 67
##k
0170:fff80ac8 00000000 00006158 00006158 fff4fdb6 _TKSleep + 1a6
0170:fff4fdb6 fe90dfe0 ffffffff 00000000 00000001 _KSEMRequestExclusive + d6
0170:fff93b7b fe90dfd8 ffffffff 0000fec8 fed0b078 _SELRemDiscRec + 13
0170:fff91f66 00000781 7cc6de14 000061a8 fff66219 _SELFree + 5e
0170:fff66219 7cc6de14 7cc6de14 fee73820 13380000 _VMFreeMemOd + 149
0170:fff9773e 21000002 7cc6de14 0000559f fff1a2f4 _vmFreeAll + 11c
0170:fff97560 fff1a2f4 fd149514 00000000 fd149514 _VMFreeTask + 9d
0170:fff779e4 fd149514 fd144ba6 fe93d8c0 00000001 _LDRFreeTask + 10
0170:fff47ee3 fd149514 00006246 62e40158 8d480000 sproc4_LDRFreeTask + 1c
0170:fff86573 fd149514 00006304 fff86bb1 00030000 _tkExitList + 8b
0170:fff86bb1 00030000 00000000 7cc60003 00000000 _VRExitList + 26
0170:fff70e81 00000000 00000000 00000000 0000632c DOSEXITLIST + 15
We are waiting on a KSEMRequestExclusive semaphore that slot #42 owns.
##.d ksem %fe90dfd8
Signature : KSEM Nest: 0001
Type : SHARE Readers: 0000
Flags : 00 PendingReaders: 0000
Owner : 0042 PendingWriters: 0001
68 OS/2 Kernel Debugger
INDEX
_____
+--------------------+ commands (continued)
| SPECIAL CHARACTERS | .LM 35
+--------------------+ .MA 36
.MC 37
.MAP files 8 .ML 37
.SYM files 8 .MO 38
.MP 39
.MV 40
+---+ .P 40
| A | .R 41
+---+ .REBOOT 41
.S 41
Add Active Map (WA) command 23 .T 42
AllStrict kernel 1 BC 17
BD 17
BE 17
+---+ BL 17
| B | BP 15
+---+ BR 16
BS 17
backtrace 12 BT 16
Breakpoint (B) commands 15 C 17
breakpoint, sticky 15 D 17
breakpoint, temporary 15 DA 17
breakpoints, useful 43 DB 18
DD 18
DG 18
+---+ DI 18
| C | DL 18
+---+ DP 18
DT 19
CMD.EXE, debugging 54 DW 18
COM Port Baud Rate (.B) command 33 DX 20
COM1 port 1 E 20
COM2 port 1, 11 F 21
commands G 21
? 22 H 22
.? 33 I 22
.B 33 J 23
.C 33 K 24
.D 34 LA 23
.I 34 LG 23
.IT 34 LM 23
.K 35 LN 22
Index 69
commands (continued) +---+
LS 23 | F |
M 24 +---+
O 25
P 25 files, map 9
R 26 files, symbol 8
S 28 FILL (F) command 21
T 28 FSFILTER 53
U 29
VC 31
VL 30 +---+
VS 30 | G |
VT 30 +---+
WA 23
WR 23 GO (G) command 21
Y 31
Z 32
ZL 32 +---+
ZS 32 | H |
commands, kernel debugger 15 +---+
COMPARE (C) command 17
Conditional Execution (J) Help (.?) command 33
command 23 Help/Print Expression (?)
conventions 2 command 22
HEX (H) command 22
HStrict kernel 1
+---+
| D |
+---+ +---+
| I |
DEBUG debugger 1 +---+
Debugger Option (Y) command 31
Default Command Lines 32 initialization file 3
device drivers, debugging 52 INPUT (I) command 22
DUMP (D) commands 17 INT 20h 53
Dump ABIOS Common Data Area (.C) INT 21h 53
command 33 Interrupt and Trap Vector
Dump OS/2 Data Structures (.D) commands 30
command 34
+---+
+---+ | K |
| E | +---+
+---+
KDB.INI 3
ENTER (E) command 20 kernel debugger commands 15
entering the debugger 2 keywords 4
expressions 3
external debugger commands 33
70 OS/2 Kernel Debugger
+---+ +---+
| L | | O |
+---+ +---+
List Absolute Symbols (LA) operators, binary 5
command 23 operators, precedence order 5
List Groups (LG) command 23 operators, unary 6
List Maps (LM) command 23 OUTPUT (O) command 25
List Near Symbol (LN) command 22
List Symbols (LS) commands 23
+---+
| P |
+---+ +---+
| M |
+---+ Print MTE Segment Table (.LM)
command 35
map files 9 Print Process Status (.P)
MAPSYM utility 8 command 40
Memory Alias Record Dump (.ML) PTRACE (P) command 25
command 37
Memory Arena Record Dump (.MA)
command 36 +---+
Memory Context Record Dump (.MC) | R |
command 37 +---+
Memory Object Record Dump (.MO)
command 38 RAS Trace Buffer Print (.T)
Memory Page Frame Dump (.MP) command 42
command 39 REBOOT (.REBOOT) command 41
Memory Virtual Page Structure Dump REGISTER (R) command 26
(.MV) command 40 remote debugging 1
MOVE (M) command 24 Remove Active Map (WR) command 23
request packet, kernel 53
retail kernel 1
+---+
| N |
+---+ +---+
| S |
NMI (non-maskable interrupt) +---+
switch 3
non-maskable interrupt (NMI) SEARCH (S) command 28
switch 3 Stack Trace (K) command 24
numbers, base of 7 strings, character 8
Swap in TSD or Page commands 34
symbol files 8
symbols 2
SYMDEB debugger 1, 5
Index 71
+---+
| T |
+---+
Task Context Change (.S) command 41
TRACE (T) command 28
trap vectors 53
+---+
| U |
+---+
UNASSEMBLE (U) command 29
User Register (.R) command 41
User Stack Trace (.K) command 35
+---+
| V |
+---+
Virtual Page (VP) structure 19
VM Start sessions, debugging 53
VMINT21 53
72 OS/2 Kernel Debugger
+++EDF002W DOCPROF tag found outside PROLOG. (Page 0 File:
KDEBUG SCRIPT)
DSMMOM397I '.EDF#CNTX' WAS IMBEDDED AT LINE 3 OF 'KDEBUG'
+++EDF154E Value of COLS or CWIDTHS attribute on the TABLE t
ag exceeds page width. (Page 7 File: KDEBUG SCRIPT)
DSMMOM397I '.EDFTABL' WAS IMBEDDED AT LINE 495 OF 'KDEBUG'
DSMLBR529E 'KP' WOULD EXCEED MAXIMUM SIZE.
DSMMOM395I 'KDEBUG' LINE 3078: .LB
DSMLBR529E 'KP' WOULD EXCEED MAXIMUM SIZE.
DSMMOM395I 'KDEBUG' LINE 3171: .LB
DSMBEG323I STARTING PASS 2 OF 2.
+++EDF002W DOCPROF tag found outside PROLOG. (Page 0 File:
KDEBUG SCRIPT)
DSMMOM397I '.EDF#CNTX' WAS IMBEDDED AT LINE 3 OF 'KDEBUG'
+++EDF154E Value of COLS or CWIDTHS attribute on the TABLE t
ag exceeds page width. (Page 7 File: KDEBUG SCRIPT)
DSMMOM397I '.EDFTABL' WAS IMBEDDED AT LINE 495 OF 'KDEBUG'
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 19.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 44.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 45.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 46.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 47.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 49.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 51.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 52.
DSMLBR529E 'KP' WOULD EXCEED MAXIMUM SIZE.
DSMMOM395I 'KDEBUG' LINE 3078: .LB
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 64.
DSMLBR529E 'KP' WOULD EXCEED MAXIMUM SIZE.
DSMMOM395I 'KDEBUG' LINE 3171: .LB
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 65.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 66.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 67.
DSMW32708E TEXT EXCEEDS RIGHT PAGE BOUNDARY ON PAGE 68.