Swat Introduction: 5.4 Essential Commands: Examining and Modifying Memory

Up: GEOS SDK TechDocs | Up | Prev: 5.3 Breakpoints and Code Stepping | Next: 5.5 Other Important Commands

The commands in this section all deal with the examination, manipulation, or modification of the memory used by an application. Memory from individual bytes to complex data structures such as objects can be displayed and examined. These commands fall into the following groups:

The commands in this section are often used with each other and with the code-stepping and breakpoint commands in order to pinpoint bugs in an application's code. Breakpoints can be set, code can be stepped through, and then the memory that the code uses can be examined.

Some related commands defined in the Reference chapter are down , func , handles , hgwalk , impliedgrab , penum , phandle , pinst , piv , precord , skip , systemobj , up , and where .

Simple Memory Examination

bytes, words, dwords, frame, backtrace, why, listi

The commands in this group are used to look at simple blocks of memory without modification. They are defined fully in the entries below.

bytes, words, dwords

bytes [<addr>] [<length>]
words [<addr>] [<length>]
dwords [<addr>] [<length>]

The bytes , words , and dwords commands are essentially the same except that each looks at a different sized piece of memory. These commands will display the memory as a pointer to a dump of bytes, words, or dwords using the given or most recent (if no address is given) address.

The bytes command additionally displays the dump as its ASCII character representation, if any. These three commands are used to examine memory on a very basic level and are useful only if the user knows what the bytes, words, or dwords should or should not be and so can spot any problems. For example, if a certain character string such as "Application" is supposed to be stored at the address given by fileType and the command

[hello3:0] 11 => bytes fileType

dumps the characters "noitacilppA", then there is most likely a problem.

These commands will automatically use the given addr as a pointer to the memory to be examined. If Return is hit many times in a row, the result will be to examine adjacent pieces of memory. (See The words Command .)

Swat Display 3-6 The words Command

(mess1:0) 15 => words themeSongBuf
Addr: +0 +2 +4 +6 +8 +a +c +e
0040h: 0004 0000 0049 0000 0004 0001 0083 0000
(mess1:0) 16 => words
Addr: +0 +2 +4 +6 +8 +a +c +e
004eh: 0000 0006 0004 0028 0000 0001 020b b800
(mess1:0) 17 => !!
words
Addr: +0 +2 +4 +6 +8 +a +c +e
005ch: b800 000c 0020 0002 0001 0000 0001 020b
(mess1:0) 18 => !!
words
Addr: +0 +2 +4 +6 +8 +a +c +e
006ah: 020b b800 000c 0010 0002 0001 000a 0010 

Here the words command examines a buffer in memory. When this command is repeated without arguments, it will display memory continuing where the last command left off. Note the use of the !! command to repeat the previous command.

backtrace, frame

backtrace [<frames to list>]
frame <subcommand>

The backtrace and frame commands are used to examine data that has been pushed onto the stack. An application may crash in a routine that is correctly written but has been passed bad data.

The backtrace command prints out a list of all the active frames for the current patient. Then the user can choose a particular frame to examine using one of the frame subcommands. The frame command is used to access frames that have been pushed onto the stack, where a frame is the information for a routine that needs to be saved when it calls another routine.

The frame and backtrace commands can be used together to print the active frames with backtrace and then access data in these frames with frame . However, most of the frame subcommands expect a token for a frame, not the frame number given by the backtrace command. To get this token, the top , cur and next subcommands are used. Then the other frame subcommands can be used with the token to further examine the frame data. See also the reference information for the frame command.

Backtrace and Frame commands

Death due to SOUND_BAD_EVENT_COMMAND
Execution died in patient sound:
SoundHandleTimerEvent+63: MOV AX, 7 (0007h)
*** No explanation available ***
Interrupt 3: Breakpoint trap
Stopped in FatalError, address 1844h:0163h
SoundHandleTimerEvent+63: MOV AX, 7 (0007h)
(mess1:0) 2 => backtrace
  1: near FatalError(), 1844h:0163h
  2: far AppFatalError(), 1844h:0163h
