2.7 External Symbols and Types

DTrace instrumentation executes inside the Oracle Linux operating system kernel. So, in addition to accessing special DTrace variables and probe arguments, you can also access kernel data structures, symbols, and types. These capabilities enable advanced DTrace users, administrators, service personnel, and driver developers to examine low-level behavior of the operating system kernel and device drivers. The reading list at the start of this guide includes books that can help you learn more about Oracle Linux operating system internals.

D uses the back quote character (`) as a special scoping operator for accessing symbols that are defined in the operating system and not in your D program. For example, the Oracle Linux kernel contains a C declaration of a system variable named max_pfn. This variable is declared in C in the kernel source code as follows:

unsigned long max_pfn

To trace the value of this variable in a D program, you can write the following D statement:

trace(`max_pfn);

DTrace associates each kernel symbol with the type that is used for the symbol in the corresponding operating system C code, which provides easy source-based access to the native operating system data structures.

To use external operating system variables, you will need access to the corresponding operating system source code.

Kernel symbol names are kept in a separate namespace from D variable and function identifiers, so you do not need to be concerned about these names conflicting with your D variables. When you prefix a variable with a back quote, the D compiler searches the known kernel symbols and uses the list of loaded modules to find a matching variable definition. Because the Oracle Linux kernel supports dynamically loaded modules with separate symbol namespaces, the same variable name might be used more than once in the active operating system kernel. You can resolve these name conflicts by specifying the name of the kernel module that contains the variable to be accessed prior to the back quote in the symbol name. For example, you would refer to the address of the _bar function that is provided by a kernel module named foo as follows:

foo`_bar

You can apply any of the D operators to external variables, except for those that modify values, subject to the usual rules for operand types. When required, the D compiler loads the variable names that correspond to active kernel modules, so you do not need to declare these variables. You may not apply any operator to an external variable that modifies its value, such as = or +=. For safety reasons, DTrace prevents you from damaging or corrupting the state of the software that you are observing.

When you access external variables from a D program, you are accessing the internal implementation details of another program, such as the operating system kernel or its device drivers. These implementation details do not form a stable interface upon which you can rely. Any D programs you write that depend on these details might cease to work when you next upgrade the corresponding piece of software. For this reason, external variables are typically used to debug performance or functionality problems by using DTrace. To learn more about the stability of your D programs, see Chapter 16, DTrace Stability Features.

You have now completed a whirlwind tour of DTrace and have learned many of the basic DTrace building blocks that are necessary to build larger and more complex D programs. The remaining portions of this chapter describe the complete set of rules for D and demonstrate how DTrace can make complex performance measurements and functional analysis of the system easy. Later, you will learn how to use DTrace to connect user application behavior to system behavior, which provides you with the capability to analyze your entire software stack.