Go to main content

Oracle® Solaris Modular Debugger Guide

Exit Print View

Updated: February 2021

MDB Symbol Name Resolution

As explained in MDB Syntax, a symbol identifier in an expression evaluates to the value of that symbol. The value typically denotes the virtual address of the storage associated with the symbol in the target's virtual address space.

Tip  - In the case of a naming conflict between a symbol and a hexadecimal integer value, MDB attempts to evaluate an ambiguous token as a symbol first, before evaluating it as an integer value. For example, the token f can refer to the decimal integer value 15 specified in hexadecimal (the default base), or f can refer to a global variable in the symbol table of the target. To avoid ambiguity, use an explicit 0x or 0X prefix to specify an integer value.

MDB Symbol Tables

    A target can support multiple symbol tables. The following examples are some of the symbol tables that a target can support:

  • Primary executable symbol table

  • Primary dynamic symbol table

  • Runtime link-editor symbol table

  • Standard and dynamic symbol tables for each of a number of load objects (such as shared libraries in a user process, or kernel modules in the Oracle Solaris kernel)

The target typically searches the symbol tables of the primary executable first, then one or more of the other symbol tables. Note 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 prior to any of the target symbol tables. The private symbol table is initially empty. Use the ::nmadd and ::nmdel dcmds to manipulate the private symbol table.

Use the ::nm –P dcmd to display the contents of the private symbol table. The private symbol table enables you to create symbol definitions for program functions or data that were either missing from the original program or stripped out. These definitions are then used whenever MDB converts a symbolic name to an address, or converts an address to the nearest symbol.

MDB Symbol Name Scoping

A target can support multiple symbol tables, and each symbol table can include symbols from multiple object files. Therefore, different symbols with the same name can exist. When two different symbols have the same name, use the symbol-name scoping operator to obtain the value of the desired symbol. The symbol-name scoping operator is the back quotation mark (`).

Use one of the following three forms to specify the scope used to resolve a symbol name:


The object identifier refers to the name of a load object. The file identifier refers to the base name of a source file that has a symbol of type STT_FILE in the specified object's symbol table. Interpretation of the object identifier depends on the target type. A target can be a process target or a kernel target.

MDB Scoping Within User-Level Applications and Shared Libraries

The MDB process target expects object to specify the name of the executable or of a loaded shared library.

MDB Object Identifier

    The object identifier can take any of the following four forms:

  • Exact match (that is, a full path name): /usr/lib/libc.so.1

  • Exact basename match: libc.so.1

  • Initial basename match up to a period or dot character (.) suffix: libc.so or libc

  • Literal string a.out, which is accepted as an alias for the executable

MDB Link Map Identifier

The process target also accepts any of the four forms described above preceded by an optional link-map id (lmid). The lmid prefix is specified by an initial LM followed by the link-map id in hexadecimal followed by an additional back quotation mark (`). For example, the following symbol name evaluates to the value of the _init symbol in the libc.so.1 library that is loaded on link-map 0 (LM_ID_BASE):


The link-map specifier might be necessary to resolve symbol naming conflicts if the same library is loaded on more than one link map. For more information about link maps, refer to the Oracle Solaris 11.4 Linkers and Libraries Guide and the dlopen(3C) man page. Link-map identifiers are displayed when symbols are printed according to the setting of the showlmid option, as described in the mdb(1) man page.

MDB Scoping Within the Kernel

The MDB kernel target expects object to specify the base name of a loaded kernel module. For example, the following symbol name evaluates to the value of the _init symbol in the specfs kernel module:


Kernel Debug Information

MDB uses CTF debug information to read and display structures correctly. CTF (Compact C Type Format) is a reduced form of debug information similar to DWARF and stab. CTF describes types (structures, unions, and typedefs, for example) and function prototypes. Oracle Solaris kernel binaries embed CTF data as an ELF section (.SUNW_ctf).

As much as possible, CTF data is stored in one place to minimize duplication of common types. Other occurrences of each type reference the one unique definition. When a kernel update is released, existing CTF structure definitions must be preserved because some kernel modules might not be updated and might still be using the old definitions. When a kernel update is released but not all modules are updated, the CTF definitions are held in the module in which they are defined. When you use MDB to examine a crash dump, you might see a message that the structure you want to examine does not exist, or you might see an indication that the structure has changed. If the structure definition has changed, the data might look corrupt, for example. If you encounter either of these conditions, use the scoping operator to specify the module where the structure is defined.

