The debugger module provides a set of dcmds and walkers that can be loaded under mdb(1) and used to inspect various internal data structures of the runtime linker. Much of this information requires familiarity with the internals of the runtime linker, and may change from one release to another. However, some elements of these data structures reveal the basic components of a dynamically linked process and may aid general debugging.
The following example provides some scenarios of how mdb(1) and this debugger module may be used.
$ cat main.c #include <dlfnc.h> 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. -ldl |
If mdb(1) has not automatically loaded the debugger module, ld.so, explicitly do so. The capabilities of the debugger module can then be inspected.
$ mdb main > ::load ld.so > ::dmods -l ld.so ld.so ----------------------------------------------------------------- dcmd Dl_handle - display Dl_handle structure dcmd Dyn - display Dynamic entry dcmd List - display entries in a List dcmd ListRtmap - display a List of Rt_Map's dcmd Lm_list - display ld.so.1 Lm_list structure dcmd Permit - display Permit structure dcmd Rt_map - display ld.so.1 Rt_map structure dcmd Rt_maps - display list of Rt_map structures walk List - walk List structure walk Rt_maps - walk list of Rt_map structures > ::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 Objects on linkmap: <base> rtmap* ADDR NAME --------------------------------------------- 0xff3b0030 0x00010000 main 0xff3b0434 0xff3a0000 /usr/lib/libdl.so.1 0xff3b0734 0xff280000 /usr/lib/libc.so.1 Objects on linkmap: <ld.so.1> rtmap* ADDR NAME --------------------------------------------- 0xff3f7c68 0xff3c0000 /usr/lib/ld.so.1 |
An individual link-map can be displayed with Rt_map.
> 0xff3b0030::Rt_map Rt_map located at: 0xff3b0030 NAME: main ADDR: 0x00010000 DYN: 0x000209d8 NEXT: 0xff3b0434 PREV: 0x00000000 ..... LIST: 0xff3f60cc [ld.so.1`lml_main] |
The object's .dynamic section can be displayed with the Dyn dcmd. The following example shows the first 4 entries.
> 0x000209d8,4::Dyn Dyn located at: 209d8 0x209d8 NEEDED 0x000001d7 Dyn located at: 209e0 0x209e0 NEEDED 0x000001e2 Dyn located at: 209e8 0x209e8 INIT 0x00010870 Dyn located at: 209f0 0x209f0 FINI 0x000108c0 |
mdb(1) is also very useful for setting deferred break points. In this example it might be useful to put a break point on the function foo(). However, until the dlopen(3DL) of foo.so.1 occurs, this symbol isn't known to the debugger. Setting a deferred break point instructs the debugger to set a real breakpoint when the dynamic object is loaded.
> ::bp foo.so.1`foo > :r > mdb: You've got symbols! > mdb: stop at foo.so.1`foo mdb: target stopped at: foo.so.1`foo: save %sp, -0x68, %sp |
At this point, new objects have been loaded:
> *ld.so`lml_main::Rt_maps rtmap* ADDR NAME --------------------------------------------- 0xff3b0030 0x00010000 main 0xff3b0434 0xff3a0000 /usr/lib/libdl.so.1 0xff3b0734 0xff280000 /usr/lib/libc.so.1 0xff3b0c1c 0xff370000 ./foo.so.1 0xff3b1030 0xff350000 ./bar.so.1 |
The link-map for foo.so.1 shows the handle returned by dlopen(3DL). You can expand this structure using Dl_handle.
> 0xff3b0c1c::Rt_map Rt_map located at: 0xff3b0c1c NAME: ./foo.so.1 ADDR: 0xff370000 DYN: 0xff3805c8 NEXT: 0xff3b1030 PREV: 0xff3b0734 FCT: 0xff3f6080 ....... PERMIT: 0xff3b0f94 HANDLE: 0xff3b0f38 > 0xff3b0f38::Dl_handle Dl_handle located at: ff3b0f38 permit: 0xff3b0f7c usercnt: 1 permcnt: 2 depends: 0xff3b0f44 [0xff3b0fc4, 0xff3b1358] parents: 0xff3b0f4c [0x00000000, 0x00000000] |
The dependencies of a handle are a list of link-maps that represent the objects of the handle that can satisfy a dlsym(3DL) request:
> 0xff3b0f44::ListRtmap Listnode data next Rt_map name --------------------------------------------- 0xff3b0fc4 0xff3b0c1c 0xff3b1358 ./foo.so.1 0xff3b1358 0xff3b1030 0x00000000 ./bar.so.1 |
The above examples provide a basic guide to the debugger module capabilities, but the exact commands, usage, and output may change from release to release. Refer to any usage or help information for the exact capabilities available on your system.