* 3: far SoundHandleTimerEvent(), 2cb2h:003fh
  4: far SoundLibDriverPlaySimpleFM(), 6247h:0062h
  5: far ResourceCallInt(), 1844h:1492h
  6: far SoundLibDriverStrategy(), 2cb2h:0ab2h
  7: near SoundCallLibraryDriverRoutine(), 629ch:00feh
  8: far SoundPlayMusic(), 629ch:0028h
  9: far ResourceCallInt(), 1844h:1492h
  10: far SOUNDPLAYMUSICNOTE(mh = ^h42b0h (at 753ch), priority = 1eh, tempo = 4h
, flags = 80h), 62d6h:00f3h
  11: far ResourceCallInt(), 1844h:1492h
  12: far Mess1Draw(), MESS1.GOC:307
  13: far MESS1PROCESSMETA_EXPOSED(win = 3a60h, message = 69 (invalid), oself =
3ee0h:0000h), MESS1.GOC:362
  14: far ResourceCallInt(), 1844h:1492h
MSG_META_EXPOSED (3a60h 0000h 0000h) sent to Mess1ProcessClass (^l20f0h:0h)
  16: near ObjCallMethodTableSaveBXSI(), 1844h:9ea5h
  17: far SendMessage(), 1844h:9d9bh
  18: far ObjMessage(), 1844h:1d9ch
  19: far MessageDispatchDefaultCallBack(), 1844h:1c72h
  20: far MessageProcess(callBack = 1844h:1c68h (geos::kcode::MessageDispatchDef
aultCallBack)), 1844h:1c15h
  21: far MessageDispatch(), 1844h:1b31h
  22: far ThreadAttachToQueue(), 1844h:bd2ch
(mess1:0) 3 => frame 12
Mess1Draw+302: MOV AX, 100 (0064h) 

Complex Memory Examination

print, hwalk, lhwalk, objwalk, pobject, gentree, vistree, vup, gup

The commands in this group are used to examine complex data structures in GEOS.

print

print <expression>

The print command is used to print out the value of the given expression argument. The expression argument is normally some sort of typed address. When there is no type for the expression , then its offset is printed.

The power of this command lies in its ability to print any type at any address; thus, it is used frequently to print out the values of important expressions such as registers or variables. The print command also takes many flags which control the way in which the value of the expression is displayed such as in decimal or hexadecimal. See the Reference chapter for more information on the flags for the print command.

hwalk

hwalk [<patient>]

Use the hwalk (heap walk) command to display blocks on the global heap. Its output can be tailored in various ways according to how the flags are set. If a patient is given, then hwalk will only print the blocks owned by that patient. There are many fields in the listing such as the handle, address, and type of each block. By examining these fields, the user can get an overall sense of how the global heap is being managed, whether any block looks too big or too small, and what the handles of important blocks are. (See The hwalk Command .)

Swat Display 3-8 The hwalk Command

(mess1:0) 6 => hwalk mess1
HANDLE ADDR SIZE FLAGS LOCK OWNER IDLE  OINFO 						TYPE
----------------------------------------------------------------
20f0h 41ebh 2272 FIXED  n/a mess1  n/a     1h 						R#1 (dgroup)
4160h 58eah  448 sDS  a   1 mess1 105eh    1h 						R#2 (MESS1_TEXT)
3a60h 59adh  784 s SL     0 mess1  0:03    1h 						WINDOW
4bb0h 6176h  560 s SL     0 mess1  0:05    1h 						WINDOW
3970h 6232h  336 s SL     0 mess1  0:03    1h 						GSTATE
3ee0h 633ch  160 s S  a   0 mess1  0:05 49c0h 						Geode
4950h 63beh 1280 s SL     0 mess1  0:05 49c0h 						OBJ(mess1:0)
4340h 640eh 1328   SL     0 mess1  0:05 49c0h 						R#3 (INTERFACE)
42b0h 753ch   96 s S      4 mess1 1249h    1h 					  
4bd0h 7542h   96 s S      0 mess1  0:01    1h   
41b0h 89d4h  896   SL     0 mess1  0:05 49c0h 						R#4 (APPRESOURCE)
4270h 99e1h   32 s S      0 mess1  0:05     1h

Total bytes allocated: 8288
(mess1:0) 7 =>

lhwalk, objwalk

lhwalk [<addr>]
objwalk [<addr>]

The lhwalk (local heap walk) command is used to display information about a local memory heap, and the objwalk command is used to print out information about an object block. After using hwalk to locate a specific block, lhwalk or objwalk can be used to print out information about that particular block. These commands also print out fields of information which include the local handle, the address, size, and type of data or object. See the Reference chapter for more information on the fields printed by lhwalk and objwalk . (See The objwalk Command .)

Swat Display 3-9 The objwalk Command

(mess1:0) 11 => objwalk ^h4340h
 
Heap at 640eh:0 (^h4340h), Type = LMEM_TYPE_OBJ_BLOCK
In use count = 3, Block size = 1328, Resource size = 59647 para (192 bytes)
 
