Debugger Module

The debugger module provides a set of dcmds and walkers that can be loaded under mdb(1). This module can be used to inspect various internal data structures of the runtime linker. Much of the debugging information requires familiarity with the internals of the runtime linker. These internals can change from release to release. However, some elements of these data structures reveal the basic components of a dynamically linked process and can aid general debugging.

The following examples show some simple scenarios of using mdb(1) with the debugger module.

$ cat main.c
#include    <dlfcn.h>

int main()
{
        void *handle;
        void (*fptr)();

        if ((handle = dlopen("foo.so.1", RTLD_LAZY)) == NULL)
                return (1);

        if ((fptr = (void (*)())dlsym(handle, "foo")) == NULL)
                return (1);

        (*fptr)();
        return (0);
}
$ cc -o main main.c -R.

If mdb(1) has not automatically loaded the debugger module, ld.so, explicitly do so. The facilities of the debugger module can then be inspected.

$ mdb main
> ::load ld.so
> ::dmods -l ld.so

ld.so
-----------------------------------------------------------------
  dcmd Bind                 - Display a Binding descriptor
  dcmd Callers              - Display Rt_map CALLERS binding descriptors
  dcmd Depends              - Display Rt_map DEPENDS binding descriptors
  dcmd ElfDyn               - Display Elf_Dyn entry
  dcmd ElfEhdr              - Display Elf_Ehdr entry
  dcmd ElfPhdr              - Display Elf_Phdr entry
  dcmd Groups               - Display Rt_map GROUPS group handles
  dcmd GrpDesc              - Display a Group Descriptor
  dcmd GrpHdl               - Display a Group Handle
  dcmd Handles              - Display Rt_map HANDLES group descriptors
  ....
> ::bp main
> :r

Each dynamic object within a process is expressed as a link-map, Rt_map, which is maintained on a link-map list. All link-maps for the process can be displayed with Rt_maps.

> ::Rt_maps
Link-map lists (dynlm_list): 0xff1e5258 Alist[used 2: total 2]
----------------------------------------------
  Lm_list: 0xff1e00c4  (LM_ID_BASE)
  ----------------------------------------------
    lmco        rtmap       ADDR()     NAME()
    ----------------------------------------------
    [0x10]      0xff1e4cc0 0x00010000 main
    [0x10]      0xff1e55f8 0xfe8b0000 /lib/libc.so.1
  ----------------------------------------------
  Lm_list: 0xff1e0178  (LM_ID_LDSO)
  ----------------------------------------------
    [0x10]      0xff1e47b0 0xff190000 /lib/ld.so.1

An individual link-map can be displayed with Rt_map.

> 0xff3f9040::Rt_map
Rt_map located at: 0xff3f9040
----------------------------------------------
     NAME: main
 PATHNAME: /export/home/user/main
     ADDR: 0x00010000         DYN: 0x00020b4c
     NEXT: 0xff1e55f8        PREV: 0x00000000
     LAZY:          0    TLSMODID:          0
     INIT: 0x00000000        FINI: 0x00000000
   GROUPS: 0x00000000     HANDLES: 0x00000000
  DEPENDS: 0xff1e5c90     CALLERS: 0x00000000
  DYNINFO: 0xff1e4e58     REFNAME: 
    RLIST: 0xff1e5338       RPATH: .
     LIST: 0xff1e00c4 [ld.so.1`lml_main]
    FLAGS: 0x10421605
           [ MAIN,RELOCATED,ANALYZED,INITDONE,FIXED,
             MODESET,INITCALLED ,INITCOLLECT ]
   FLAGS1: 0x00400682
           [ ALTCAPCHK,DTFLAGS,NOINITFINI,USED,CRTFINI ]
     MODE: 0x00001901
           [ LAZY,GLOBAL,WORLD,NODELETE ]

The object's .dynamic section can be displayed with the ElfDyn dcmd. The following example shows the first 4 entries.

> 0x00020b4c,4::ElfDyn
Elf_Dyn located at: 0x20b4c
    0x20b4c  NEEDED       0x00000150
Elf_Dyn located at: 0x20b54
    0x20b54  INIT         0x00010aa8
Elf_Dyn located at: 0x20b5c
    0x20b5c  FINI         0x00010ab4
Elf_Dyn located at: 0x20b64
    0x20b64  RUNPATH      0x00000170

mdb(1) is also very useful for setting deferred break points. In this example, a break point on the function foo() might be useful. However, until the dlopen(3C) of foo.so.1 occurs, this symbol isn't known to the debugger. A deferred break point instructs the debugger to set a real breakpoint when the dynamic object is loaded.

> ::bp foo.so.1`foo
> :c
> mdb: You've got symbols!
> mdb: stop at foo.so.1`foo
mdb: target stopped at:
foo.so.1`foo:   save      %sp, -0x60, %sp
mdb: You've got symbols!

At this point, new objects have been loaded.

> *ld.so`lml_main::Rt_maps
lmco    rtmap       ADDR()     NAME()
----------------------------------------------
[0x10]  0xff1e4cc0 0x00010000 main
[0x10]  0xff1e55f8 0xfe8b0000 /lib/libc.so.1
[0x10]  0xff1d8110 0xff160000 ./foo.so.1
[0x10]  0xff1d8a58 0xff140000 ./bar.so.1

The link-map for foo.so.1 shows the handle returned by dlopen(3C). You can expand this structure using Handles.

> 0xff1d8110::Handles -v
HANDLES for ./foo.so.1
----------------------------------------------
  HANDLE: 0xff1d8570 APlist[used 1: total 20]
    ----------------------------------------------
    Group Handle located at: 0xff1d8548
    ----------------------------------------------
        owner:               ./foo.so.1
        flags: 0x00000101    [ PUBLIC,INITIAL ]
       refcnt:          1    depends: 0xff1d8660 Alist[used 3: total 20]
        ----------------------------------------------
        Group Descriptor located at: 0xff1d8670
           depend: 0xff1d8110    ./foo.so.1
            flags: 0x00000007    [ DLSYMAVAIL,RELOCAVAIL,ADDEPS ]
        ----------------------------------------------
        Group Descriptor located at: 0xff1d8678
           depend: 0xff1e4cc0    main
            flags: 0x00000008    [ PARENT ]
        ----------------------------------------------
        Group Descriptor located at: 0xff1d8680
           depend: 0xff1d8a58    ./bar.so.1
            flags: 0x00000007    [ DLSYMAVAIL,RELOCAVAIL,ADDEPS ]

The dependencies of a handle are a list of link-maps that represent the objects of the handle that can satisfy a dlsym(3C) request. In this case, the dependencies are foo.so.1 and bar.so.1.

Note:

The previous examples provide a basic guide to the debugger module facilities, but the exact commands, usage, and output can change from release to release. Refer to the usage and help information from mdb(1) for the exact facilities that are available on your system.