dprobes.lang(8)

NAME

Dynamic Probes Program File Format and Language Reference

DESCRIPTION

The Dynamic Probes (dprobes) facility can be used to
insert software probes dynamically into executing code
modules. When a probe is fired, a user written probe-handler is executed. The probe-handler is a program written
in an assembly-like language, based on the Reverse Polish
Notation (RPN).

Dynamic Probes also allows probes to be fired on specific
type of memory accesses(execute|write|read or write|io).
This is made possible by using the debug registers available on Intel x86 processors. These probes are called
watchpoint probes. Watchpoint probes are not currently
available for S/390.

A probe program file specifies one or more probes for an
executable program. It consists of a file header followed
by a set of probe definitions. A probe definition contains the probe's identity and a series of instructions
that make up the probe handler.

The assembly-like language in which the probe handlers are
written provides:
- arithmetic/logical/bitwise operations
- control flow instructions (conditional branching/calls)
- preprocessing directives (same as those in C language)
Special instructions are provided for a probe handler to:
- access CPU registers
- access user/kernel memory contents
- access key system variables
- access IO ports
- log data into a buffer
- exit to other debug facilities
RPN instructions work on a circular stack of 1024 elements. The top of the stack is the only element accessible
at any time. Typical instruction to place a data item on
to the top of the stack is by a push instruction. Similarly, a pop instructions a retrieves the data item on the
top of the stack.
The stack elements are of fixed size (machine word length:
4 bytes on IA32) and instructions always operate on integral number of elements. The stack pointer will always be
aligned on a machine word length boundary. Thus, even if a
byte is pushed on to the stack, it will be padded to size
of machine word length and placed on the stack.
In addition to RPN program stack, RPN program interpreter
also provides a call stack. Call stack is primarily present to hold the return address of the call rpn instruction.
RPN language supports Exception Handling and Stack Tracing. Several kinds of faults can occur when rpn instructions are executed. RPN program interpreter generates different exceptions based on the type of fault. Programmer
has the option of catching the exceptions and try to
recover from faults by coding exception handlers. Programmer has the option of masking/unmasking different
exceptions. Some exceptions are non-maskable. Maskable
exceptions are not generated if they are masked. Nonmaskable exceptions terminate the probe program interpretation if they are masked.
When an exception is generated, programmer has the option
to store probe program execution state (RPN stack entries,
probe point details, call chain etc) in Stack trace buffer. This is called stack tracing. Stack trace buffer data is logged along with the normal dprobes log(see man
page dprobes(8) ) when the probe program terminates. Programmer can also store the execution state at arbitrary
time during probe program execution by using an rpn
instruction (explained later).
Exception handling and Stack Tracing is primarily intended to be used by High Level Language(HLL) DProbes Compiler. HLL compiler allows probe programs to be written in C-like language, which will then be compiled into RPN language.
Refer to the section RPN Exception Handling and Stack Tracing for complete explanation.
The dprobes interpreter provides some internal registers which the probe program can make use of. There are rpn
instructions provided to access/modify these.
Top of the Stack Pointer register(TSP) This register always contains the pointer to top of the RPN stack. This
register gets modified on every push and pop rpn instruction.
Stack Base Pointer register(SBP) This register is intended to be a pointer to arbitrary locations on RPN stack. SBP
is stored/restored on every call/return. Programmer can
use SBP as pointer to the base of RPN stack during the
call.
Log Pointer register(LP) Holds the value of the current dprobes log buffer pointer. It is initialized to the
beginning of the user log area in the log buffer. Note
that a few bytes in the beginning of the log buffer are
used to store the log header elements.
Previous Log Pointer register(PLP) PLP will be maintained as a lagging value of LP. This will normally be the same
value as LP when a logging instruction starts execution.
PLP is updated to LP only if logging instruction succeeds.
Using PLP, programmer has the option of backing out the
partial log in the log buffer if logging fails.

PROBE PROGRAM FILE FORMAT

