| . @(#)kme.1 $Revision$ $Date$ |
| .TH KME 1 "$Revision$ $Date$" |
| .SH NAME |
| kme \- Kernel Memory Editor |
| .SH SYNOPSIS |
| .TP 7 |
| \fBkme |
| \fB[\-ahirstx\fB] |
| \fB[\-A\ \fRaddrsca\fBl |
| \fB[\-b\ \fRbase\fB] |
| \fB[\-c\ \fRcorefile\fB] |
| \fB[\-d\ \fRdefsnames\fB] |
| \fB[\-D\ \fRdefspaths\fB] |
| \fB[\-e\ \fRemuldev\fB] |
| \fB[\-f\ \fRfepdev\fB] |
| \fB[\-k\ \fRboard_index\fB] |
| \fB[\-L\ \fRextension\fB] |
| \fB[\-m\ \fRhostlist\fB] |
| \fB[\-M\ \fRoffset:len\fB] |
| \fB[\-n\ \fRnamelist\fB] |
| \fB[\-p\ \fRrow\fB] |
| \fB[\-P\ \fRpid\fB] |
| \fB[\-S\ \fRaddressmask\fB] |
| \fB[\-u\ \fRuptime\fB] |
| \fB[\-U\ \fRudp_port\fB] |
| \fB[\fRparams ...\fB] |
| .SH DESCRIPTION |
| \fIKme\fR is a general purpose screen-oriented |
| tool for viewing and modifying UNIX kernel memory. |
| Upon invokation, the program continuously displays and updates |
| one or more sections of \fI/dev/kmem\fR 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 \fIkme_defs\fR in the current directory may contain |
| user-defined display formats for composite memory structures. |
| .PP |
| Command line options include: |
| .TP 15n |
| .BI -a |
| Do not display address expressions. |
| .TP |
| .BI \-A \ addrscale |
| Scale input addresses by multiplying them by \fIaddrscale\fR |
| before accessing the \fIcorefile\fR. Scale displayed addresses |
| by dividing them by \fIaddrscale\fP before displaying them. |
| .sp 1 |
| The default value for \fIaddrscale\fP is 1 (no scaling). |
| .sp 1 |
| 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). |
| .sp 1 |
| NOTE: this feature is not very well tested. |
| .TP |
| .BI \-b \ base |
| Add the hex number \fIbase\fR to all addresses |
| before accessing kernel memory. |
| .TP |
| .BI \-c \ corefile |
| Use the file \fIcorefile\fR for memory accesses. |
| If the environment variable \fIKME_CORE\fR is defined, |
| it contains the default file name. Otherwise the |
| default is \fI/dev/kmem\fR. |
| .TP |
| .BI \-d \ defsnames |
| Read user-defined display definitions from |
| the colon-separated list of file names given in |
| \fIdefsnames\fR. |
| If the environment variable \fIKME_DEFS\fR is defined, |
| it contains the list of default file names. |
| Otherwise the default is \fIkme_defs\fR 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 \fIkme_defs\fP |
| can't be found. |
| .TP |
| .BI \-D \ defspaths |
| When searching for display definition files which aren't |
| absolute file names (see -d), use |
| \fIdefspaths\fR as a colon separated list of directories to |
| search. |
| If the environment variable \fIKME_PATH\fR is defined, |
| it contains the list of default directory names. |
| Otherwise the default is the current directory. |
| .TP |
| .BI \-e \ emuldev |
| Access kernel memory using the HP64000 emulator connected |
| to tty device \fIemuldev\fR. |
| The program assumes a 38400 connection to port B of the emulator. |
| .TP |
| .BI \-f \ fepdev |
| Access kernel memory using DIGI_KME ioctl() calls directed |
| to tty device \fIfepdev\fR. |
| .TP |
| .BI -h |
| Suppress the one-line help memu normally displayed |
| at screen bottom. |
| .TP |
| .BI -i |
| Allow curses to use insert/delete line sequences when |
| updating the screen. |
| .TP |
| .BI \-k \ board_conc |
| .TP |
| .BI \-L \ extension.so |
| Dynamically load a shared object as an extension to the |
| display format capabilities of "kme". Not supported on |
| all operating systems. |
| .TP |
| .BI \-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 server, |
| as specified in the |
| .B services |
| file. |
| .TP |
| .BI \-M \ offset:len |
| Access memory by using the mmap() system call to map the \fIcorefile\fP |
| directly into kme's address space. Memory is mapped beginning at |
| \fIoffset\fP bytes from the beginning of \fIcorefile\fP for a length |
| of \fIlen\fP bytes. Note that \fIcorefile\fP |
| is typically set to \fB/dev/pmem\fP when this option is used. |
| \fIOffset\fP and \fIlen\fP |
| are specified using the conventions of strtol(), e.g. 0x500000:0x1000. |
| .TP |
| .BI \-n \ namelist |
| Read symbol definitions from the colon separated list of |
| file names given in \fInamelist\fR. |
| If the environment variable \fIKME_SYMS\fR is defined, |
| it contains the default file list. |
| Otherwise the default is \fIkme_syms\fR 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. |
| .TP |
| .BI \-p |
| Position the initial display so |
| \fIrow\fR is at the top of the screen. |
| .TP |
| .BI \-P \ process_id |
| Access the memory space of the running process with the |
| specified \fIprocess_id\fR. |
| If process_id is zero, it uses the process id of KME itself. |
| (Useful for debugging KME) |
| Best when combined with the \fI-n\R option. |
| .TP |
| .BI \-r |
| Open \fIcorefile\fR read-only, and prohibit all |
| attempts to modify memory. |
| .TP |
| .BI \-s |
| Swap multiple-byte quantities displayed from and written to the |
| core file. |
| .TP |
| .BI \-S \ addressmask |
| All addresses read from the symbols file (ascii, coff, or nlisted) |
| will be binary masked with \fIaddressmask\fR. |
| .TP |
| .BI \-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. |
| .TP |
| .BI \-u \ uptime |
| Wait \fIuptime\fR tenths of a second after refreshing |
| the screen before beginning a new refresh cycle. |
| Default is 2, limiting screen refresh time to 5/second. |
| .TP |
| .BI \-U \ port |
| When accessing memory over the network (option \fI-m\fR) |
| ignore the \fBkme/udp\fR entry in the services file, |
| and assume the remote is |
| listening on the specified UDP \fIport\fR. |
| .TP |
| .BI -V |
| Print version and other information determined by the configuration |
| process when kme was built. |
| .PP |
| .BI -x |
| Print debugging information to \fIstderr\fR. |
| .PP |
| Additional parameters specify initial screen |
| display requests, or user format defines. The form: |
| .PP |
| .RS |
| \fIline_number \fB= \fImemory_address \fB/ \fIdisplay_format\fR |
| .RE |
| .PP |
| says to display data at screen \fIline_number\fR |
| from at \fImemory_address\fR |
| according to \fIdisplay_format\fR. If \fIline_number\fR is 0 |
| this data will display on the line following the first blank line |
| after the previous \fIdisplay_format\fR has completed. This |
| method of determining format positioning may affect subsequent |
| absolutely anchored references. |
| |
| The form: |
| .PP |
| .RS |
| \fIuser_display_char \fB= \fIdisplay_format\fR |
| .RE |
| .PP |
| defines the upper-case single \fIuser_display_char\fR |
| to be an abbreviation for the \fIdisplay_format\fR string which follows. |
| .PP |
| As a special case when using the \fB-f\fR |
| option, the memory address field may be prefined by one or two |
| hexidecimal digits and a (\fB:\fR) 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 \fB03:1000\fR specifies address 0x1000 |
| in the 3rd concentrator attached to the 1st host adapter board. |
| .SH SCREEN\ DISPLAY |
| 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. |
| .PP |
| Regardless of the screen size, \fIkme\fR 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. |
| .PP |
| 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 \fBm\fR 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 \fBc\fR for change, |
| or \fBe\fR for edit, |
| and then enter a string of the form: |
| .PP |
| .RS |
| \fIaddress_expression\fR \fB/ \fIdisplay_format\fR |
| .RE |
| .PP |
| In either case, the memory \fIaddress_expression\fR value |
| immediately appears on the specified display line, |
| followed by zero or more data fields according to |
| the \fIdisplay_format\fR 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. |
| .PP |
| The \fIaddress_expression\fR 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. |
| .RS |
| .TP 8 |
| .B . |
| Structure element designator. |
| Performs a simple binary add, |
| but with much higher precedence. |
| .TP 8 |
| .B {} |
| 2-byte Subscript. |
| The form |
| .IB a { b } |
| returns the 16-bit quantity at address |
| .IB a \(pl b |
| in the corefile. |
| .TP |
| .B [] |
| 4-byte Subscript. |
| The form |
| .IB a [ b ] |
| returns the 32-bit quantity at address |
| .IB a \(pl b |
| in the corefile. |
| .TP |
| .B \(** |
| Unary 32-bit indirection. |
| .TP |
| .B @ |
| Unary 16-bit indirection. |
| .TP |
| .B # |
| Unary 8-bit indirection. |
| .TP |
| .B $ |
| 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 |
| .B $ |
| display operator. |
| .TP |
| .B \(pl |
| Unary plus. |
| .TP |
| .B \(mi |
| Unary minus. |
| .TP |
| .B ~ |
| Unary NOT. |
| .TP |
| .B ^ |
| Swap 2 byte operand. |
| .TP |
| .B % |
| Swap 4 byte operand. |
| .TP |
| .B \(** |
| Multiply. |
| .TP |
| .B / |
| Divide. This operator is recognized only in parenthesized expressions, |
| so it is not confused with the |
| .B / |
| separator character. |
| .TP |
| .B % |
| Modulus. |
| .TP |
| .B \(pl |
| Binary add. |
| .TP |
| .B \(mi |
| Binary subtract. |
| .TP |
| .B << |
| Shift left. |
| .TP |
| .B >> |
| Shift right. |
| .TP |
| .B < |
| Less than. |
| .TP |
| .B > |
| Greater than. |
| .TP |
| .B <= |
| Less equal. |
| .TP |
| .B >= |
| Greater equal. |
| .TP |
| .B == |
| Equal. |
| .TP |
| .B != |
| Not equal. |
| .TP |
| .B & |
| Bitwise AND. |
| .TP |
| .B ^ |
| Bitwise Exclusive OR. |
| .TP |
| .B | |
| Bitwise Inclusive OR. |
| .TP |
| .B ?: |
| C-language style if-else conditional value operator. |
| .TP |
| .B <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 |
| .B ^ |
| operator. |
| .TP |
| .B <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 |
| .B % |
| operator. |
| .TP |
| .B <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 |
| .B ^ |
| operator. |
| .TP |
| .B <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 |
| .B % |
| operator. |
| .RE |
| .PP |
| 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 |
| .I 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. |
| .PP |
| 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. |
| .TP 10 |
| .B \(pl |
| Increment the working memory address. |
| .TP |
| .B \(mi |
| Decrement the working memory address. |
| .TP |
| \fB\'\fItext\fB\'\fR |
| Display \fItext\fR. If \fItext\fR is more than 8 characters, use multiple |
| fields as required. Ignore any repetition count. |
| .TP |
| \fB"\fItext\fB"\fR |
| Same as above. |
| .TP |
| .B \. |
| Display a blank data field. |
| .TP |
| .B : |
| Display nothing, but fetch subsequent blocks of display data from the |
| memory device in blocks of |
| .I count |
| bytes. |
| The effect continues until the end of the format string. |
| This is often useful when reading device registers. |
| .TP |
| .B $ |
| Display nothing, but store the current display address in the |
| temporary value given by |
| .I count. |
| .TP |
| .B % |
| 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. |
| .TP |
| .B = |
| Display nothing, but set an internal variable called |
| .I width |
| to the value of |
| .I count. |
| .TP |
| .B * |
| Display nothing, but set the new |
| .I count |
| to the temporary value stored in temporary register number |
| .I count. |
| .TP |
| .B & |
| Display nothing, but store the value at the current display |
| address in temporary register number |
| .I count. |
| The width of the value fetched is determined by the current |
| setting of |
| .I width |
| (see = format). |
| .TP |
| .B ^ |
| Display nothing, but roundup the value in temporary register |
| number |
| .I count. |
| The value is rounded up to the next multiple of the current |
| value of |
| .I width. |
| .TP |
| .B # |
| Display nothing. |
| If enclosed in parenthesis, set the working memory address to |
| the working memory address at the last left paren plus \fIcount\fR. |
| Otherwise set the working memory address to |
| \fIaddress_expression\fR plus \fIcount\fR. |
| .TP |
| .B 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. |
| .TP |
| .B b |
| Display the next memory byte in hexadecimal. |
| .TP |
| .B 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. |
| .TP |
| .B d |
| Display the next 2 bytes as signed decimal. |
| .TP |
| .B e |
| Display the next 4 bytes as an unsigned decimal. To keep the field |
| size down to 8 characters, if the number exceeds 9,999,999, display |
| a plus sign |
| .RB ( \+ ) |
| followed by the lower 7 digits of the decimal value. |
| .TP |
| .B f |
| Display the next 4 bytes as floating point number with |
| printf mode "%8f". |
| This is probably terribly broken if your longs and your |
| floats are different sizes. |
| .TP |
| .B 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 |
| .RB ( \+ ) |
| followed by the lower 15 digits of the decimal value. |
| .TP |
| .B i |
| Display the next byte as a character (masked to 7 bits), |
| and the following byte in hexadecimal. |
| .TP |
| .B l |
| Display the next 4 bytes as an 8-digit hexadecimal number. |
| .TP |
| .B n |
| Advance to the next display line. |
| .TP |
| .B q |
| Display the next 8 bytes as a 16-digit hexadecimal quadword (long long). |
| .TP |
| .B 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. |
| .TP |
| .B t |
| Display the next byte of memory as unsigned decimal. |
| .B u |
| Display the next 2 bytes as an unsigned decimal. |
| .TP |
| .B x |
| Display the next 2 bytes of memory in hexadecimal. |
| .TP |
| .B z |
| Display the next 4 bytes of memory in decimal. |
| .SH SCREEN_COMMANDS |
| Screen commands are all single keystrokes, possibly preceeded by a |
| repeat count. Available commands are: |
| .TP 5 |
| .B ^F |
| Page forward. |
| .TP |
| .B ^U |
| Page back. |
| .TP |
| .B ^D |
| Scroll down. The line scroll count is remembered and becomes |
| the default scroll count next time. |
| .TP |
| .B ^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. |
| .TP |
| .B ^U |
| Scroll up. The line scroll count is remembered and becomes |
| the default scroll count next time. |
| .TP |
| .B ^J |
| Move down to the beginning of the next line. |
| .TP |
| .B ^ |
| Move to the address field. |
| .TP |
| .B \(pl |
| Advance the memory address of the current display line |
| by the size of the data displayed. |
| .TP |
| .B \(mi |
| Decrement the memory address of the current display line |
| by the size of the data displayed. |
| .TP |
| .B ! |
| Prompt for and execute a shell command. |
| .TP |
| .B ? |
| Toggle the appearance of the help menu on the bottom |
| line of the screen. |
| .TP |
| .B a |
| Toggle address display mode. |
| .TP |
| .B b |
| Prompt for and accept a new memory base address. |
| .TP |
| .B c |
| Change the field under the cursor. |
| .TP |
| .B 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. |
| .TP |
| .B e |
| Edit the contents of the field under the cursor using \fIvi\fR |
| style editing commands. |
| .TP |
| .B f |
| When using an HP64000 emulator, switch command input to control |
| port A. Memory updates will not succeed until switched back |
| by other means. |
| .TP |
| .B 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. |
| .TP |
| .B h |
| Move left. |
| .TP |
| .B i |
| Insert \fIcount\fR lines before the current one. |
| .TP |
| .B j |
| Move down. |
| .TP |
| .B k |
| Move up. |
| .TP |
| .B l |
| Move right. |
| .TP |
| .B m |
| Prompt for and accept either a display line request or |
| a user format macro using the command line syntax. |
| .TP |
| .B n |
| Discard all existing symbol definitions and re-read the |
| \fInamelist\fR files to get a fresh copy. |
| .TP |
| .B o |
| Output (print) the contents of the current screen to a file. |
| If the first character of the file name is the pipe character (\fB|\fP), |
| then the output is piped to a program. If the first two characters |
| of the file name are \fB>>\fP then the output is appended to the file. |
| .TP |
| .B p |
| Put deleted lines back into the display. |
| .TP |
| .B q |
| Quit the program. |
| .TP |
| .B r |
| Discard all existing macro definitions and re-read |
| the \fIdefspath\fR files to get a fresh copy. |
| .TP |
| .B s |
| Save the configuration of the current display to a command |
| file. Subsequently executing that command file should |
| automatically recreate the current display. |
| .TP |
| .B u |
| Allow the user to enter a new update interval. |
| .TP |
| .B y |
| Yank (copy) the specified number of screen lines into the |
| save buffer. |
| .TP |
| .B z |
| Zero the memory location under the cursor. |
| .PP |
| During all field entry, the user may invoke vi-style commands to |
| edit the entry in the style of \fIksh\fR. |
| This facility supports |
| the basic line editing command characters \fB$.0abcdDfhiIlrstuwx\fR, |
| and the history command characters \fB+-/jkn\fR. |
| The character \fBq\fR quits the field entry w/o change. |
| .SH USER\ DISPLAY\ FORMATS |
| On startup, user-defined display formats are read from the |
| colon-separated list of files defined in \fIdefspath\fR. |
| 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. |
| .PP |
| An example file might contain: |
| .PP |
| .nf |
| .TA 4 |
| 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 |
| .fi |
| .PP |
| This file defines format \fBA\fR to display a 128 byte |
| structure. The name of each field is displayed immediately |
| above it. |
| The \fB49+\fR at the end of the \fBA\fR definition pads out |
| the size of the structure to be 128 bytes so that the \fB+\fR |
| and \fB-\fR 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. |
| .PP |
| When \fBl\fR format fields are displayed side-by-side, |
| they run together. The \fBL\fR user format overcomes this by |
| placing a blank field after the 8-character hexadecimal number. |
| .PP |
| 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: |
| |
| .nf |
| .TA 4 |
| !channel "thead""ttail""tstart""tmax""rhead""rtail""rstart""rmax" |
| 8xN |
| ... |
| .fi |
| |
| You must display this symbolically named format with a |
| leading \fB!\fR character, so the program knows the difference |
| between a symbol named "channel" and a format string consisting |
| of \fBc\fR, \fBh\fR, and so on. All alphanumeric (plus underbar) |
| characters following the \fB!\fR are interpreted to be part of the format |
| name. |
| .SH "EXTENSIONS" |
| 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: |
| |
| .nf |
| .TA 4 |
| $ cc -c dxbmsg.c -o dxbmsg.o |
| $ ld -shared dxbmsg.o -o dxbmsg.so |
| $ kme -L dxbmsg.so 1=0/!dxbmsg |
| .fi |
| |
| The shared object must have an |
| .I _init() |
| routine which calls: |
| |
| .nf |
| .TA 4 |
| typedef char * (*DLFUNC)(ulong *addrp); |
| |
| add_format(char *name, char *format, DLFUNC dlfunc); |
| .fi |
| |
| for each new format |
| .I name |
| that it wants to define. If |
| .I 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 |
| .I dlfunc |
| is not NULL, then (*dlfunc)(&addr) |
| is called whenever the format needs to be displayed. |
| .I &addr |
| is a pointer to the variable which holds the current display |
| address. |
| .PP |
| .I (*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. |
| .PP |
| An example format that displays a real C-string by returning |
| a customized display format string is: |
| .nf |
| .TA 8 |
| 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+\n", zaddr - faddr); |
| |
| return (fmt); |
| } |
| |
| void |
| _init(void) |
| { |
| add_format("asciiz", NULL, &format); |
| } |
| .fi |
| .PP |
| 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. |
| .SH FILES |
| .TP 20 |
| /usr/lib/kme_defs |
| User defined formatting commands. |
| .TP |
| /dev/kmem |
| Access to kernel memory. |
| .TP |
| /etc/services |
| Internet Services file. |
| .SH BUGS |
| 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. |
| .PP |