Using the Scoping Operator With a Kernel Module

The genunix module contains many common types. The ip module also contains types that are used by many kernel modules but that are not found in genunix. Therefore, you might need to use scoping with the ip module more often than with other kernel modules.

Notice the use of the scoping operator with the ip module in the second versions of the following examples.

Example 1  Failed to Find Member of Structure
> ::print -at conn_t conn_udp mdb: failed to find member conn_udp of conn_t: no such member of structure or union
> ::print -at ip`conn_t conn_udp
30 struct udp_s *conn_udp 
Example 2  Data Looks Wrong: Structure Definition Might Have Changed
> 0x300b038cc38::print queue_t q_ptr  | print -at conn_t
3021e581780 kmutex_t conn_lock = {
3021e581780 void *[1] _opaque = [ 0 ]
3021e581788 uint32_t conn_ref = 0x3
3021e58178c uint_t conn_state_flags = 0
3021e581790 ire_t *conn_ire_cache = 0x600b102f598
3021e581798 uint32_t conn_flags = 0x49000001
3021e58179c unsigned conn_on_sqp = 0
3021e58179c unsigned conn_dontroute = 0
3021e58179c unsigned conn_loopback = 0
3021e58179c unsigned conn_broadcast = 0
3021e58179c unsigned conn_reuseaddr = 1
3021e58179c unsigned conn_multicast_loop = 0
3021e58179c unsigned conn_multi_router = 0
3021e58179c unsigned conn_draining = 0
3021e58179d unsigned conn_did_putbq = 0
3021e58179d unsigned conn_unspec_src = 0
3021e58179d unsigned conn_policy_cached = 0
3021e58179d unsigned conn_in_enforce_policy = 0
3021e58179d unsigned conn_out_enforce_policy = 0
3021e58179d unsigned conn_af_isv6 = 0
3021e58179d unsigned conn_pkt_isv6 = 0
3021e58179d unsigned conn_ipv6_recvpktinfo = 0
3021e58179e unsigned conn_ipv6_recvhoplimit = 0
3021e58179e unsigned conn_ipv6_recvhopopts = 0
3021e58179e unsigned conn_ipv6_recvdstopts = 0
3021e58179e unsigned conn_ipv6_recvrthdr = 0
3021e58179e unsigned conn_ipv6_recvrtdstopts = 0
3021e58179e unsigned conn_ipv6_v6only = 0
3021e58179e unsigned conn_ipv6_recvtclass = 0
3021e58179e unsigned conn_ipv6_recvpathmtu = 0
3021e58179f unsigned conn_pathmtu_valid = 0
3021e58179f unsigned conn_ipv6_dontfrag = 0
3021e58179f unsigned conn_fully_bound = 1
3021e58179f unsigned conn_recvif = 0
3021e58179f unsigned conn_recvslla = 0
3021e58179f unsigned conn_mdt_ok 
3021e58179f unsigned pad_to_bit_31 = 0
3021e5817a0 tcp_t *conn_tcp = 0
3021e5817a8 squeue_t *conn_sqp = 0x3021e581980
3021e5817b0 edesc_rpf conn_recv = 0
3021e5817b8 void *conn_pad1 = 0x600b082ba40      // Should have 0's in this field. Data looks
3021e5817c0 ill_t *conn_xmit_if_ill = tcp_input  // wrong starting from the conn_pad1 field.
3021e5817c8 ill_t *conn_nofailover_ill = 0
3021e5817d0 ipsec_latch_t *conn_latch = 0
3021e5817d8 ill_t *conn_outgoing_ill = 0
3021e5817e0 edesc_spf conn_send = 0
3021e5817e8 queue_t *conn_rq = 0
3021e5817f0 queue_t *conn_wq = ip_output
3021e5817f8 dev_t conn_dev = 0

> 0x300b038cc38::print queue_t q_ptr | print -at ip`conn_t
3021e5817c8 void *conn_pad1 = 0   // Now the data looks correct from here on.
3021e5817d0 ill_t *conn_xmit_if_ill = 0
3021e5817d8 ill_t *conn_nofailover_ill = 0
3021e5817e0 ipsec_latch_t *conn_latch = 0
3021e5817e8 ill_t *conn_outgoing_ill = 0
3021e5817f0 edesc_spf conn_send = ip_output
3021e5817f8 queue_t *conn_rq = 0
3021e581800 queue_t *conn_wq = 0
3021e581808 dev_t conn_dev = 0x1d2b