Probe Program file consists of the following sections:
* File Header
* Probe Point Definitions (one or more)
- Probe Point Header
- RPN Instructions
Comments can be specified anywhere in the probe program
file. Comments start with two backslashes(//) and extend
up to the end of the line. Blank lines are allowed
anywhere in the probe program file.
File header and each probe point header consist of a number of statements of the key = value format.
Numeric values may be specified in decimal or hexadecimal.
Hexadecimal values have to be prefixed with 0x , as in the
C language.
Except the value of name= statement in the file header,
everything else is case-insensitive. The value of name=
has to be case-sensitive as the executable file names in
Linux are case-sensitive.
All the sections are defined below in detail.
PROBE PROGRAM FILE HEADER
File header may comprises of one or more statements of the
key = value format. Any combination of the below explained statements may be specified with the name = statement
being mandatory.
name = <modulename>
<modulename> is the name of the module on which probe is
to be applied. It needs to be specified within quotes if
it contains any characters other than a-zA-Z0-9.
For ex.:
name = testapp (valid)
name = /home/user/testapp (invalid)
name = "/home/user/testapp" (valid)
name = "a+b/testapp" (valid).
modtype = <typename>
Type of the module. <typename> can take the any of the
following values:
kernel - the name specified above is the kernel
kmod - the name specified above is a kernel module
user - the name specified above is user
space module. It could be an executable
file or a shared library
vars = <n>
Probe handlers can use a specified number (<n>) of local
variables. Each variable is of a fixed size of 4 bytes.
Many instructions can take a variable as an operand, usually referred to as "lv,index", where index is the variable index from 0 to <n>-1. They are all initialized to
zero. Variables retain their values across probe hits.
These variables are available to all the probe handlers in
this probe program. Default value of <n> is 0 which
implies that this probe program does not make use of variables.
gvars = <n>
<n> specifies the number of global variables that the
probe handler can use. The use and accessing mechanisms
of global variables are similar to local variables except
that they are accessible across probe points. i.e., they
are global in nature. Default value of <n> is 0 which
implies that this probe program does not make use of
global variables.
groupdef = <group_name>[ <group_name>[ <group_name> ...]] This field is used to define all the valid group definitions which can be used by the individual probe points.
The <group_name> used in the group field of any probepoint header should have a definition present in this
field.
typedef = <type_name>[ <type_name>[ <type_name> ...]] This field is used to define all the valid type definitions which can be used by the individual probe points.
The <type_name> used in the type field of any probe-point
header should have definition present in this field.
major = <n>
<n> is the number to be assigned as the probe point major
code, The major code can be used for easy identification
of the log generated by the probe handlers specified in
this program. Default value is 0.
id = <n>
<n> is a number which can be used as probe program identifier. This is not validated for uniqueness. Default value
is 0.
logmax = <n>
<n> is the maximum number of bytes that can be logged in
the log buffer during one run of a probe handler. Default
is 1024 bytes.
jmpmax = <n>
<n> is the maximum number of jumps and loop iterations
allowed for one run of a probe handler. This is needed to
ensure that probe handlers will not loop infinitely causing the system to hang. Default is 256.
logonfault = <yes|no>
This specifies if the probe on faulting instruction should
produce log or not. The default action is not to produce
log. But if yes is specified, even if the probed instruction faults, the log is generated. This keyword in probe
program file header applies uniformly to all the probes
specified in this probe program file.
PROBE-POINT DEFINITION
Probe-Point Header:
Probe point header consists of statements of the key =
value format. The valid statements are explained below.
These can be specified in any order, with the exception
that offset = <n> must appear first. opcode = <n> and offset = <n> statements are mandatory, remaining statements are optional.
In case of kernel mode probe program files, instead of
offset = <n> one can specify address = statement (explained below) to specify the probe location by its
absolute linear address.
offset = <n>
<n> is the offset within the module where probe-point will
be applied. It can also be specified symbolically using
function symbol names and symbol expressions. e.g offset
= main + 0x10 By default, the symbols will be looked up in
the module specified on the name= line in the file header.
The file to be used for looking up the symbols can also be
specified on the --insert command line using --sym option. Kernel symbols can only be looked up in the
System.map file. The pathname of System.map should be specified using the --sym option on the command line.
See man page dprobes(8) for more details.
address = <n1>[:<n2>]
This statement may be present only in kernel mode probe
program files. n1 specifies the absolute virtual address
of the probe location. For watchpoint probes, n1 and n2
together specify the range of memory address for which the
watchpoint is active. n1 is the lower address and n2 is
the higher address of the range. Note that if this range
is not consistent with the range specified by the processor, probes won't be inserted. On Intel x86 processors,
the allowed memory ranges are 1, 2 and 4 bytes. Note that
n2 is an optional argument here and it has no meaning in
case of breakpoint probes.
This statement is mutually exclusive with the offset = <n> statement. Only one of them should be present. Instead of
specifying the probe point by offset, this statement can
be used to specify it directly by its absolute linear
address. However, this statement can also take symbolic
expressions.
watchpoint = <x|w|rw|io> This classifies the probe as watchpoint type and also specifies the type of watchpoint
probe. This statement can be present only in the kernel
mode probe program files. When this statement is not present, probes are meant to be of breakpoint type. (Currently not implemented on S/390)
x: Watchpoint probes will be hit on instruction fetch from
the address specified in 'address =' statement. Here the valid address range is 1 byte.
w: Watchpoint probes will be hit if any write is made to
the address range specified in 'address =' statement. Valid address ranges are 1, 2 and 4 bytes.
rw: Watchpoint probes will be hit if any read or write
occurs in the address range specified. Valid address
ranges are 1, 2 and 4 bytes.
io: Watchpoint probes will be hit if any io read or write
happens in the address range specified. Valid address
ranges are 1, 2 and 4 bytes.
Probes won't be applied if the address range specified is
not consistent with the address range specified by the
processor.
Note: If watchpoint probes are to be put on user address , the user address should be specified in a kernel mode
probe program file. Also note that user mode watchpoints
are global. i.e., the are active across all process contexts.
See Example 7 in COMPLETE EXAMPLES OF RPN for typical use of watchpoint probes.
opcode = <n>
<n> is the first byte of the opcode of the instruction
present at the probe location (IA32), or the first two
bytes of an instruction which may be the opcode, the
opcode and part of the operands, or part of the opcode
(S390). At the time of inserting probes, the opcode present there is compared with the one specified here and the
probe is applied only if they match. This is to ensure
that probe is actually being inserted in the intended
location.
Opcode specification is mandatory only for breakpoint
probes. For watchpoint probes, it may not be specified.
Note that only the first byte of the instruction on which
a probe is desired is specified in this statement. If the
instruction has a prefix, the prefix byte has to be specified here.
There are a few instructions on which probes cannot be
placed. They are:
int3, int, into, wait (IA32) svc, lpsw (S/390)
and floating point instructions when FPU is emulated.
WARNING: The onus is on the user to correctly specify the offset and the opcode statements. Incorrect use may cause
probes to be inserted in the middle of an instruction
which could lead to a system crash and data corruption.
While Dprobes interoperates well with other debuggers, if
a breakpoint is placed using another debugger at the same
location where a probe already exists, the breakpoint will
be ineffective.
Although probes on floating point instructions are not
allowed, when the FPU is emulated, we are not explicitly
disallowing probes on FXSAVE and FXSTOR instructions. Putting probes on these instructions when FPU is emulated
might result in unexpected behavior.
group = <group_name>
This field classifies the probe-point under some specified
group. The <group_name> specified here should be present in the <group_name> list present in the groupdef field of the probe program file header. The group field is used by
the --apply-ppdf option on the command line to selectively apply the probes.
type = <type_name>
This field classifies the probe-point under some specified
type. The <type_name> specified here should be present in the <type_name> list present in the typedef field of the probe program file header. The type field is used by the
--apply-ppdf option on the command line to selectively apply the probes.
Note: See Example 6. in COMPLETE EXAMPLES OF RPN for usage
of the keywords group, type, groupdef and typedef.
minor = <n>
<n> is the number to be assigned as the probe point minor
code, The minor code can be used for easy identification
of the log generated by this probe handler. Default value
is 0.
ignore = <n>
If this entry is present, this probe handler will not be
executed the first <n> times it is hit. Default value is
0. This instruction was called pass_count in dprobes versions before 3.4.0.
maxhits = <n>
This probe point will be disabled automatically after it
is hit <n> times. Default value is 0x7fffffff. This
instruction was called max_hits in dprobes versions before 3.4.0.
logonfault = <yes|no>
This keyword has the same meaning as the logonfault keyword present in the probe program file header, but here it
specifies the 'log on fault' behavior for this probe. Any
settings by the use of logonfault keyword in probe program file header gets over-ridden here.
INSTRUCTION SET
Probe handler consists of any meaningful combination of
valid RPN instructions. The general format of an instruction is:
[label:] operator [op1 [,op2 [, ..... ]]] [// comment] [// comment]
label: optional string used to specify "jmp" targets. It has to start with a non-numeric character and delimited by
a ':' and can consist of any alpha-numeric characters. An
RPN instruction has to follow a label.
operator: any of the instructions listed below.
opN: any operands required for the instruction.
Note that TOS in the following description refers to the
contents of the top of the stack on which RPN instructions
operate.
The Instructions in this language are classified under
various categories as follows:
RPN Execution Group:
jmp <label>
program control is transferred to <label>
jlt <label>
program control is transferred to <label> if TOS < 0.
jle <label>
program control is transferred to <label> if TOS <= 0.
jgt <label>
program control is transferred to <label> if TOS > 0.
jge <label>
program control is transferred to <label> if TOS >= 0.
jz <label>
program control is transferred to <label> if TOS == 0.
jnz <label>
program control is transferred to <label> if TOS != 0.
Loop <label>
Decrement TOS and jump to <label> if TOS != 0.
Note: If the total number of branches (jumps+loops) taken
during one run of the probe handler exceeds the jmpmax
value specified in the program file header, probe handler
will generate a JMP_MAX exception or will terminate if
this exception is masked.
call <procname>
Call the procedure <procname>. When a procedure is
called, the return addresses are stored on the call stack,
If number of nested calls exceeds 32 at any point of time,
CALL_MAX exception is generated. If the exception is
masked, the probe handling is terminated.
ret
Return from the procedure. The address to return to is the
top of the call stack. If ret doesn't have an associated
call (can happen if ret is done with an empty call stack)
CALL_MAX exception is generated. If the exception is
masked, the probe handling is terminated.
Format of Procedure:
A procedure can be written in the probe program file using
the proc and endproc instructions. These procedures are accessible to all the probe handlers in this probe program
file. Procedures defined in one probe program cannot be
called from a different probe program. Note that, using
the preprocessor directive #include <filename> one can write libraries of probe programs and include them in multiple probe program files.
The format of a procedure definition is:
proc <procname>
:
instructions
:
ret
endproc
callk
This instruction can be used to allow one or more kernel
modules to be called from the RPN command interpreter.
Modules registering for this will use the GKHI mechanism
and will exist as hook_exits to DProbes. A sample kernel
module that registers exits to be called when callk
instruction is interpreted, callk.c, can be found in the
command directory.
abort
Terminate the execution of the probe handler without saving the data logged so far.
exit
Terminate the execution of the probe handler, saving the
data logged so far.
exit <n>
This facility is used to interface with other debug facilities. The debug facilities are invoked when this
instruction is encountered in the probe handler. This
instruction terminates the probe handler. The exit n
instruction can be used when it is more appropriate to
invoke the exit facilities when certain conditions are
detected in the probe handler. The value of <n> can be
any one of the following:
1 = SGI kdb
exit 1 invokes kdb only for kernel mode probes. For
user mode probes it is equivalent to nop as user
applications are not expected to use kernel debugger. When kdb is terminated, probe handler terminates. This instruction will be effective only if
the kernel is configured with the kdb support.
2 = SGI crash dump
exit 3 takes the crash dump for only kernel mode
probes. This instruction will be effective only if
the kernel is configured with the crash dump support. Note that dump taken might not show the correct back trace.
3 = Core Dump
exit 3 dumps the core of the process which has
probe in it. After core dump, the probe handler
terminates. Also dumping the core of the process
doesn't cause the process to stop. This instruction is meaningful only in case of user probes.
Any other value of <n> will result in INVALID_OPERAND
exception being generated.
remove
Remove the current probe. This can be used to remove a
probe from within the probe handler when certain conditions are detected that may render this probe unnecessary.
nop
No operation.
Logging Group
setmin <minor>
Override the minor code with <minor> when data for this
probe point is logged to the log buffer.
setmin
Override the minor code with TOS when data for this probe
point is logged to the log buffer.
setmaj <major>
Override the major code with <major> when data for this
probe point is logged to the log buffer.
setmaj
Override the major code with TOS when data for this probe
point is logged to the log buffer.
Note that the instructions to temporarily override major
and minor codes are provided to enable users to easily
identify of certain log records in the log buffer.
log str
It pops two elements from the RPN stack ( addr and n in
that order). It logs the n number of bytes starting at the
addr. Logging is discontinued if a NULL byte is encountered. The NULL byte is not logged. If the log buffer
becomes full, the program interpreter will either generate
LOG_MAX exception if this exception is unmasked or will
exit. In either case, the partial string is not logged.
If the log is successful, the logged string is prefixed by
a token byte of 1 and a word indicating the length of the
string logged. This data is intended to be used by any
applications that may try to format the data collected in
the log buffer.
If the logging fails due to invalid memory reference the
fault record is logged. Then INVALID_ADDR exception is
generated if this exception is unmasked or probe handler
is terminated if it is masked. Fault record consists of a
token byte of -1(0xff), an unsigned short length of 4, and
the faulting address(4 bytes).
This instruction is intended to be used to log null-terminated strings at a known address to the log buffer. The
length is only used to specify the upper limit on the
string length. An example scenario would be (say we know
that address of the string is in ECX)
push w, 256
push R, ECX
log str
log arf
This instruction has been renamed to log str in dprobes v3.4.0.
log ars
This instruction providing segmented addressing mode has
been removed from dprobes v3.4.0.
log mrf
It pops two elements from the RPN stack ( addr and n in
that order). It logs the n number of bytes starting at the
addr. If the log is successful, the logged data is prefixed by a token byte of 0 and a word indicating the
length of the data logged. This data is intended to be
used by any applications that may try to format the data
collected in the log buffer.
If the logging fails due to invalid memory reference,
fault record is logged and INVALID_ADDR exception is generated. If this exception is masked, the probe handling is
terminated. Fault record consists of a token byte of
-1(0xff), an unsigned short length of 4, and the faulting
address(4 bytes).
This instruction is intended to be used to log any data
structures at a known address to the log buffer. An example scenario to log say the first 40 bytes of the current
task structure would be:
push w, 40
push task
log mrf
log mrs
This instruction providing segmented addressing mode has
been removed from dprobes v3.4.0.
log <count>
Pops <count> number of elements from the RPN stack and stores them in the log buffer.
log b, <count>
log w, <count>
log d, <count>
These instructions have been replaced with the simpler log
<count> instruction in dprobes v3.4.0.
Note that the above logging instructions will generate
LOG_OVERFLOW exception if size of the log exceeds the size
specified on the logmax= statement in the probe program file header. Exception is generated only if it is
unmasked. Partial log is retained.
log
Pops count and logs count number of elements from RPN
stack(by popping) to log buffer.
Note: With this instruction, the actual log is preceded by
a 3 byte prefix having a token byte of 7 and a word indicating number of RPN elements logged. If logging fails
due to log buffer overflow, LOG_OVERFLOW exception is generated(only if this exception is unmasked). Partial log is
retained.
Local Variable Group
The following instructions are provided to manipulate
variables. Note that the local here means that the variables defined in a probe program are not accessible from
other probe programs. However, variables defined in a
probe program are accessible to all the probe handlers in
that program, as mentioned before.
Variables are identified by their index. An index must be
in the range 0 to n where n is the number specified on the
vars= statement in the probe program file header. The
instructions that manipulate local variables obtain the
index of the variable to operate on either as an immediate
operand in the instruction or from the RPN stack (in which
case the value on the top of the stack is considered as
the index). When index specified as an immediate operand,
if its value is not the allowed range, then a compilation
error will be returned when the probe program is being
applied.
push lv, <index>
Push the content of the specified variable on to the RPN
stack.
push lv
Pops an element ( index ) from the stack and pushes the
content of the variable on to the RPN stack.
pop lv, <index>
Pop one element from the RPN stack and set it as the value
of the specified variable.
pop lv
Pops two elements ( value , and index ) from the stack and sets the specified variable to value
move lv, <index>
Set the specified variable to TOS. Note that here the contents of the RPN stack remain unchanged.
move lv
Pops one element ( index ) from the stack and sets the
specified variable to the current TOS.
inc lv, <index>
Increments the specified variable.
inc lv
Pops one element ( index ) from the stack and increments
the specified variable.
dec lv, <index>
Decrements the specified variable.
dec lv
Pops one element ( index ) from the stack and decrements
the specified variable.
log lv
Pops two elements (range and starting index in that order) and logs local variables starting from index=starting index till index=starting index+range to log buffer. The actual log is preceded by a 3 byte prefix having a token byte of 5 and a word indicating number of local variables
logged. If the log buffer becomes full, LOG_OVERFLOW
exception is generated (only if this exception is
unmasked) after logging as many variables as possible.
Note: For all the above instructions accessing local variables, INVALID_OPERAND exception is generated if the index
is exceeds the range specified by vars = statement in the
file header. If this exception is masked, the probe handling is terminated.
Global Variable Group.
Global variables can be accessed across all the probe programs that are active. Probe programs are expected to use
global variables in a cooperative manner. Variables are
identified by their index. An index must be in the range 0 to n where n is the number specified on the gvars= statement in the probe program file header. The instructions
that manipulate global variables obtain the index of the
variable to operate on either as an immediate operand in
the instruction or from the RPN stack (in which case the
value on the top of the stack is considered as the index).
When index specified as an immediate operand, if its value
is not the allowed range, then a compilation error will be
returned when the probe program is being applied.
push gv, <index>
Push the content of the specified variable on to the RPN
stack.
push gv
Pops an element ( index ) from the stack and pushes the
content of the variable on to the RPN stack.
pop gv, <index>
Pop one element from the RPN stack and set it as the value
of the specified variable.
pop gv
Pops two elements ( value , and index ) from the stack and sets the specified variable to value
move gv, <index>
Set the specified variable to TOS. Note that here the contents of the RPN stack remain unchanged.
move gv
Pops one element ( index ) from the stack and sets the
specified variable to the current TOS.
inc gv, <index>
Increments the specified variable.
inc gv
Pops one element ( index ) from the stack and increments
the specified variable.
dec gv, <index>
Decrements the specified variable.
dec gv
Pops one element ( index ) from the stack and decrements
the specified variable.
log gv
Pops two elements (range and starting index in that order) and logs global variables starting from index=starting index till index=starting index+range to log buffer. The actual log is preceded by a 3 byte prefix having a token byte of 6 and a word indicating number of global variables
logged. If the log buffer becomes full, LOG_OVERFLOW
exception is generated (only if this exception is
unmasked) after logging as many variables as possible.
Note: For all the above instructions accessing global
variables, INVALID_OPERAND exception is generated if the
index is exceeds the range specified by gvars = statement in the file header. If this exception is masked, the probe
handling is terminated.
Arithmetic & Logic Group
add
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1+val2 ) on to the stack.
sub
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1-val2 ) on to the stack.
mul
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1*val2 ) on to the stack.
div
Pops two elements ( divisor and dividend ) from the stack and performs an unsigned division (dividend/divisor). Pushes the remainder first and quotient next on to the stack.
idiv
Pops two elements ( divisor and dividend ) from the stack and performs a signed division (dividend/divisor). Pushes the remainder first and quotient next on to the stack.
Note: The division instructions generate DIVIDE_BY_ZERO
exception if divisor is zero. If this exception is
masked, the probe handling is terminated.
neg
Pops one element ( val ) from the stack and pushes its 1's
complement ( ~val ) on to the stack.
and
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1 & val2 ) on to the stack.
or
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1 | val2 ) on to the stack.
xor
Pops two elements ( val1 and val2 ) from the stack and pushes the result of ( val1 ^ val2 ) on to the stack(.
rol <count>
Rotates left TOS by (byte operand) number of bits.
rol
Pops two elements ( val and count ) from the stack, rotates left val
by count number of bits and pushes the result on to the
stack.
ror <count>
Rotates right TOS by (byte operand) number of bits.
ror
Pops two elements ( val and count ) from the stack, rotates right val
by count number of bits and pushes the result on to the
stack.
shl <count>
Shifts left TOS by (byte operand) number of bits.
shl
Pops two elements ( val and count ) from the stack, shifts left val
by count number of bits and pushes the result on to the
stack.
shr <count>
Shifts right TOS by (byte operand) number of bits.
shr
Pops two elements ( val and count ) from the stack, shifts right val
by count number of bits and pushes the result on to the
stack.
pbl
Pops two elements ( bit index n and operand ) from the stack, sets all the bits to the left of bit n-1 of the operand to the value of the bit n-1. Operand is pushed
back to rpn stack.
pbl <n>
Pops one element ( operand ) from the stack, sets all the bits to the left of bit n-1 of the operand to the value of the bit n-1. Operand is pushed back to rpn stack.
pbr
Pops two elements ( bit index n and operand ) from the stack, sets all the bits to the right of bit n-1 of the operand to the value of the bit n-1. Operand is pushed
back to rpn stack.
pbr <n>
Pops one element ( operand ) from the stack, sets all the bits to the right of bit n-1 of the operand to the value of the bit n-1. Operand is pushed back to rpn stack.
Note:
For all these propagate instructions, the valid value of
bit index n ranges between 1 and rpn stack width. If the bit index n is 0 or greater than RPN stack width,
INVALID_OPERAND exception is generated. If this exception
is masked, the probe handling is terminated.
xchg
Exchange the top two elements of the RPN stack.
dup <count>
The TOS will be pushed on to the stack <count> times.
dup
Pops two elements ( val and count ) from the stack and pushes the val on to the stack count+1 times.
ros <count>
Rotate the RPN stack down count number of times. This is
equivalent to popping count elements from the stack.
Register Group
Inside the probe handler, access is provided to two different kinds of register contexts, the user context registers and current context registers. The current context registers refer to the state of the registers at the time
of the probe hit. User context registers refer to the
state of the registers in the current process context just
before it switched to kernel mode. For probes in user
space code, user and current context registers are same.
In the following instructions, r indicates registers in
the current context and u indicates registers in the user
context. Please refer to Appendix A for names of the registers and which registers are valid in these contexts.
push r, <name>
Pushes the contents of the name register in the current
context onto the stack.
push u, <name>
Pushes the contents of the name register in the user context onto the stack.
pop r, <name>
Pops an element ( value ) from the stack sets the contents
of the name register in the current context to it.
pop u, <name>
Pops an element ( value ) from the stack sets the contents
of the name register in the user context to it.
Writing to user and current context registers cs, eip, ss, esp, control and debug registers is not permitted. Also writing to gdtr, ldtr, tr, idtr is not permitted. Registers fs and gs are context independent. Processor registers are directly used when fs and gs are referenced.
WARNING Changing the contents of registers in the probe handlers is dangerous and can cause system crashes and
data corruption. Use these features with caution and only
when you know exactly what you are doing.
Data Group
push <value>
Pushes value onto the stack.
push b, <val>
push w, <val>
push d, <val>
These instructions have been replaced with the simpler
push <value> instruction in dprobes v3.4.0.
push <symbol>
Allowed only for Kernel Symbols. Pushes the address of the symbol onto the stack.
push mem, u8
Pops one element ( addr ) from the stack and pushes a byte
at addr onto the stack.
push mem, u16
Pops one element ( addr ) from the stack and pushes a 16
bit value at addr onto the stack.
push mem, u32
Pops one element ( addr ) from the stack and pushes a 32
bit value at addr onto the stack.
push mem, u64
Pops one element ( addr ) from the stack and pushes a 64
bit value at addr onto the stack.
pop mem, u8
Pops two elements ( val and addr ) from the stack and stores the least significant byte of val at addr
pop mem, u16
Pops two elements ( val and addr ) from the stack and stores the least significant 16bits of val at addr
pop mem, u32
Pops two elements ( val and addr ) from the stack and stores val at addr
pop mem, u64
Pops three elements ( val (64 bit value, two elements) and
addr ) from the stack and stores val at addr
push bif
push wif
push dif
push qif
pop bif
pop wif
pop dif
pop qif
All these instructions have been renamed in dprobes
v3.4.0. So, now the equivalent of push bif is push mem, u8 pop wif is pop mem, u16
All these instructions providing segmented addressing mode
have been removed in dprobes v3.4.0.
push bis
push wis
push dis
push qis
pop bis
pop wis
pop dis
pop qis
All these instructions providing segmented addressing mode
have been removed in dprobes v3.4.0.
Note: The instructions which access memory will generate
INVALID_ADDR exception if the memory accessed is invalid
or is currently paged out. If these exceptions are
masked, the probe handling is terminated.
System Variable Group
The following instructions can be used to access details
of the current process (like the pid) and relevant system
data structures.
push pid
Pushes the pid of the current process onto the stack.
push procid
Pushes the id of the processor, on which the current process is executing, on to the stack.
push task Pushes the address of the current task (system variable current) onto the stack.
IO Group (IA32)
The following instructions can be used to read and write
to IO ports from the probe handlers.
push io, u8
Pops an element ( ioport ) from the stack, reads a byte from ioport and pushes it onto the stack.
push io, u16
Pops an element ( ioport ) from the stack, reads a 16 bit value from ioport and pushes it onto the stack.
push io, u32
Pops an element ( ioport ) from the stack, reads a d32 bit value from ioport and pushes it onto the stack.
pop io, u8
Pops val
and ioport
from the stack, writes the least significant byte of val
to ioport
pop io, u16
Pops val
and ioport
from the stack, writes the least significant 16 bit value
of val to ioport
pop io, u32
Pops val
and ioport
from the stack, writes the 32 bit value val to ioport
Address Verification
The following instructions can be used to verify the
validity of an address before actually accessing it. If
the given address is valid, a zero will be pushed onto the
RPN stack. Otherwise, 1 will be pushed to indicate invalid
address. Note that the execution of a probe handler can be
terminated if it attempts to access any invalid address.
vfyr
Pops an element ( addr ) from the stack and verifies read
access to a byte at addr
vfa
This instruction has been renamed to in dprobes v3.4.0.
vfyrw
Pops an element ( addr ) from the stack and verifies readwrite access to a byte at addr
vsa
This instruction providing segmented addressing mode has
been removed from dprobes v3.4.0.
Miscellaneous
seg2lin
Pops two elements ( offset and selector ) from the stack and converts the segmented address selector:offset into its equivalent flat address and pushes it onto the stack.
This instruction generates SEG_FAULT exception if the
selector is invalid (IA32 only)
cnvrt sxf
This instruction has been renamed to seg2lin in dprobes v3.4.0.
cnvrt sxd
This instruction has been removed from dprobes v3.4.0.

PREPROCESSOR DIRECTIVES

The RPN Compiler works in two passes. In the first pass it
does all the pre-processing for the conditional and unconditional directives and in the second pass it actually
compiles the RPN files. All the conditional directives &
macros can be specified in an RPN file in the same way as
in C language.
The following types of directives are supported in an RPN
file:
#define <variable> <value>
#include <RPN filename>
#ifdef <some-condn>
#elseif <other-condn>
#endif

SUBSTITUTION

The RPN compiler allows for substitution of variables from the command line as provided by the GNU C Compiler(gcc). With the -D option in the command line, the keys to be substituted by values can be specified as follows:

dprobes -i <rpn-file> -D key = value where
key is the string present in the RPN file and value is the value (string/numeral) to be substituted for
key.

RPN EXCEPTION HANDLING AND STACK TRACING

Several RPN instructions generate faults during execution.
RPN program interpreter throws exceptions when it encounters RPN instruction faults. Interpreter provides infrastructure/instructions for catching the exceptions, handling them, rethrowing the exceptions and propagating them
up the call chain.

When the interpreter throws an exception, it puts the
exception information on the RPN stack. Top of the RPN
stack will look like this when an exception occurs:
+----------------+
| exception code | <-- top of the RPN stack
+----------------+
| parameter 1
+----------------+
| parameter 2
+----------------+
| .
Exception code identifies the type of exception. This depends on the type of RPN instruction fault. Width of
exception code is equal to the RPN stack width. For IA32
and S/390, exception code is of the form:
+--------------------+--------------------+
| u-field | x-field
+--------------------+--------------------+
|31 16|15 0
The u-field is for user use and does not affect the meaning of the exception to the interpreter when the exception
is re-thrown. For non-user exception the u-field is initialized to zero. The x-field actually defines the exception.
The values indicated by parameter 1 and parameter 2 depends on the type of exception.
The following table gives a list of exceptions, associated
parameter meanings and the type of fault causing the
exception.
+-----------------------------------------------------------------------------+
|Ex code parm 1 parm 2

Reason(fault type)

+-----------------------------------------------------------------------------+ |0x0001 Faulting 0 Invalid
memory | | address
reference | | IN
VALID_ADDR
+-----------------------------------------------------------------------------+ |0x0002 Faulting 0 seg2lin
used | | selector
with invalid | selector
| SEG_FAULT
+-----------------------------------------------------------------------------+ |0x0004 jmpmax 0 Max
jumps reached | | allowed
JMP_MAX
+-----------------------------------------------------------------------------+ |0x0010 No of nested 0 call
stack overflow | | calls
or underflow | CALL_MAX
+-----------------------------------------------------------------------------+ |0x0020 0 0 divide
by zero | DIVIDE_BY_ZERO
+-----------------------------------------------------------------------------+ |0x0040 1 - lv out invalid Invalid
operand | | of range in
dex for rpn | instruction | | 2 - gv out
invalid INVALID_OPERAND | of range
index | |
3 - invalid |
propagate bit | | bit
out of index |
range | | | 4 - invalid
exit | | exit code
code
+-----------------------------------------------------------------------------+ |0x0080 invalid rpn Invalid
rpn | | rpn opcode
program instruction | offset
INVALID_OPCODE
+-----------------------------------------------------------------------------+ |0x1000 logmax 0 log
buffer | | value
overflow | LOG_OVERFLOW
+-----------------------------------------------------------------------------+ |0x8000 user user user
exception | | defined
defined USER_EX
+-----------------------------------------------------------------------------+ Masking/Unmasking Exceptions

Exceptions can be selectively masked/unmasked by using the
probe header control statement excpt_mask. Masked exceptions are not generated. Presently only LOG_OVERFLOW and
USER_EX are maskable exceptions. All others are non-maskable. By default excpt_mask is set to 0x0FFF so that these exceptions are masked. If masked non-maskable exception occurs, probe handling will be terminated. Bits in
excpt_mask corresponds to the bits in x-field of the exception code. An exception type can be masked by resetting it's corresponding bit in excpt_mask.

Exception related instructions

sx <handler> / ux
This instruction pair sets an exception handler for any
exceptions generated by the instructions that follow sx
until the instruction ux. So if any exception is generated by an instruction lying between sx and ux, the control is transferred to the label handler Note that handler must be a label local to the current subroutine. If sx is
not matched by a ux, the scope of the exception handler
ends at the subroutine boundary.

push x
Pushes the last exception information (ex code, parm1,
parm2) on to exception stack. Note that the interpreter
remembers the last exception that was generated. push x
either pushes the last generated exception information, if
there was any or pushes NULL information(0, 0, 0).

rx
Raises an exception. Expects to find the exception information on the RPN stack. This instruction along with push
x can be used to re-raise/ throw an exception.

Exception handling - some rules

1. Exceptions handlers cannot nest. That is if there are
nested sx/ux pairs within a subroutine scope, only the
innermost one will be effective.

2. A raised(generated) exception remains handled once a
handler is called.

3. On raising an exception, the handler is implicitly
reset. That is, a handler to catch an exception in a group
of instructions will be effective only for the 1st exception generated by the group. The same handler will not be
called for subsequent exceptions generated by the group.

4. Exceptions propagate up the call chain until a handler
is found. That is if an exception occurs in a sub-routine
which has not set any exception handlers, the exception
will automatically propagate up to the calling routine.
During this, an implicit return is made to the calling
routine.

If the exception is not handled anywhere till the outermost routine, the probe handling is terminated.

5. Program interpreter remembers the last generated exception.

STACK TRACING

Interpreter provides a stack trace buffer to store stack trace information. Stack trace buffer data is logged along with the dprobes log data using dprobes (major,
minor) = (0,0) This data can be used to debug the rpn program.

The size of the stack trace buffer is governed by a file
header control statement excpt_log. Default size of excpt_log is 1024 bytes.

Stack trace information can be filled up in two ways.
Implicitly when an exception is generated or explicitly
using log st instruction.

log st
This instruction writes current stack trace information into the stack trace buffer.

purge st
This instruction clears (flushes) the stack trace buffer.

autostacktrace = [yes|no] This is a file header control statement. If set to yes stack trace information is collected whenever an exception is generated.

Stack trace information has the following format
header
stack trace records(with
3 byte prefix having
a
token byte 2 and wordindi
cating the numbernum
ber of records)
The header consists of
name of the module(with 3
byte prefix having
a
token byte 1 and wordindi
cating the length of
the
string)
offset of the probe point
id of the probe point
major code
minor code
Stack trace records
Stack trace record contains information about the execution state of the probe point. It has the following format:
last exception code or 0
last exception handler
address or -1
last exception parameter
1 or 0
last exception parameter
2 or 0
call stack frame records
(with a 3 byte prefix
having a
token byte of 3 and word
indicating
the number of records)
The number of call stack frame records depends on the number of calls (nested) made at the time log st is executed
(implicitly or explicitly)
Format of call stack frame record called address
return address
RPN stack entries pre
fixed with 3 byte prefix
lv entries prefixed with
3 byte prefix
gv entries prefixed with
3 byte prefix
The 3 byte prefixes associated with RPN stack entries, lv
entries and gv entries indicate the number of RPN stack
entries, local variables and global variables logged and
have token bytes of 4, 5 and 6 respectively.
Prior to the collection of stack trace information, interpreter needs to be told about the range of RPN stack, lv,
and gv entries to be logged as part of stack trace. This
is achieved by the following instructions.
trace pv
Pops two elements ( range and index ). If this call stack frame is logged as part of stack trace, the interpreter
logs the RPN stack entries starting from the stack pointer
index up to index + range. to the stack trace buffer.
trace lv
Pops two elements ( range and index ). If this call stack frame is logged as part of stack trace, the interpreter
logs the local variables starting from index up to index + range to the stack trace buffer.
trace gv
Pops two elements ( range and index ). If this call stack frame is logged as part of stack trace, the interpreter
logs the global variables starting from index up to index + range to the stack trace buffer.
If the interpreter is not told about the range and index
(i.e., if the above instructions are not present in a call
scope), it logs 0 number of RPN stack, lv and gv entries,
while building the call stack frame record for this call
scope. So if any subroutine wants the RPN stack, lv and gv
entries to be logged as part of its call stack, it should
code the above three instructions.
Interpreter provides Stack Trace Pointer register which will always point to the stack trace buffer from where the
next log starts.
Instructions using interpreter internal registers.
push stp
Push(save) the value in stack trace pointer register to
RPN stack.
pop stp
Pop (from the RPN stack) a value to stack trace pointer
register.
push lp
Push(save) the value in log pointer register to RPN stack.
pop lp
Pop(from the RPN stack) a value to log pointer register.
push plp
Push the value in previous log pointer register to RPN
stack.
save sbp
Push (save) the value of stack base pointer register to
RPN stack.
restore sbp
Pop (from RPN stack) a value to stack base pointer
register.
save tsp
Push (save) the value of top of the stack pointer register
to RPN stack.
restore tsp
Pop (from RPN stack) a value to top of the stack pointer
register.
push sbp
Pops an element ( n ) from RPN stack and pushes the stack
element at sbp + n to the top of RPN stack. n can be negative also.
pop sbp
Pops two elements ( value and n ) from RPN stack and sets the contents of stack element at sbp + n to value. Note that n can be negative also.
copy sbp
Pops an element ( n ) and copies (without popping) the
element at RPN TOS to the location pointed by sbp + n in
the RPN stack. n can be negative.
push sbp, n
Pushes the RPN stack element at sbp + n to RPN TOS. n can be negative.
pop sbp, n
Pops an element from RPN stack and stores it in the RPN
stack at the location pointed by sbp + n. Here n can be negative.
copy sbp, n
Copies (without popping) the element at RPN TOS to the
location pointed by sbp + n in the RPN stack. n can be negative.
push tsp
Pops an element ( n ) from RPN stack and pushes the element at tsp + n to TOS. Here tsp refers to the value after n is popped. Here n can be negative.
pop tsp
Pops two elements ( value and n ) from RPN stack and stores the value at the location pointed by tsp + n in the RPN stack. Here tsp refers to the value after value and n are popped. Here n can be negative.
copy tsp
Pops and element ( n ) from RPN stack and copies the element at TOS (after popping n ) to the location pointed by
tsp + n in the RPN stack. Here tsp refers to value after n is popped. Here n can be negative.
push tsp, n
Pushes the RPN stack element at tsp + n to RPN TOS. Here
tsp refers to the stack location before the instruction
executes. n can be negative.
pop tsp, n
Pops a RPN stack element and stores it at location pointed
by tsp + n in the RPN stack. tsp refers to the stack location before the instruction executes. n can be negative.
copy tsp, n
Copies (without popping) the RPN stack element at TOS to
the location pointed by tsp + n in the RPN stack. Here tsp refers to the stack location before the instruction is
executed. n can be negative.

SAMPLE RPN FILES

The comments in RPN Language are specified by //. The following examples illustrate common usage of the RPN
commands:

1) Log EAX and EBX registers:
push r, eax
push u, ebx
log 2 // logs two words from the
// top of stack
2) Log the bytes after exchanging the two bytes on the
stack:

