Oracle Solaris Modular Debugger Guide

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 3–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 3–2 Data Looks Wrong: The 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 = 0
    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