KME(1) General Commands Manual KME(1)

kme - Kernel Memory Editor

kme
[-ahirstx] [-A addrscal [-b base] [-c corefile] [-d defsnames] [-D defspaths] [-e emuldev] [-f fepdev] [-g host[:port][,...]] [-g device[:baud][,...]] [-k board_index] [-L extension] [-m hostlist] [-M offset:len] [-n namelist] [-p row] [-P pid] [-S addressmask] [-u uptime] [-U udp_port] [-w colwidth] [params ...]

Kme is a general purpose screen-oriented tool for viewing and modifying memory (such as UNIX kernel memory). Upon invokation, the program continuously displays and updates one or more sections of memory in a spreadsheet-like format. The memory range and display format may be defined on the command line or entered on the screen. Thereafter the corresponding memory contents are continuously displayed and updated on the screen, and may be modified by field entry. Available builtin display formats are character, hex and decimal in various byte, word and longword combinations. The file kme_defs in the current directory may contain user-defined display formats for composite memory structures.

By default, kme displays UNIX memory using the /dev/kmem pseudo file. But kme can display memory in any file or by using a number of alternative access methods, such as its own RW protocol, the GDB remote serial protocol (over TCP or serial), or several other lesser-used methods.

Command line options include:

-a
Do not display address expressions.
-A addrscale
Scale input addresses by multiplying them by addrscale before accessing the corefile. Scale displayed addresses by dividing them by addrscale before displaying them.

The default value for addrscale is 1 (no scaling).

This feature is useful for displaying memory on devices that are not byte addressable, such as DSP memory. For example, when displaying memory on an Analog Devices 2187 DSP, a scale factor of 2 can be used for data memory and a scale factor of 4 can be used for program memory (4 is used instead of 3 because the underlying DSP interface is 32 bits wide, not 24 bits wide).

NOTE: this feature is not very well tested.

-b base
Add the hex number base to all addresses before accessing kernel memory.
-c corefile
Use the file corefile for memory accesses. If the environment variable KME_CORE is defined, it contains the default file name. Otherwise the default is /dev/kmem.
-d defsnames
Read user-defined display definitions from the colon-separated list of file names given in defsnames. If the environment variable KME_DEFS is defined, it contains the list of default file names. Otherwise the default is kme_defs in the current directory. The search path can be modified using the -D option. If a file can't be opened, a warning will be printed except that no warning will be printed if the file kme_defs can't be found.
-D defspaths
When searching for display definition files which aren't absolute file names (see -d), use defspaths as a colon separated list of directories to search. If the environment variable KME_PATH is defined, it contains the list of default directory names. Otherwise the default is the current directory.
-f fepdev
Access kernel memory using DIGI_KME ioctl() calls directed to tty device fepdev.
-g gdblist
Specifies a comma-separated list of TCP/IP hostnames and/or serial port devices where memory should be displayed. Each host/device must provide a GDB remote serial protocol server. An optional :port may be appended to each TCP/IP hostname to override the default GDB port of 9000. An optional :baudrate may be appended to each serial device to override the default baudrate of 38400. Please note that GDB protocol over TCP/IP can be terribly slow on networks with latencies larger than a few milliseconds; serial devices may be faster.
-h
Suppress the one-line help memu normally displayed at screen bottom.
-i
Allow curses to use insert/delete line sequences when updating the screen.
-k board_conc
Default board and concentrator for DigiBoard devices. This is a two digit decimal number.
-L extend.so
Dynamically load a shared object as an extension to the display format capabilities of "kme". Not supported on all operating systems.
-m hostlist
Specifies a colon-separated list of TCP/IP hostnames where memory should be displayed. Each host must provide a kme/udp memory read/write (RW) server, as specified in the services file.
-M offset:len
Access memory by using the mmap() system call to map the corefile directly into kme's address space. Memory is mapped beginning at offset bytes from the beginning of corefile for a length of len bytes. Note that corefile is typically set to /dev/pmem when this option is used. Offset and len are specified using the conventions of strtol(), e.g. 0x500000:0x1000.
-n namelist
Read symbol definitions from the colon separated list of file names given in namelist. If the environment variable KME_SYMS is defined, it contains the default file list. Otherwise the default is kme_syms in the current directory. Each file may be either a binary file (defined by the ld library) or an ASCII file where each line contains a hexidecimal symbol value followed by a alphanumeric symbol name.
-p
Position the initial display so row is at the top of the screen.
-P process_id
Access the memory space of the running process with the specified process_id. Best when combined with the -n option. Note that KME uses PTRACE to view the memory of the process, so viewing is invasive. KME must stop the process each screen refresh, and KME must catch and rethrow all exceptions handled by the process.
-r
Open corefile read-only, and prohibit all attempts to modify memory.
-s
Swap multiple-byte quantities displayed from and written to the core file.
-S addressmask
All addresses read from the symbols file (ascii, coff, or nlisted) will be binary masked with addressmask.
-t
Normally, indexed arrays are displayed in the form of "foo+0xb4". This flag changes it to display the index into the array instead of the offset. The example may then display as "foo[4]". Same as ^T within the program.
-u uptime
Wait uptime tenths of a second after refreshing the screen before beginning a new refresh cycle. Default is 2, limiting screen refresh time to 5/second.
-U port
When accessing memory over a network (option -m or -g), use the specified port rather than the normal default port.
-V
Print version and other information determined by the configuration process when kme was built.
-w colwidth
Set the kme column width to the desired value. The current default is 9, up from the traditional 8.
-x
Print debugging information to stderr.

Additional parameters specify initial screen display requests, or user format defines. The form:

line_number = memory_address / display_format

says to display data at screen line_number from memory_address according to display_format. If line_number is 0 this data will display on the line following the first blank line after the previous display_format has completed. This method of determining format positioning may affect subsequent absolutely anchored references.

The form:

user_display_char = display_format

defines the upper-case single user_display_char to be an abbreviation for the display_format string which follows.

As a special case when using the -f option, the memory address field may be prefixed by one or two hexadecimal digits and a (:) to designate the address space of a particular DigiBoard device. The first digit specifies the PC-bus board, while the second digit (if present) further specifies a concentrator attached to that host adapter. For example the prefix 03:1000 specifies address 0x1000 in the 3rd concentrator attached to the 1st host adapter board.

As a special case when using the -m option, the memory address field may be prefixed by one or two hexadecimal digits and a (:) to designate the hostname and kmed corefile of a particular device. The first digit specifies the nth hostname in the -m hostlist option, while the second digit (if present) further specifies the nth corefile given with kmed's -c corelist option. For example the prefix 01:1000 specifies address 0x1000 in the 2nd corefile attached to the kmed ruuning on the 1st hostname.

The CRT screen display is tabular, with a line number leftmost, the hex memory address next, and memory data fields every 8 columns thereafter across the screen. On a 24 by 80 CRT screen, the display is 23 address lines tall by 8 data columns wide, with a help menu on the bottom line.

Regardless of the screen size, kme supports 200 virtual display lines. At any given time, only a subset of these lines may be viewed through the screen window. The screen window follows the cursor, so the user may scroll through the range in the manner of an editor or spreadsheet.

Through command line parameters, or by screen entry, the user selects the data to be displayed on each address line. From the screen there are two methods to accomplish this. The user may type an m and enter a memory display string or user format character definition just as it would appear on a command line. He may also position the cursor to the desired address field, type the letter c for change, or e for edit, and then enter a string of the form:

address_expression / display_format

In either case, the memory address_expression value immediately appears on the specified display line, followed by zero or more data fields according to the display_format given. If more data fields are specified than fit across the screen, the data is extended to multiple lines, and the memory address of the first data field on each line is displayed in the corresponding address field.

The address_expression may include decimal (0t prefix) and hexidecimal numbers, symbols defined in the namelist file, and the operators listed below. Precedence is modeled after the C-language.
.
Structure element designator. Performs a simple binary add, but with much higher precedence.
{}
2-byte Subscript. The form a{b} returns the 16-bit quantity at address a+b in the corefile.
[]
4-byte Subscript. The form a[b] returns the 32-bit quantity at address a+b in the corefile.
Unary 32-bit indirection.
@
Unary 16-bit indirection.
#
Unary 8-bit indirection.
$
Fetch temporary value. The size of the current display item is available in temporary 0, although it will always be zero the first time the item is displayed. Other temporaries are stored with the $ display operator.
+
Unary plus.
Unary minus.
~
Unary NOT.
^
Swap 2 byte operand.
%
Swap 4 byte operand.
Multiply.
/
Divide. This operator is recognized only in parenthesized expressions, so it is not confused with the / separator character.
%
Modulus.
+
Binary add.
Binary subtract.
<<
Shift left.
>>
Shift right.
<
Less than.
>
Greater than.
<=
Less equal.
>=
Greater equal.
==
Equal.
!=
Not equal.
&
Bitwise AND.
^
Bitwise Exclusive OR.
|
Bitwise Inclusive OR.
?:
C-language style if-else conditional value operator.
<be16>
Conditional swap 2 byte operand. On a big-endian CPU, this operator is a NOP. On a little-endian CPU, this operator is the same as the ^ operator.
<be32>
Conditional swap 4 byte operand. On a big-endian CPU, this operator is a NOP. On a little-endian CPU, this operator is the same as the % operator.
<le16>
Conditional swap 2 byte operand. On a little-endian CPU, this operator is a NOP. On a big-endian CPU, this operator is the same as the ^ operator.
<le32>
Conditional swap 4 byte operand. On a little-endian CPU, this operator is a NOP. On a big-endian CPU, this operator is the same as the % operator.

Builtin format characters are lower-case letters, punctuation marks, and text strings delimited by single and double quotes. As a special case, text strings containing ´\h´ are used to toggle highlighting in the displayed string. You may want to use this for section headers or elsewhere for emphasis. User-defined format characters are upper case alpha letters. Format characters, and format strings enclosed in parens may be preceeded by a decimal repetition count, and concatenated to form a display string of arbitrary complexity. User-defined format characters may include other user-defined characters to a recursive limit of 10.

The builtin format characters are given below. Except as otherwise described, a preceeding decimal repetition behaves exactly as though the following character were repeated that number of times.

+
Increment the working memory address.
Decrement the working memory address.
´text´
Display text. If text is more than 8 characters, use multiple fields as required. Ignore any repetition count.
"text"
Same as above.
.
Display a blank data field.
:
Display nothing, but fetch subsequent blocks of display data from the memory device in blocks of count bytes. The effect continues until the end of the format string. This is often useful when reading device registers.
$
Display nothing, but store the current display address in the temporary value given by count.
%
Display nothing, but toggle the endianness swap flag. If enclosed in parenthesis, the effect ends at the next right paren. Otherwise the effect continues until the end of the format string.
=
Display nothing, but set an internal variable called width to the value of count.
*
Display nothing, but set the new count to the temporary value stored in temporary register number count.
&
Display nothing, but store the value at the current display address in temporary register number count. The width of the value fetched is determined by the current setting of width (see = format).
^
Display nothing, but roundup the value in temporary register number count. The value is rounded up to the next multiple of the current value of width.
#
Display nothing. If enclosed in parenthesis, set the working memory address to the working memory address at the last left paren plus count. Otherwise set the working memory address to address_expression plus count.
a
Mask the next memory byte with 0x7f and display the result in ASCII. Characters below 0x20 are shown with a caret as control characters.
b
Display the next memory byte in hexadecimal.
c
Display the next byte in an unambiguous character format. Characters below 0x20 are shown with a caret as control characters. Characters greater-equal 0x7f are shown in hexadecimal.
d
Display the next 2 bytes as signed decimal.
e
Display the next 4 bytes as an unsigned decimal. If the number is too large to fit in the column, the number is truncated, and a plus sign is displayed on the right. (+) followed by the lower 7 digits of the decimal value.
f
Display the next 4 bytes as a float, with printf mode "%-*.*g", where the first * is the column width, and the second * is the column width - 6.
g
Display the next 8 bytes as an unsigned decimal quadword (long long). To keep the field size down to 16 characters, if the number exceeds 999,999,999,999,999, display a plus sign (+) followed by the lower 15 digits of the decimal value.
h
Display the next 8 bytes as a double, with printf mode "%-*.*g", where the first * is double the column width, and the second * is double the column width - 7.
i
Display the next byte as a character (masked to 7 bits), and the following byte in hexadecimal.
l
Display the next 4 bytes as an 8-digit hexadecimal number.
n
Advance to the next display line.
q
Display the next 8 bytes as a 16-digit hexadecimal quadword (long long).
s
Display string data with zeroes shown as spaces, and other unprintable characters shown as periods. When used with a repeat count, up to 8 characters are shown per field, using as many fields as necessary to show the complete string.
t
Display the next byte of memory as unsigned decimal. u Display the next 2 bytes as an unsigned decimal.
w
Display the next 4 bytes as a float, with printf mode "%-*.8g", where * is double the column width.
x
Display the next 2 bytes of memory in hexadecimal.
z
Display the next 4 bytes of memory in decimal.

Screen commands are all single keystrokes, possibly preceeded by a repeat count. Available commands are:
^F
Page forward.
^U
Page back.
^D
Scroll down. The line scroll count is remembered and becomes the default scroll count next time.
^T
Normally, indexed arrays are displayed in the form of "foo+0xb4". This flag changes it to display the index into the array instead of the offset. The example may then display as "foo[4]". Same as -t on the command line.
^U
Scroll up. The line scroll count is remembered and becomes the default scroll count next time.
^J
Move down to the beginning of the next line.
=
Makes the current row the indirect row. After this is done, the line number is highlighted. This alters the action taken by the * command (below). When an indirect row is selected, the selected address field used by the * command is the first address_expression above this row. Entering this key a second time cancels the effect.
*
When entered over a left column hex address or a hex data field, causes the address under the cursor to temporarily replace the address_expression in the selected address field. The selected address field is the address_expression at or above the current row, unless an indirect row was chosen with the = key. Then it is the first address field at or above the indirect row. Entering this key over an address_expression field restores the original contents.
^
Move to the address field.
+
Advance the memory address of the current display line by the size of the data displayed.
Decrement the memory address of the current display line by the size of the data displayed.
!
Prompt for and execute a shell command.
?
Toggle the appearance of the help menu on the bottom line of the screen.
a
Toggle address display mode.
b
Prompt for and accept a new memory base address.
c
Change the field under the cursor.
d
Delete the current line, and remember it in the save buffer. If a repeat count is given, delete and keep all those lines in a single operation.
e
Edit the contents of the field under the cursor using vi style editing commands.
f
When using an HP64000 emulator, switch command input to control port A. Memory updates will not succeed until switched back by other means.
g
If no repeat count is given, move the cursor to the last virtual display line. If a count is given, move to the line number given in that count.
h
Move left.
i
Insert count lines before the current one.
j
Move down.
k
Move up.
l
Move right.
m
Prompt for and accept either a display line request or a user format macro using the command line syntax.
n
Discard all existing symbol definitions and re-read the namelist files to get a fresh copy.
o
Output (print) the contents of the current screen to a file. If the first character of the file name is the pipe character (|), then the output is piped to a program. If the first two characters of the file name are >> then the output is appended to the file.
p
Put deleted lines back into the display.
q
Quit the program.
r
Discard all existing macro definitions and re-read the defspath files to get a fresh copy.
s
Save the configuration of the current display to a command file. Subsequently executing that command file should automatically recreate the current display.
u
Allow the user to enter a new update interval.
y
Yank (copy) the specified number of screen lines into the save buffer.
z
Zero the memory location under the cursor.

During all field entry, the user may invoke vi-style commands to edit the entry in the style of ksh. This facility supports the basic line editing command characters $.0abcdDfhiIlrstuwx, and the history command characters +-/jkn. The character q quits the field entry w/o change.

On startup, user-defined display formats are read from the colon-separated list of files defined in defspath. In this file, a line beginning with an upper-case letter defines the corresponding user format character. Subsequent indented lines are continuations. Single and double quoted strings are passed verbatim, otherwise white space is discarded, and everything on a line after an unquoted (#) is a comment.

An example file might contain:

A	"thead""ttail""tstart""tmax""rhead""rtail""rstart""rmax"
	8xN
	"cport""seg""rlow""rhigh"n
	4xnN
	"tlow""dcdtime""flow""mstat""lstat""status"n
	2x4bnN
	"imask""baud""dtype""hndshk""xoff""xon""hflush""btime"
	4b2c2bN
	"bcount""portnum""dmask""irq""tmask""tval""bstart"n
	6bxnN
	"rr0""rr1""rr3""rr10""wr0""wr1""wr2""wr3"
	8bN
	"wr4""wr5""wr9""wr11""wr12""wr13""wr14""wr15"
	8bN
	"ov/un""dcdlo""dcdhi""portbit"n
	4xnN
	"mcount""m10ms""mand""mor""mval"n
	xxbbbn 49+
L	l.
N	n

This file defines format A to display a 128 byte structure. The name of each field is displayed immediately above it. The 49+ at the end of the A definition pads out the size of the structure to be 128 bytes so that the + and - commands will work as desired. Normally, double spacing is used between lines, but the user may make it single spaced by redefining N to be Null.

When l format fields are displayed side-by-side, they run together. The L user format overcomes this by placing a blank field after the 8-character hexadecimal number.

The syntax for user defined formats has been enhanced, while remaining compatible with the mode described above. In a complex system, a limit of 26 uppercase user defined formats was restricive and difficult to make mnemonic. You can now also define the above format like this:

!channel	"thead""ttail""tstart""tmax""rhead""rtail""rstart""rmax"
	8xN
	...

You must display this symbolically named format with a leading ! character, so the program knows the difference between a symbol named "channel" and a format string consisting of c, h, and so on. All alphanumeric (plus underbar) characters following the ! are interpreted to be part of the format name.

A new feature in kme is the ability to extend display formats using shared objects. You can write your own C program to add an arbitrary display format to kme. The method to do this is operating system specific. With the GNU toolchain, you would do something like the following:

	$ cc -c dxbmsg.c -o dxbmsg.o
	$ ld -shared dxbmsg.o -o dxbmsg.so
	$ kme -L dxbmsg.so 1=0/!dxbmsg

The shared object must have an _init() routine which calls:

	typedef char * (*DLFUNC)(ulong *addrp);
	add_format(char *name, char *format, DLFUNC dlfunc);

for each new format name that it wants to define. If format is not NULL, then the new format is just a simple string. This is not interesting as you can already do this with kme_defs files. However, if dlfunc is not NULL, then (*dlfunc)(&addr) is called whenever the format needs to be displayed. &addr is a pointer to the variable which holds the current display address.

(*dlfunc)(ulong *addrp) can do one of two things. It can generate a format string on the fly and return a pointer to it. In this case, kme will display the format as returned. Or it can handle doing display updates itself. In this case, it returns NULL and must update the current display address (*addrp) itself.

An example format that displays a real C-string by returning a customized display format string is:

extern unsigned char *mem;
typedef unsigned long ulong;
char *
format(ulong * addrp)
{
	ulong		faddr = *addrp;
	ulong		zaddr;
	static char	fmt[32];
	for (;;)
	{
		if (!getmem(1))
			return "
		if (*mem == 0)
			break;
		(*addrp)++;
	}
	zaddr = *addrp;
	*addrp = faddr;
	sprintf(fmt, "%d a 1+0, zaddr - faddr);
	return (fmt);
}
void
_init(void)
{
	add_format("asciiz", NULL, &format);
}

The above example, although simple to implement, also shows why there is a second method for the way that extensions can choose to operate. The above example is inefficient, as memory will be traversed twice (once in the extension, and once in kme itself). However, the second method currently requires some knowledge of how kme is implemented internally. Translation: we are currently too busy to clean up and expose a set of functions for your convenient use.

/usr/lib/kme_defs
User defined formatting commands.
/dev/kmem
Access to kernel memory.
/etc/services
Internet Services file.

There needs to be a stack of last memory addresses, so that you can use '-' to step backwards thru memory when a variable length format from an extension is being used.
$Revision$ $Date$ BSD