push 0x02
push 0xff
xchg
log 2 // logs two bytes after exchanging
3) Operations on a local variable (the var = keyword
should be present in the RPN file header):

push 0xffffffff
pop lv, 0x0000 // pops the value on top of stack // into local variable
inc lv, 0x0000 // increments the local variable // at index 0x0000
dec lv, 0x0000 // decrements the local variable // at index 0x0000
push lv, 0x0000 // pushes the local variable on // the stack
log 1 // logs a dword from the stack
4) Arithmetic operations:

push 0x02
push 0x04
add
log 1 // logs the result of addition
// from top of stack
5) Logs the cpuid data after pushing it on to the stack :

push 0x0
push r, cpuid
log 4 // logs 4 dwords containing the
// cpuid
6) Example depicting the use of jumps and calls:

push 0xff
jnz down
exit
down: call proc1
exit
proc proc1
push 0x01
log 1
ret
endproc

COMPLETE EXAMPLES OF RPN

In the following examples offset and opcodes must be verified accordingly before running any of these on a Linux
system.

1) This rpn program puts a probe on an user application.

name = appln //appln is the module on which
//probe is put.
modtype = user //appln is a user application. major = 1 //major number.
offset = main //probe is on function main.
opcode = 0x55 //0x55 is the opcode present at offset. minor = 2 //minor number.
push u, cs //push user context code segment register. push u, ds //push user context data segment register. log 2 //log the two registers.
exit //exit this probe handler.
Whenever the application appln is executed the probe is
hit and the log shows the values of cs and ds.
2) This rpn file puts probe on kernel
name = vmlinux //kernel probe
modtype = kernel
major = 2 //major point
offset = do_fork //probe on do_fork
opcode = 0x55 //opcode is 0x55
minor = 1 //minor point
push pid //push pid
push task //push the address of the current
//task_struct
log 2 //log the pid and task_struct
exit
Whenever fork occurs, this probe logs the pid and the
address of the current task_struct.
2) Putting a probe on the network device driver and logging memory and register values.Traces the entry points to
the various driver functions and logs the data.
// The module 3c59x (Ethernet module) is loaded at boot
// time and for testing the probe, network services are
// restarted.
#define func1 vortex_open
name = "/lib/modules/2.2.12-20/net/3c59x.o" modtype = kmod
major = 0
offset = func1 // After preprocessing "func1" is //
replaced by "vortex_open"
opcode = 0x55
minor = 0
push r, eip // push the address of the instruction
// pointer
push wif // push the word found at the above address log 1 // log the word
push r, eax // also log the contents of the eax and ebx // registers
push r, ebx
log 2
offset = vortex_start_xmit opcode = 0x55
minor = 1
push 0x10
push r, eip
log mrf // logs 10 bytes from the address pushed.
exit
offset = vortex_close
opcode = 0x55
minor = 2
push 0x10
push r, eip // logs 10 bytes from the address pushed log mrf
#include "test.rpn" // After preprocessing the "test.rpn"
// file is copied in this RPN file.
exit
3) Monitor the number of calls to do_fork
name = vmlinux
modtype = kernel
major = 0
jmpmax = 15
vars = 3 // Shows that number of variables used in the // probe program is 3 (i.e. index is
// from 0 to 2)
offset = do_fork
opcode = 0x55
minor = 0
inc lv, 0x01 // increments the local variable
// at index 1
abort
4) Dump the system registers whenever swap_out function is called.
name = vmlinux
modtype = kernel
major = 0
ignore = 5
maxhits = 50
offset = swap_out
opcode = 0x55
minor = 1
push r, eax // dump the current registers
log 1
push r, ebx
log 1
push r, eip
log mrf // log memory at the flat address pushed
// previously
push u, eax // dump the user context registers
log 1
push u, ebx
log 1
5) Putting probe on an interrupt handler "do_general_protection" by keeping some maxhits and logging some information.
name = vmlinux
modtype = kernel
major = 0
vars = 1 // index of the variable is 0
offset = do_general_protection opcode = 0x55
minor = 0
maxhits = 10 // after getting hit for 10 times
// the probe will be disabled
push r, cr0 // pushes cr0 on to the stack
push r, cr2 // push cr2
push r, cr3 // push cr3
push r, cr4 // push cr4
log 4 // log all control registers.
exit
6) Putting probes on the entry and exit points of some of
the most frequently used functions in the kernel like
do_fork, kmalloc and do_page_fault. This example makes use of the group and type keywords in the probe program file header and groupdef and typedef keywords in the RPN file header. This probe program can be used to selectively
apply probes of same group and same type.
name = vmlinux
modtype = kernel
major = 1
groupdef = filesys memory process faults // Valid groups type = enter leave
// Valid types
offset = do_fork
opcode = 0x83 // Entry point of do_fork
minor = 0
group = process // probe point group type = enter // probe point type
push r, esp
push r, ss
log 2
exit
offset = do_fork + 1987
opcode = 0xc3 // Exit point of the do_fork function
minor = 1
group = process // probe point group type = leave // probe point type
push r, esp
push r, ss
log 2
exit
offset = kmalloc
opcode = 0x55 // First instruction in kmalloc().
minor = 2
group = memory // probe point group
type = enter // probe point type
maxhits = 100
push r, esp
push r, ss
log 2
exit
offset = kmalloc + 344
opcode = 0xc3 // Exit point of kmalloc().
minor = 4
group = memory // probe point group
type = leave
maxhits = 100
push r, esp
push r, ss
log 2
exit
offset = ext2_file_write
opcode = 0x83 // Entry point of ext2_file_write
minor = 5
group = filesys // probe point group type = enter // probe point type
maxhits = 100
push r, esp
push r, ss
log 2
exit
offset = ext2_file_write + 1583 opcode = 0xc3 // Entry point of ext2_file_write
minor = 6
group = filesys // probe point group type = leave // probe point type
maxhits = 100
push r, esp
push r, ss
log 2
exit
offset = do_page_fault
opcode = 0x83
// Entry point of do_page_fault
minor = 7
group = faults
// probe point group
type = enter
// probe point type
maxhits = 100
push r, esp
push r, ss
log 2
exit
offset = do_page_fault + 813 // Exit point of
do_page_fault
opcode = 0xc3
minor = 8
group = faults
// probe point group
type = leave
// probe point type
maxhits = 100
push r, esp
push r, ss
log 2
exit
The above RPN file can be built and applied in the following ways:
Let us call the RPN file example.rpn
dprobes --build-ppdf example.rpn -o example.ppdf Generates ppdf file example.ppdf.
dprobes --apply-ppdf example.ppdf Applies all the probes present in example.ppdf.
dprobes --apply-ppdf example.ppdf --group process --type enter
Applies probes belonging to the group process and
type enter.
dprobes --apply-ppdf example.ppdf --group = filesys Applies all probes belonging to the group filesys.
dprobes --apply-ppdf example.ppdf --type = leave Applies all probes belonging to type leave.
dprobes --apply-ppdf example.ppdf --group process memory --type leave
Applies all probes belonging to group process, type leave and group memory, type leave.
7) Illustration of watchpoint probes
a) This examples puts probe on a kernel data symbol and
watches it whenever a 4 byte write occurs to it.
name = vmlinux
modtype = kernel
address = nr_free_pages:nr_free_pages+3 watchpoint = w
maxhits = 100
push nr_free_pages
push dif
log 1
exit
b) This example shows how to watch a user space address.
name = vmlinux
modtype = kernel // note that modtype is kernel.
address = 0x0804040c:0x0804040f // User data address watchpoint = rw // readwrite type of watchpoint
push u, eip
log 1
exit