HANDLE ADDRESS 	SIZE FLAGS CLASS (NAME)
------ ------- 	---- ----- ------------
 001ch     56h 		1eh  ---  *flags*
 001eh     76h 		c1h  D RO GenPrimaryClass (Mess1Primary)
 0020h    1aah 		ceh  D RO GenViewClass (Mess1View)
 0022h    166h 		32h ID  O OLGadgetAreaClass
 0024h    19ah 		 eh  I
 0026h    492h 		6bh  D  O GenValueClass
 0028h    2deh 		6bh  D  O GenValueClass
 002ah    37eh 		a6h ID  O GenInteractionClass
 002ch    44ah 		46h ID  O OLMenuBarClass
 002eh    13ah 		 bh ID
 0030h    426h 		22h ID  O OLMenuButtonClass
 
Free handles = 17, null handles = 0
Objects = 8, 4 of them marked ignoreDirty
 
(mess1:0) 12 =>

pobject

pobject [<addr>] [<print level>]

The pobject (print object) command (often abbreviated pobj ) is used to print out the entire instance data chunk of an object. You can use gentree , vistree , or hwalk and objwalk to get the handles for an object; once you have them, use pobj with the handles, as follows:

[hello3:0] 7 => pobj ^l0x43d0:0x0022

will print out the instance data chunk specified by that optr.

Any valid address expression, such as a dereferenced object name, may be used as an addr . Additionally, the print level can be changed to print just the headings to each of the master levels and an address history number. The pobject command is used to verify that the object is behaving correctly and that its instance variables (if any) are correct. (See The pobject Command .)

Swat Display 3-10 The pobject Command

[lesink:0] 10 => pobj ^l4710h:0020h
*UpTextView::UpTextViewClass (@7, ^l4710h:0020h)
master part: Gen_offset(123) -- UpTextViewInstance
@8: {UpTextViewInstance (^h18192:622)+123} = {
    MetaBase Gen = {
        ClassStruct _far *MB_class = 360ah:162fh (motif::dgroup::OLPaneClass)
    }
    LinkPart GI_link = {
        dword LP_next = 4710h:001fh
    }
    CompPart GI_comp = {
        dword CP_firstChild = 4710h:002ah
    }
    word GI_visMoniker = 0h
    word GI_kbdAccelerator = 0h
    byte GI_attrs = 2h
    byte GI_states = c0h
    PointDWFixed GVI_origin = {
        DWFixed PDF_x = {0.000000}
        DWFixed PDF_y = {0.000000}
    }
    RectDWord GVI_docBounds = {
        long RD_left = 0
        long RD_top = 0
        long RD_right = +480
        long RD_bottom = +480
    }
    PointDWord GVI_increment = {
        long PD_x = +20
        long PD_y = +15
    }
    PointWWFixed GVI_scaleFactor = {
        WWFixed PF_x = {1.000000}
        WWFixed PF_y = {1.000000}
    }
    ColorQuad GVI_color = {
        CQ_redOrIndex = fh, CQ_info = 0h, CQ_green = 0h, CQ_blue = 0h
    }
    word GVI_attrs = 10h
    byte GVI_horizAttrs = 88h
    byte GVI_vertAttrs = 88h
    byte GVI_inkType = 0h
    dword GVI_content = 4710h:0024h
    dword GVI_horizLink = 0000h:0000h
    dword GVI_vertLink = 0000h:0000h
}
Variable Data:
         *** No Variable Data ***
[lesink:0] 11 =>

In addition to printing information about the object at a given address, pobject can print information about certain objects in the application if passed certain flags:

pobject -i
Prints information about the windowed object under the mouse pointer.
pobject -c
Prints information about the content for the view over which the mouse is located.

There are more flags available, and it is also possible to ask for more or less instance data information. See the full reference for this command for details.

gentree

gentree [<addr>] [<instance field>]

The gentree (generic tree) command prints out a generic tree from the given addr and instance field . The addr must be the address of an object in the generic tree, and the instance field must be the offset into the Generic master part of the instance chunk or any instance data within the Generic master level which is to be printed. This command is used primarily to ensure correct structure of a generic tree and its instance data and to find a particular object in the generic tree. The -i (implied grab) option is used to find an object by placing the mouse over the window in which the object resides and typing the following:

[hello3:0] 7 => gentree -i

The default address that gentree examines is contained in *DS:SI. (See Gentree and Gup .) To examine objects more closely, pass the handles displayed by gentree to the pobject command.

