|
| ||
Document Contents: - Debugger Objective C Support - Sample .dbxrc File - Tracing Objective C Objects - Debugging Applications Using Optimized Libraries |
Debugging an OpenStep Application The SPARCworks Debugger is an interactive, window-based, source code and machine-instruction level debugging tool. It provides dynamic analysis for observing run-tme program behavior. The Debugger gives you complete control of the dynamic execution of a program, including the collection of performance data.
The Debugger provides the same functionality as To debug an OpenStep application, click on the Debug button in the project window for the application in Project Builder. If the project has not been built yet, it is built first. If the project builds successfully, then the application is run in debug mode and the SPARCworks Debugger starts up. See the SPARCworks manual Debugging a Program for details on using the Debugger windows.
Note: If the project has already been built, you can Alt-click on the Debug button to run the application under the Debugger. Debugger Objective C SupportRelease 3.1 of the SPARCworks Debugger includes support for Objective C applications, such as those developed using OpenStep.
Dynamic TypesIn Objective C an object pointer has two types:
print, display, inspect, and whatis commands with the -d option, or when you have set the dbx customization variable output_dynamic_type to on. If you use the +d option, the commands will use the static type.
It is recommended that you put
Use the If the process is active, the Debugger uses the run-time system to look up a method, otherwise it uses static information (stabs).
Setting BreakpointsThe Debugger accepts the following variations of thestop command for setting breakpoints in Objective C methods:
stop in -[Test ival:second:] stop in +[Test alloc] stop in [Test ival:second:] stop in [obj ival:second:] // through an object (only if active process) stop in ``ival:second: // searches all classes for ival:second: stop in ival:second: // only if dbxenv scope_look_aside is `on' stop inmethod ival:second: // stops in all methods with that nameIf the process is not active, use the following syntax for category methods:
stop in -[Test(Cat1) catmethod:second:] Calling Objective C MethodsAll Objective C instance methods must be called through an object. The following are some valid variations of calling Objective C methods:
call [obj ival: 30] // calling instance method with parameter call [self ival: 30] / use self if stopped inside a class call [Test alloc] // calling class method Recovering from a Run-time System CrashThe Debugger calls the Objective C run-time system to look up methods and, if output_dynamic_type is on, to find the dynamic type of an object. In some cases this can cause a crash of the run-time system. The Debugger can usually recover if you use thepop command. Use the where command and then the pop command to unwind frames from the stack. You can also use the kill command to return to a previous Debugger level.
Sample .dbxrc FileYour ~/.dbxrc file is read automatically if it exists when the Debugger starts up. The following is a sample .dbxrc file for debugging Objective C applications. This file is located in /usr/openstep/etc. To have the Debugger read this file when it starts up, add source /usr/openstep/etc/.dbxrc to your .dbxrc file.
##################################################################
# Objective C settings #
##################################################################
language objc
dbxenv scope_look_aside on
// sets the dbx customization variable
scope_look_aside to on (find static
symbols even when not in scope)
dbxenv output_dynamic_type on
// sets the dbx customization variable
output_dynamic_type to on (display,
inspect, print, whatis commands use
dynamic type of object)
# do
# call objc_enableMessageSendDebug(1)
# to enable the tracing of messages in objc_msgSend. This tracing is
# very fast and flexible. The above command will echo back all the
# info you need to use this feature.
function objchelp
{
echo "Add 'source /usr/openstep/etc/.dbxrc' to your ~/.dbxrc file"
echo " to define helpful Objective C functions, aliases and buttons."
echo " Look at this file in an editor to see what it contains."
echo "For more help, enter:"
echo " help general dbx help"
echo " help ObjC more Objective C help"
echo " help FAQ dbx - gdb correspondences, and other information"
}
function memon # stop if an object is freed too many times. VERY SLOW!!
{
call [NSAutoreleasePool enableDoubleReleaseCheck: 1]
stop in _NSAutoreleaseInconsistency
status
}
function memoff
{
call [NSAutoreleasePool enableDoubleReleaseCheck: 0]
}
function defbrks # breakpoints that catch errors
{
language objc
stop in abort
stop in -[NSObject doesNotRecognizeSelector:]
stop in +[NSAssertionHandler currentHandler]
stop in -[NSAssertionHandler
handleFailureInMethod:object:file:lineNumber:description:]
stop in -[NSAssertionHandler
handleFailureInFunction:file:lineNumber:description:]
stop in -[NSException raise]
stop in DPSDefaultErrorProc
stop in DPSCantHappen
stop in _exit
}
function morebrks # other helpful places to breakpoint
{
stop in NSLog
stop in _XErrorHandler
stop in -[Zombie forward::]
}
function allbrks # set breakpoints to catch errors
{
defbrks
morebrks
}
function pselfvar
{
print self->${1}
}
function pdesc
{
print [[$* description] cString]
}
function pnsstring
{
print [$* cString]
}
function prstar
{
print -r *($*)
}
function pcounts # print retain count and number of autoreleases of
$1
{
print [$* retainCount]
print [NSAutoreleasePool _numberOfObjectsIdenticalTo: $*]
}
# print string of an NSText object
dalias ptext print [[!1 text] cString]
// sets dbx alias ptext to
print string of an NSText object
# print string of an NSCStringText object
dalias pcs print [[!1 cStringTextInternalState]->_string cString]
// sets dbx alias pcs to print string of
an NSCStringText object
dalias pns pnsstring
// sets dbx alias pns for psstring command
dalias pd pdesc
// sets dbx alias pd for pdesc command
dalias prs prstar
// sets dbx alias prs for prstar command
alias typeof="print -l ((NSObject *)!:*)->isa->name"
// sets dbx alias typeof for printing type of
current object
dalias currwin "print -l [(NSView *)[NSView focusView] window]"
// sets dbx alias currwin for printing
current window
dalias flushcurrwin "print -l [((NSWindow *)[(NSView *)[NSView
focusView] window]) _forceFlushWindowToScreen]"
// sets dbx alias fluchcurrwin for synchronous flushing
of current window's off-screen buffer to screen
button expand whatis
// adds whatis button command;if selected
characters begin with alphanumeric
character, $, or _, then expands
selection and uses as target
button expand prstar
// adds prstar button command;if selected
characters begin with alphanumeric
character, $, or _, then expands
selection and uses as target
button expand pselfvar
// adds pselfvar button command;if
selected characters begin with
alphanumeric character, $, or _, then
expands selection and uses as target
button expand pnsstring
// adds pnsstring button command;if
selected characters begin with
alphanumeric character, $, or _, then
expands selection and uses as target
button expand pcounts
// add pcounts button command;if selected
characters begin with alphanumeric
character, $, or _, then expands
selection and uses as target
button expand pdesc
// add pcounts button command;if selected
characters begin with alphanumeric
character, $, or _, then expands
selection and uses as target
button ignore defbrks
// adds defbrks button command; ignores
current mouse selection for command
##################################################################
# General purpose settings #
##################################################################
toolenv cmdlines 20
// sets the number of lines in the
command subwindow to 20
dbxenv step_events on
// sets the dbx customization variable
step_events to on to allow breakpoints
while stepping or "nexting"
dbxenv suppress_startup_message 4.0
// sets the dbx customization
variable suppress_startup_message to
set -o ignoresuspend # uncomment to cause dbx to ignore ^Z
set -o emacs # uncomment to enable emacs-style command editing
#set -o vi # or uncomment this line for vi-style editing
function attach # attach to a running process
{
typeset PIG="$(/bin/ps -ef | /bin/egrep ${1} | /bin/egrep -v
egrep | /bin/head -1 | /bin/awk '{ print $8 " " $2 }')"
debug $PIG
}
function collOn # enable collector modes
{
collector work_set mode on
collector profile mode stack
}
function ff
{
where -f $(frame) 1
list
}
function penviron # dump the environment variables of the target
process
{
[ -z "$1" ] || { echo "$0: unexpected argument" >&2 && return; }
typeset -i i=0
typeset env="((char **)$[(char**)environ])"
while :
do
x=$[($env)[$i]]
echo "$i: " "${x#0x*\ }"
case "$x" in
*\(nil\)*) break;;
esac
((i += 1))
done
}
PS1="$SMSO(dbx !)$RMSO " # reverse-video prompt with history number
function _cb_prompt
{
if $mtfeatures
then # set prompt for MT debugging
PS1='${SMSO}${thread} ${lwp}:!${RMSO} '
else # set prompt for non-thread debugging
PS1='${SMSO}dbx:!${RMSO} '
fi
}
function hex # print arg in hex
{
# print <expr> in hex"
: ${1?"usage: $0 <expr>}
typeset -i16 x
((x = $[(int)$*]))
echo - $* = $x
}
typeset -q hex
function hexdump # dump $2 (default: sizeof $1) bytes in hex
{
: ${1?"usage: $0 <exp> [<size>] # dump <size> bytes in hex"}
typeset -i16 p="$[(void *)&$1]" # address of $1
# number of bytes
typeset -i s="${2:-$[sizeof ($1)]}" >/dev/null 2>&1
builtin examine $p/$[(${s:-4}+3)/4]X
}
typeset -q hexdump
function pg # print process status by name
{
/bin/ps -ef | /bin/egrep ${1} | /bin/egrep -v egrep
}
regs() # print register contents
{
case $# in
0) x &$g0/32X; x &$y/X; x &$psr/X; x &$pc/X; x &$npc/X ;;
*) for i
do reg=\$$i; x &$reg/X
done ;;
esac
}
dalias p print
// sets dbx alias p for print command
dalias w where
// sets dbx alias w for where command
dalias br where
// sets dbx alias br for where command
dalias ww where -q
// sets dbx alias ww for where -q (quick
traceback) command
dalias fr frame
// sets dbx alias fr for frame command
dalias b stop in
// sets dbx alias b for stop in command
dalias ba stop at
// sets dbx alias ba for stop at command
dalias si stop in
// sets dbx alias si for stop in command
dalias sa stop at
// sets dbx alias sa for stop at command
dalias sic stop inclass
// sets dbx alias sic for stop inclass
command
dalias sif stop infunction
// sets dbx alias sif for stop
infunction command
dalias sim stop inmember
// sets dbx alias sim for stop inmember
command
dalias sm stop modify
// sets dbx alias sm for stop modify
command
dalias sr stop returns
// sets dbx alias sr for stop returns
command
dalias cc="clear;cont"
// sets Korn alias cc for clear command
followed by cont command
dalias cl clear
// sets dbx alias cl for clear command
dalias ib status
// sets dbx alias ib for status command
dalias st status
// sets dbx alias st for status command
dalias d delete
// sets dbx alias d for delete command
dalias r run
// sets dbx alias r for run command
dalias c cont
// sets dbx alias c for cont command
dalias s step
// sets dbx alias s for step command
dalias su step up
// sets dbx alias su for step up command
dalias n next
// sets dbx alias n for next command
dalias di handler -disable
// sets dbx alias di for handler
-disable command
dalias en handler -enable
// sets dbx alias en for handler -enable
command
dalias N nexti
// sets dbx alias N for nexti command
dalias S stepi
// sets dbx alias S for stepi command
dalias q quit
// sets dbx alias q for quit command
dalias tiny toolenv srclines 16; toolenv cmdlines 8
// sets dbx alias
tiny to 16 lines in the source
subwindow and 8 lines in the command
subwindow
dalias mid toolenv srclines 25; toolenv cmdlines 25
// sets dbx alias
mid to 25 lines in the source
subwindow and 25 lines in the command
subwindow
dalias big toolenv srclines 33; toolenv cmdlines 14
// sets dbx alias
big to 33 lines in the source
subwindow and 14 lines in the command
subwindow
dalias und_all undisplay
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
// sets dbx
alias und_all to undo display commands
1 through 20
dalias insense dbxenv case insensitive
// sets dbx alias insense to
make case insignificant in variable
and function names
dalias sense dbxenv case sensitive
// sets dbx alias sense to make
case significant in variable and
function names
button lineno cont at
// adds button command cont at; uses
line number associated with current
selection as target of command
button ignore step up
// adds button command step up; ignores
current mouse selection for command
button ignore tiny
// adds button command tiny; ignores
current mouse selection for command
button ignore mid
// adds button command mid; ignores
current mouse selection for command
button ignore big
// adds button command big; ignores
current mouse selection for command
button ignore quit
// adds button command quit; ignores
current mouse selection for command
Helpful User Default Variables to Set with dwriteThe following user default variables, which you can set with thedwrite command, may be useful in debugging your application:
NSEnableAutoreleasePool NSEnableDoubleReleaseCheck NSHideOnDeactivateEnabled NSPauseAtStartup NSSetPoolThreshold NSShowAllViews NSShowAllWindows NSShowDrawTimes NSShowEvents NSShowPS NSShowWindowInfo NSShowXEvents NSTrapIllegalFloatingPointOps Tracing Objective C ObjectsYou can monitor Objective C messages being sent by objects in your application by calling the function objc_messageSendDebug. This function allows you to filter on different message attributes, and also stop at breakpoints when a certain filter matches the current message.This facility is particularly useful for finding memory allocation errors and performance problems.
You can enable
Invoking messageSendDebug Using dwrite CommandsYou can automatically invokemessageSendDebug at execution time by using one of the following dwrite commands.
This command turns on
dwrite AppName NSEnableMessageSendDebug YESThis command suspends the display of messages, even if filters are set:
dwrite AppName NSEnableMessageSendDebug NOThis command turns on messageSendDebug, and adds a generic filter to show all messages:
dwrite AppName NSEnableMessageSendDebug ALLThis command displays an explanation of how to use this facility:
dwrite AppName NSEnableMessageSendDebug HELP Adding Individual Message FiltersYou can add individual message filters with the following commands:
YES or NO applies to whether or not to call objc_messageMatchedFilter()
when a filter matches. Enter YES if you want your program to hit a breakpoint
when any filter matches (see "Setting a Breakpoint on a Filter Match").
GENERIC_FILTER shows all messages.If ClassName in the filter is *, any class counts as a match. If selectorName in the filter is *, any selector counts as a match. If selectorName in the filter is preceeded by a "+" or "-", only class methods, or instance methods (respectively) are considered matches. If receiverID in the filter is *, any receiver counts as a match. If ClassName, selectorName, and receiverID are all *, all messages are considered matches.
dwrite AppName NSEnableFilterCallLevelIndentation YES | NO dwrite NSGlobalDomain NSEnableFilterCallLevelIndentation YES | NOThis setting effects console output only, and has no effect on external debug-monitoring applications like ObjectDebug.
Invoking messageSendDebug from a Program or the DebuggerFor detailed information, see the file/usr/openstep/include/objc/objc-debug.h. Enabling messageSendDebug adds to, and does not preclude, filtering options you have set using dwrite.
Enabling messageSendDebugTo enablemessageSendDebug, call one of the following methods:
objc_enableMessageSendDebug(EnableDebug) objc_enableMessageSendDebug(EnableDebugShowAllMessages) objc_enableMessageSendDebug(EnableDebugSilently) objc_enableMessageSendDebug(DisableDebug) objc_enableMessageSendDebug(DisableDebugSilently)The following methods are equivalent to the above methods:
objc_enableMessageSendDebug(1) objc_enableMessageSendDebug(2) objc_enableMessageSendDebug(3) objc_enableMessageSendDebug(0) objc_enableMessageSendDebug(-1) Note:You may want to disable this mechanism before making method calls in your debugger, as those method calls will get traced as well! Adding FiltersTo add filters, you can call one of the following methods:
objc_addFilterFromString has the same syntax as the NSMessageSendDebugFilter dwrite command, with the addition of a FilterID field as the first value. This field lets you uniquely identify the filter.The filter string format looks like this:
objc_addFilterFromString("FilterID, ClassName | *,
[+ | -]selectorName | [+ | -]*, receiverID[hex or dec] | *, YES | NO
or this:
objc_addFilterFromString("GENERIC_FILTER")
YES or NO applies to whether or not to call objc_messageMatchedFilter()
when a filter matches. Enter YES if you want your program to hit a breakpoint
when any filter matches (see "Setting a Breakpoint on a Filter Match").
GENERIC_FILTER shows all messages.If ClassName in the filter is *, any class counts as a match. If selectorName in the filter is *, any selector counts as a match. If selectorName in the filter is preceeded by a "+" or "-", only class methods, or instance methods (respectively) are considered matches. If receiverID in the filter is *, any receiver counts as a match. If ClassName, selectorName, and receiverID are all *, all messages are considered matches.
objc_enableFilterCallLevelIndentation(0 | 1)This setting effects console output only, and has no effect on external debug-monitoring applications. It is unnecessary if the feature has already been enabled or disabled with dwrite.
objc_removeAllFilters() Disabling FiltersTo temporarily disable all filters, call the following method:
objc_enableMessageSendDebug(DisableDebug[0]) Setting a Breakpoint on a Filter MatchIf you want your program to hit a breakpoint when any filter matches, call the following method:
objc_callMessageMatchedFilter(0 | 1) Note: objc_callMessageMatchedFilter sets this flag for all existing filters. To set the flag for individual filters, use the objc_addFilterFromString method to create your filter, or call objc_callMessageMatchedFilter after setting some filters, and then set the rest of your filters.
Once you continue program execution, a string is printed indicating that the current message or receiver matched one of the set filters.
After this string is printed, the function
You can put a breakpoint at
ExamplesExample 1:To see all the messages sent to the NSAutoreleasePool class, either enter the followingdbx commands in the Debugger Command Pane:
call objc_enableMessageSendDebug(1)
call objc_addFilterForClass("NSAutoreleasePool")
or use the following dwrite commands at execution time:
dwrite AppName NSEnableMessageSendDebug YES dwrite AppName NSMessageSendDebugFilter "NSAutoreleasePool,*,*,NO" Example 2:To see all theaddObject: messages sent to the NSAutoreleasePool class, and have Objective C call objc_messageMatchedFilter() when that message is sent (so you can hit a breakpoint there), either enter the following dbx commands in the Debugger Command Pane:
call objc_enableMessageSendDebug(1)
call
objc_addFilterFromString("1,NSAutoreleasePool,addObject:,*,YES")
or use the following dwrite commands at execution time
dwrite AppName NSEnableMessageSendDebug YES dwrite AppName NSMessageSendDebugFilter1 "NSAutoreleasePool,addObject:,*,YES"Notice the lack of the first parameter, the filterID, which is automatically generated in this case by the number that is appended to the dwrite key + 1000 (for example. "1001").
Example 3:To see all the class method calls (as opposed to instance method calls) sent to any object, and not show call level indentation, either enter the followingdbx commands in the Debugger Command Pane:
call objc_enableMessageSendDebug(1)
call objc_addFilterForSelector("+*")
call objc_enableFilterCallLevelIndentation(0)
or use the following dwrite commands at execution time:
dwrite AppName NSEnableMessageSendDebug YES dwrite AppName NSMessageSendDebugFilter "*,+*,*,NO" dwrite AppName NSEnableFilterCallLevelIndentation NO Implementing Your Own Filtering MechanismIf you want to implement your own filtering mechanism, you can call the following function:
objc_setMessageSendFilterFunction(void (*customFilterFunction)(Class receiverClass,id receiver, SEL selector,void *callLevel, void *threadID))This function takes a pointer to a filterFunction. After calling this function, every message (objc_msgSend) that is sent will go through your own filter function. You can then implement your own filtering system.You can also call the following function from your filter function, in case you want to do the normal filtering stuff but tweak a few things first.:
objc_defaultMessageSendFilterFunction()You can get a linked list of all the currently set filters by calling the following:
Debugging Applications Using Optimized LibrariesIf you compile an application with -g but use libraries not compiled with -g, the Debugger does not know the prototypes of methods defined in the libraries. This means it does not know the types of the returned values, nor of the parameters. It assumes the types are int.For example, assume that set1 is an NSSet, You could use casts to tell the Debugger the return types of methods:
dbx:3 whatis set1 @interface NSSet *set1; dbx:4 p [set1 description] [set1 description] = -283014864 dbx:5 p (NSString *)[set1 description] (@interface NSString *) [set1 description] = 0xef218bd0 dbx:6 p [(NSString *)[set1 description] cString] [(@interface NSString *) [set1 description] cString] = -281204711 dbx:7 p (char *)[(NSString *)[set1 description] cString] (char *) [(@interface NSString *) [set1 description] cString] = 0xef3d2841 "NSConcreteSet(a, b)"In order to obviate the need for these casts, Project Builder includes a special module named dbxInfo.o. This module contains debugging information for all the methods defined in the Application Kit and Foundation Kit libraries. When you do a debug build using the Project Builder Makefiles, this module is automatically linked into your application. In order to make this information available to the Debugger after it has started, Project Builder issues the following command to the Debugger as it is starting up:
This command causes the Debugger to read in the debugging information contained in dbxInfo.o so it is available when the Debugger has to determine the return types and parameter types of methods invocations.
| |
Copyright 1996 Sun Microsystems, Inc., 2550 Garcia Ave., Mtn. View, CA 94043-1100 USA. All rights reserved.