APPENDIX A

List of user and current registers for INTEL allowed/not
allowed for push and pop operations.
y -- allowed, n -- not allowed.
+------+----------+----------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+----------+----------+--------+-------+-------+
|0 | cs | y | y | n | n
|1 | ds | y | y | y | y
|2 | es | y | y | y | y
|3 | fs | y | y | y | y
|4 | gs | y | y | y | y
|5 | ss | y | y | n | n
|6 | eax | y | y | y | y
|7 | ebx | y | y | y | y
|8 | ecx | y | y | y | y
|9 | edx | y | y | y | y
|a | edi | y | y | y | y
|b | esi | y | y | y | y
|c | eflags | y | y | n | n
|d | eip | y | y | n | n
|e | esp | y | y | n | n
|f | ebp | y | y | y | y
|21 | tr | n | y | n | n
|21 | ldtr | n | y | n | n
|22 | gdtr | n | y | n | n
|23 | idtr | n | y | n | n
|24 | cr0 | n | y | n | n
|25 | cr1 | RESERVED
|26 | cr2 | n | y | n | n
|27 | cr3 | n | y | n | n
|28 | cr4 | n | y | n | n
|29 | cr5 | RESERVED
|2a | cr6 | RESERVED
|2b | cr7 | RESERVED
|2c | dr0 | n | y | n | n
|2d | dr1 | n | y | n | n
|2e | dr2 | n | y | n | n
|2f | dr3 | n | y | n | n
|30 | dr4 | RESERVED
|31 | dr5 | RESERVED
|32 | dr6 | n | y | n | n
|33 | dr7 | n | y | n | n
+------+----------+----------+--------+-------+-------+
+------+----------+----------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+----------+----------+--------+-------+-------+
|34 | tr0 | RESERVED
|35 | tr1 | RESERVED
|36 | tr2 | RESERVED
|37 | tr3 | RESERVED
|38 | tr4 | RESERVED
|39 | tr5 | RESERVED
|3a | tr6 | RESERVED
|3b | tr7 | RESERVED
|3c | cpuid | y | y | n | n
|3d | msr | y | y | n | n
|3e | fr0 | y | n | n | n
|3f | fr1 | y | n | n | n
|40 | fr2 | y | n | n | n
|41 | fr3 | y | n | n | n
|42 | fr4 | y | n | n | n
|43 | fr5 | y | n | n | n
|44 | fr6 | y | n | n | n
|45 | fr7 | y | n | n | n
|46 | fcw | y | n | n | n
|47 | fsw | y | n | n | n
|48 | ftw | y | n | n | n
|49 | fip | y | n | n | n
|4a | fcs | y | n | n | n
|4b | fdp | y | n | n | n
|4c | fds | y | n | n | n
|4d | xmm0 | y | n | n | n
|4e | xmm1 | y | n | n | n
|4f | xmm2 | y | n | n | n
|50 | xmm3 | y | n | n | n
|51 | xmm4 | y | n | n | n
|52 | xmm5 | y | n | n | n
|53 | xmm6 | y | n | n | n
|54 | xmm7 | y | n | n | n
|55 | mxcsr | y | n | n | n
+------+----------+----------+--------+-------+-------+
Floating Point Registers
fr0 - fr7 Floating point data registers
(Each register is 80bit wide,
hence occupies 2.5 rpn stack elements)
fcw Control register
fsw Status register
ftw Tag word register
fip Instruction pointer register
fcs Code segment register
fdp Data (operand) pointer register
fds Data segment register
Inserting probes on floating point instructions when the FPU is emulated is not allowed. If FPU is emulated, accessing FPU registers will give a default value of zero.
Streaming SIMD Extension (SSE) Registers
xmm0 - xmm7 SSE Floating Point Registers
each 128 bits wide, occupying 4 rpn
stack elements
mxcsr SSE Floating Point Control/Status Register
32 bits wide

