Solaris mdb使用简介 收藏
13.2. MDB Command SyntaxThe MDB debugger lets us interact with the target program and the memory image of the target. The syntax is an enhanced form of that used with debuggers like adb, in which basic form is expressed as value and a command. [value] [,count ] command The language syntax is designed around the concept of computing the value of an expression (typically a memory address in the target), and applying a command to that expression. A command in MDB can be of several forms. It can be a macro file, a metacharacter, or a dcmd pipeline. A simple command is a metacharacter or dcmd followed by a sequence of zero or more blank-separated words. The words are typically passed as arguments. Each command returns an exit status that indicates it succeeded, failed, or was invoked with invalid arguments. For example, if we wanted to display the contents of the word at address fec4b8d0, we could use the / metacharacter with the word X as a format specifier, and optionally a count specifying the number of iterations. > fec4b8d0 /X MDB retains the notion of dot (.) as the current address or value, retained from the last successful command. A command with no supplied expression uses the value of dot for its argument. > /X A pipeline is a sequence of one or more simple commands separated by |. Unlike the shell, dcmds in MDB pipelines are not executed as separate processes. After the pipeline has been parsed, each dcmd is invoked in order from left to right. The full definition of a command involving pipelines is as follows. [expr] [,count ] pipeline [words...] Each dcmd's output is processed and stored as described in "dcmd Pipelines" in Section 13.2.8. After the left-hand dcmd is complete, its processed output is used as input for the next dcmd in the pipeline. If any dcmd does not return a successful exit status, the pipeline is aborted. For reference, Table 13.1 lists the full set of expression and pipeline combinations that form commands.
13.2.1. ExpressionsArithmetic expansion is performed when an MDB command is preceded by an optional expression representing a numerical argument for a dcmd. A list of common expressions is summarized in Tables 13.2, 13.3, and 13.4.
An example of a simple expression is adding an integer to an address. > d7c662e0+0t8/X 13.2.2. SymbolsMDB can reference memory or objects according to the value of a symbol of the target. A symbol is the name of either a function or a global variable in the target. For example, you compute the address of the kernel's global variable lotsfree by entering it as an expression, and display it by using the= metacharacter. You display the value of the lotsfree symbol by using the / metacharacter. > lotsfree=X Symbol names can be resolved from kernel and userland process targets. In the kernel, the resolution of the symbol names can optionally be defined with a scope by specifying the module or object file name. In a process, symbols' scope can be defined by library or object file names. They take the form shown in Table 13.5.
The target typically searches the primary executable's symbol tables first, then one or more of the other symbol tables. Notice that ELF symbol tables contain only entries for external, global, and static symbols; automatic symbols do not appear in the symbol tables processed by MDB. Additionally, MDB provides a private user-defined symbol table that is searched before any of the target symbol tables are searched. The private symbol table is initially empty and can be manipulated with the ::nmadd and ::nmdel dcmds. The ::nm -P option displays the contents of the private symbol table. The private symbol table allows the user to create symbol definitions for program functions or data that were either missing from the original program or stripped out. > ::nm These definitions are then used whenever MDB converts a symbolic name to an address, or an address to the nearest symbol. Because targets contain multiple symbol tables and each symbol table can include symbols from multiple object files, different symbols with the same name can exist. MDB uses the backquote "`" character as a symbol-name scoping operator to allow the programmer to obtain the value of the desired symbol in this situation. 13.2.3. Formatting MetacharactersThe /, /, ?, and = metacharacters denote the special output formatting dcmds. Each of these dcmds accepts an argument list consisting of one or more format characters, repeat counts, or quoted strings. A format character is one of the ASCII characters shown in Table 13.6.
13.2.4. Formatting CharactersFormat characters read or write and format data from the target. They are combined with the formatting metacharacters to read, write, or search memory. For example, if we want to display or set the value of a memory location, we could represent that location by its hexadecimal address or by its symbol name. Typically, we use a metacharacter with a format or a dcmd to indicate what we want MDB to do with the memory at the indicated address. In the following example, we display the address of the kernel's lotsfree symbol. We use the = metacharacter to display the absolute value of the symbol, lotsfree and the X format to display the address in 32-bit hexadecimal notation. > lotsfree=X In a more common example, we can use the / metacharacter to format for display the value at the address of the lotsfree symbol. > lotsfree/D Optionally, a repeat count can be supplied with a format. A repeat count is a positive integer preceding the format character and is always interpreted in base 10 (decimal). A repeat count can also be specified as an expression enclosed in square brackets preceded by a dollar sign ($[ ]). A string argument must be enclosed in double-quotes (" "). No blanks are necessary between format arguments. > lotsfree/4D If MDB is started in writable (-w) mode, then write formats are enabled. Note that this should be considered MDB's dangerous mode, especially if operating on live kernels or applications. For example, if we wanted to rewrite the value indicated by lotsfree to a new value, we could use the W write format with a valid MDB value or arithmetic expression as shown in the summary at the start of this section. For example, the W format writes the 32-bit value to the given address. In this example, we use an integer value, represented by the 0t arithmetic expression prefix. > lotsfree/W 0t5000 A complete list of format strings can be found with the ::formats dcmd. > ::formats A summary of the common formatting characters and the required metacharacters is shown in Table 13.7 through Table 13.9.
13.2.5. dcmdsThe metacharacters we explored in the previous section are actually forms of dcmds. The more general form of a dcmd is ::name, where name is the command name, as summarized by the following: ::{module`}d A list of dcmds can be obtained with ::dcmds. Alternatively, the ::dmods command displays information about both dcmds and walkers, conveniently grouped per MDB module. > ::dmods -l Help on individual dcmds is available with the help dcmd. Yes, almost everything in MDB is implemented as a dcmd! > ::help ps For example, we can optionally use ::ps as a simple dcmd with no arguments. > ::ps Optionally, we could use the same ::ps dcmd with an address supplied in hexadecimal. > ffffffff87be90b8::ps 13.2.6. WalkersA walker is used to traverse a connect set of data. Walkers are a type of plugin that is coded to iterate over the specified type of data. In addition to the ::dcmds dcmd, the ::walkers dcmd lists walkers. > ::walkers For example, the ::proc walker could be used to traverse set of process structures (proc_ts). Many walkers also have a default data item to walk if none is specified. > ::walk proc There are walkers to traverse common generic data structure indexes. For example, simple linked lists can be traversed with the ::list walker, and AVL trees with the ::avl walker. > ffffffff9a647ae0::walk avl 13.2.7. MacrosMDB provides a compatibility mode that can interpret macros built for adb. A macro file is a text file containing a set of commands to execute. Macro files typically automate the process of displaying a simple data structure. These older macros can therefore be used with either tool. The development of macros is discouraged, since they are difficult to construct and maintain. Following is an example of using a macro to display a data structure. > d8126310$<ce 13.2.8. PipelinesWalkers and dcmds can build on each other, combining to do more powerful things by placement into an mdb "pipeline." The purpose of a pipeline is to pass a list of values, typically virtual addresses, from one dcmd or walker to another. Pipeline stages might map a pointer from one type of data structure to a pointer to a corresponding data structure, sort a list of addresses, or select the addresses of structures with certain properties. MDB executes each dcmd in the pipeline in order from left to right. The leftmost dcmd executes with the current value of dot or with the value specified by an explicit expression at the start of the command. When a | operator is encountered, MDB creates a pipe (a shared buffer) between the output of the dcmd to its left and the MDB parser, and an empty list of values. To give you a taste of the power of pipelines, here's an example, running against the live kernel. The ::pgrep dcmd allows you to find all processes matching a pattern, the thread walker walks all of the threads in a process, and the ::findstack dcmd gets a stack trace for a given thread. Connecting them into a pipeline, you can yield the stack traces of all sshd threads on the system (note that the middle one is swapped out). MDB pipelines are quite similar to standard UNIX pipelines and afford debugger users a similar level of power and flexibility. > ::pgrep sshd The full list of built-in dcmds can be obtained with the ::dmods dcmd. > ::dmods -l mdb 13.2.9. Piping to UNIX CommandsMDB can pipe output to UNIX commands with the ! pipe. A common task is to use grep to filter output from a dcmd. We've shown the output from ::ps for illustration; actually, a handy ::pgrep command handles this common task. > ::ps !grep inet 13.2.10. Obtaining Symbolic Type InformationThe MDB environment exploits the Compact Type Format (CTF) information in debugging targets. This provides symbolic type information for data structures in the target; such information can then be used within the debugging environment. Several dcmds consume CTF information, most notably ::print. The ::print dcmd displays a target data type in native C representation. The following example shows ::print in action. /* process ID info */ The ::print dcmd is most useful to print data structures in their typed format. For example, using a pipeline we can look up the address of the p_pidp member of the supplied proc_t structure and print its structure's contents. > ::pgrep inet The ::print command also understands how to traverse more complex data structures. For example, here we traverse an element of an array. > d7c662e0::print proc_t p_user.u_auxv[9] Several other dcmds, listed below, use the CTF information. Starting with Solaris 9, the kernel is compiled with CTF information, making type information available by default. Starting with Solaris 10, CTF information is also available in userland, and by default some of the core system libraries contain CTF. The CTF-related commands are summarized in Table 13.10.
13.2.11. VariablesA variable is a variable name, a corresponding integer value, and a set of attributes. A variable name is a sequence of letters, digits, underscores, or periods. A variable can be assigned a value with > dcmd and read with < dcmd. Additionally, the variable can be the ::typesetdcmd, and its attributes can be manipulated with the ::typeset dcmd. Each variable's value is represented as a 64-bit unsigned integer. A variable can have one or more of the following attributes:
The following examples shows assigning and referencing a variable. > 0t27>myvar The CPU's registers are also exported as variables. > ::vars Commands for working with variables are summarized in Table 13.11.
13.2.12. Walkers, Variables, and Expressions CombinedVariables can be combined with arithmetic expressions and evaluated to construct more complex pipelines, in which data is manipulated between stages. In a simple example, we might want to iterate only over processes that have a uid of zero. We can easily iterate over the processes by using a pipeline consisting of a walker and type information, which prints the cr_uids for every process. > ::walk proc | ::print proc_t p_cred->cr_uid Adding an expression allows us to select only those that match a particular condition. The ::walk dcmd takes an optional variable name, in which to place the value of the walk. In this example, the walker sets the value of myvar and also pipes the output of the same addresses into ::print, which extracts the value of proc_t->p_cred->cr_uid. The ::eval dcmd prints the variable myvar only when the expression is true; in this case when the result of the previous dcmd (the printed value of cr_uid) is equal to 1. The statement given to ::eval to execute retrieves the value of the variable myvar and formats it with the K format (uint_ptr_t). > ::walk proc myvar |::print proc_t p_cred->cr_uid |::grep .==1 |::eval <myvar=K |
13.3. Working with Debugging TargetsMDB can control and interact with live mdb processes or kmdb kernel targets. Typical debugging operations include starting, stopping, and stepping the target. We discuss more about controlling kmdb targets in Chapter 14. The common commands for controlling targets are summarized in Table 13.12.
13.3.1. Displaying StacksWe can print a stack of the current address with the $c command or with $C, which also prints the stack frame address for each stack level. > $c 13.3.2. Displaying RegistersWe can print a stack of the current address with the $c command or with $C, which also prints the stack frame address for each stack level. > ::regs (or $r) 13.3.3. Disassembling the TargetWe can dissasemble instructions in the target with the ::dis dcmd. > atomic_add_32+8::dis Note that in this example combined with the registers shown in Section 13.3.2, the contents of %eax from $r is zero, causing the movl instruction to trap with a NULL pointer reference at atomic_add_32+4. 13.3.4. Setting BreakpointsWe can set breakpoints in MDB by using :b. Typically, we pass a symbol name to :b (the name of the function of interest). We can start the target program and then set a breakpoint for the printf function. > printf:b In this example, we stopped at the first symbol matching "printf", which is actually in the procedure linkage table (PLT) (see the Linker and Libraries manual for a description of how dynamic linking works in Solaris). To match the printf we likely wanted, we can increase the scope of the symbol lookup. The :c command continues execution until the next breakpoint or until the program finishes. > libc`printf:b |