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 frommdb
(1) for the exact facilities
that are available on your system.