APPENDIX B

List of user and current registers for S/390(32bit) and
zSeries(64bit) Lallowed/not allowed for push and pop operations.
y -- allowed, n -- not allowed.
+------+-----------+--------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+-----------+--------+--------+-------+-------+
|0x00 | PSWMASK | y | y | n | n
|0x01 | PSWADDR | y | y | n | n
+------+-----------+--------+--------+-------+-------+
|0x10 | GPR0 | y | y | y | y
|0x11 | GPR1 | y | y | y | y
|0x12 | GPR2 | y | y | y | y
|0x13 | GPR3 | y | y | y | y
|0x14 | GPR4 | y | y | y | y
|0x15 | GPR5 | y | y | y | y
|0x16 | GPR6 | y | y | y | y
|0x17 | GPR7 | y | y | y | y
|0x18 | GPR8 | y | y | y | y
|0x19 | GPR9 | y | y | y | y
|0x1a | GPR10 | y | y | y | y
|0x1b | GPR11 | y | y | y | y
|0x1c | GPR12 | y | y | y | y
|0x1d | GPR13 | y | y | y | y
|0x1e | GPR14 | y | y | y | y
|0x1f | GPR15 | y | y | y | y
+------+-----------+--------+--------+-------+-------+
+------+-----------+--------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+-----------+--------+--------+-------+-------+
|0x20 | ACR0 | y | y | n | n
|0x21 | ACR1 | y | y | n | n
|0x22 | ACR2 | y | y | n | n
|0x23 | ACR3 | y | y | n | n
|0x24 | ACR4 | y | y | n | n
|0x25 | ACR5 | y | y | n | n
|0x26 | ACR6 | y | y | n | n
|0x27 | ACR7 | y | y | n | n
|0x28 | ACR8 | y | y | n | n
|0x29 | ACR9 | y | y | n | n
|0x2a | ACR10 | y | y | n | n
|0x2b | ACR11 | y | y | n | n
|0x2c | ACR12 | y | y | n | n
|0x2d | ACR13 | y | y | n | n
|0x2e | ACR14 | y | y | n | n
|0x2f | ACR15 | y | y | n | n
+------+-----------+--------+--------+-------+-------+
+------+-----------+--------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+-----------+--------+--------+-------+-------+
|0x03 | FPC | y | n | n | n
+------+-----------+--------+--------+-------+-------+
|0x30 | FPR0 | y | n | n | n
|0x31 | FPR1 | y | n | n | n
|0x32 | FPR2 | y | n | n | n
|0x33 | FPR3 | y | n | n | n
|0x34 | FPR4 | y | n | n | n
|0x35 | FPR5 | y | n | n | n
|0x36 | FPR6 | y | n | n | n
|0x37 | FPR7 | y | n | n | n
|0x38 | FPR8 | y | n | n | n
|0x39 | FPR9 | y | n | n | n
|0x3a | FPR10 | y | n | n | n
|0x3b | FPR11 | y | n | n | n
|0x3c | FPR12 | y | n | n | n
|0x3d | FPR13 | y | n | n | n
|0x3e | FPR14 | y | n | n | n
|0x3f | FPR15 | y | n | n | n
+------+-----------+--------+--------+-------+-------+
Inserting probes on floating point instructions when the FPU is emulated is not allowed. If FPU is emulated, accessing FPU registers will give a default value of zero.
FPR0-15 Floating Point Registers each 64 bits wide, occupying 2 rpn stack elements
FPC Floating Point Control Register 32 bits wide
+------+-----------+--------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+-----------+--------+--------+-------+-------+
|0x40 | CR_0 | n | y | n | n |0x41 | CR_1 | n | y | n | n |0x42 | CR_2 | n | y | n | n |0x43 | CR_3 | n | y | n | n |0x44 | CR_4 | n | y | n | n |0x45 | CR_5 | n | y | n | n |0x46 | CR_6 | n | y | n | n |0x47 | CR_7 | n | y | n | n |0x48 | CR_8 | n | y | n | n |0x49 | CR_9 | n | y | n | n |0x4a | CR_10 | n | y | n | n |0x4b | CR_11 | n | y | n | n |0x4c | CR_12 | n | y | n | n |0x4d | CR_13 | n | y | n | n |0x4e | CR_14 | n | y | n | n |0x4f | CR_15 | n | y | n | n +------+-----------+--------+--------+-------+-------+