vistree

vistree [<addr>] [<instance field>]

The vistree (visual tree) command prints out a visual tree from the given addr and instance field . The addr must be the address of an object in the visual tree, and the instance field must be the offset into the Vis master part of the object's instance data which is to be printed. This command is primarily used to examine the on-screen layout of the application and to ensure correct structure of the visual tree and its instance data. The vistree command can use the -i option (implied grab), which will use the window that the mouse is over as the first visual object in the printed tree. The default address that vistree examines is contained in *DS:DI. To examine objects more closely, pass the handles displayed by vistree to the pobject command.

gup

gup [<addr>] [<instance field>]

The gup (Generic UPward query) command is used to go up the generic tree from a particular object specified by the addr argument, the default *DS:SI, or the -i option. The -i option (implied grab) uses the windowed object under the mouse as the object from which to start the upward query. This command is used primarily to ensure correct generic class hierarchy and to determine the field of the given object.

Swat Display 3-11 Gentree and Gup

(mess1:0) 19 => gentree -i
 
GenViewClass (@5, ^l4340h:0020h)
 GenValueClass (@6, ^l4340h:0026h)
 GenValueClass (@7, ^l4340h:0028h)
 
(mess1:0) 20 => gup @5
 
GenViewClass (@11, ^l4340h:0020h)
GenPrimaryClass (@12, ^l4340h:001eh) "MESS #1"
GenApplicationClass (@13, ^l41b0h:0024h) *** Is Moniker List ***
GenFieldClass (@14, ^l4080h:001eh)
GenSystemClass (@15, ^l2460h:0020h)
 
(mess1:0) 21 => gentree ^l4340h:001eh
 
GenPrimaryClass (@16, ^l4340h:001eh) "MESS #1"
 GenViewClass (@17, ^l4340h:0020h)
 GenValueClass (@18, ^l4340h:0026h)
 GenValueClass (@19, ^l4340h:0028h) 

vup

vup [<addr>] [<instance field>]

The vup (Visual UPward query) command is used to examine the visual ancestors of a particular object given by the addr argument, the default *DS:SI, or the -i option. The vup command can be used with the -i option (implied grab) to use the windowed object under the mouse as the object from which to start the upward query. This command is used primarily to ensure correct visual class hierarchy and to determine the field of the given object.

Memory Examination with Modification

assign, imem

The commands in this group are used to modify memory without detaching Swat and editing the application code. They are often used in conjunction with istep , sstep , and pobject to fix any small errors while the code is executing rather than detaching, modifying the actual code, and recompiling. These fixes are temporary, and you must change the source code to enact the real bug fixes.

assign

assign <addr> <value>

The assign command will assign the given value to the given addr , which can only have type byte , word , or dword . Both memory locations and registers may be assigned new values. This command is used to correct minor mistakes or test differing values at run-time without having to recompile.

imem

imem [<addr>] [<mode>]

The imem (inspect memory) command combines examination and modification of memory into one command. It can be used to search through areas of memory and modify problem areas selectively. The command is used to print out memory starting at either the given addr or at the default DS:SI in one of the following modes:

b (bytes)
Displays the memory in terms of bytes.
w (words)
Displays the memory in terms of words.
d (double words)
Displays the memory in terms of double words.
i (instructions)
Displays the memory in terms of instructions.

There are many subcommands to imem which are executed in the same manner as those for istep and sstep . These subcommands are as follows:

b, w, d, i
These will reset the mode to the given letter and redisplay the data in that mode.
n, j, <return> (next, jump)
This will advance to the next piece of data using the appropriate step size (dependent upon the display mode).
p, k, P (previous)
This will retreat to the preceding piece of data. While in instruction mode, if the displayed instruction is wrong, try again with the P subcommand.
<space>
This will clear the data being displayed and allow you to enter a new value in accordance with the current mode. This is exactly like the assign command except for singly and doubly quoted strings. A singly quoted string such as `hello' will have its characters entered into memory starting at the current address with no null byte at the end. A doubly quoted string such as "good-bye" will be entered into memory at the current address with the addition of a null byte at the end of the string. This subcommand may not be used in instruction mode.
q (quit)
Quits the imem mode and returns to the command level.
Ctrl-d
Control-d (down) displays ten successive memory elements in the current display mode.
Ctrl-u
Control-u (up) displays ten of the preceding memory elements in the current display mode.

Up: GEOS SDK TechDocs | Up | Prev: 5.3 Breakpoints and Code Stepping | Next: 5.5 Other Important Commands