APPENDIX C

List of user and current registers for ppc and ppc64
allowed/not allowed for push and pop operations.
y -- allowed, n -- not allowed.
+------+-----------+--------+--------+-------+-------+
|Index | Register | push u | push r | pop u | pop r +------+-----------+--------+--------+-------+-------+
|0x01 | NIP | y | y | n | n
|0x02 | MSR | y | y | n | n
|0x03 | CTR | y | y | n | n
|0x04 | LNK | y | y | n | n
|0x05 | XER | y | y | n | n
|0x06 | CCR | y | y | n | n
|0x07 | MQ | y | y | n | n
|0x08 | DAR | y | y | n | n
|0x09 | DSISR | y | y | n | n
|0x0A | FPC | y | y | n | n
|0x0B | CPUID | y | y | n | n
|0x10 | R0 | y | y | y | y
|0x11 | R1 | y | y | y | y
|0x12 | R2 | y | y | y | y
| | ... |
|0x2f | R31 | y | y | y | y
|0x30 | FPR0 | y | n | n | n
|0x31 | FPR1 | y | n | n | n
|0x32 | FPR2 | y | n | n | n
| | ... |
|0x4f | FPR31 | y | n | n | n
+------+-----------+--------+--------+-------+-------+

APPENDIX D

Some methods to get the opcode present at any offset.

For any user executable, objdump with -D option can be used to obtain the complete disassembly of the executable.
Disassembled code can then be used to obtain the opcode.

For example, the disassembled section of the function main
of a user application looks like this:

080483d0 <main>:
80483d0: 55 pushl %ebp
80483d1: 89 e5 movl
%esp,%ebp
80483d3: 83 ec 0c subl
$0xc,%esp
.
.
.
If probe has to be put on main then opcode is 0x55.
For S/390 code the method is the same, but the object code
looks a bit different:
004007ac <main>:
4007ac: 90 af f0 28 stm %r10,%r15,40(%r15)
4007b0: a7 d5 00 0a bras %r13,4007c4
<main+0x18>
.
.
.
If probe has to be put on main then the opcode for the probe definition is 0x90af (S/390 has to use two byte opcodes in the probe point definition).
The above method can also be used for kernel probes by
disassembling and obtaining the opcode from vmlinux. Application debuggers or Kernel debuggers can also be used for the purpose.

AUTHOR

IBM Corporation

VERSION

DProbes version: 3.6.4
man pages last modified on: 27 May 2002

LICENSE

Dynamic Probes is licensed under GNU General Public
License version 2 or later.

Copyright (c) International Business Machines Corp., 2000
Copyright © 2010-2025 Platon Technologies, s.r.o.           Home | Man pages | tLDP | Documents | Utilities | About
Design by styleshout