4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 #include <mdb/mdb_modapi.h>
32 typedef struct ps_prochandle ps_prochandle_t
;
35 * addr::pr_symtab [-a | n]
37 * -a Sort symbols by address
38 * -n Sort symbols by name
40 * Given a sym_tbl_t, dump its contents in tabular form. When given '-a' or
41 * '-n', we use the sorted tables 'sym_byaddr' or 'sym_byname', respectively.
44 pr_symtab(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
64 if (mdb_getopts(argc
, argv
,
65 'a', MDB_OPT_SETBITS
, TRUE
, &byaddr
,
66 'n', MDB_OPT_SETBITS
, TRUE
, &byname
,
70 if (byaddr
&& byname
) {
71 mdb_warn("only one of '-a' or '-n' can be specified\n");
75 if (!(flags
& DCMD_ADDRSPEC
))
78 if (mdb_vread(&symtab
, sizeof (sym_tbl_t
), addr
) == -1) {
79 mdb_warn("failed to read sym_tbl_t at %p", addr
);
83 if (symtab
.sym_count
== 0) {
84 mdb_warn("no symbols present\n");
89 * As described in the libproc header Pcontrol.h, a sym_tbl_t
90 * contains a primary and an optional auxiliary symbol table.
91 * We treat the combination as a single table, with the auxiliary
92 * values coming before the primary ones.
94 * Read the primary and auxiliary Elf_Data structs.
96 if (mdb_vread(&data_pri
, sizeof (Elf_Data
),
97 (uintptr_t)symtab
.sym_data_pri
) == -1) {
98 mdb_warn("failed to read primary Elf_Data at %p",
102 if ((symtab
.sym_symn_aux
> 0) &&
103 (mdb_vread(&data_aux
, sizeof (Elf_Data
),
104 (uintptr_t)symtab
.sym_data_aux
) == -1)) {
105 mdb_warn("failed to read auxiliary Elf_Data at %p",
106 symtab
.sym_data_aux
);
111 if (byaddr
|| byname
) {
112 uintptr_t src
= byaddr
? (uintptr_t)symtab
.sym_byaddr
:
113 (uintptr_t)symtab
.sym_byname
;
115 symlistsz
= symtab
.sym_count
* sizeof (uint_t
);
116 symlist
= mdb_alloc(symlistsz
, UM_SLEEP
);
117 if (mdb_vread(symlist
, symlistsz
, src
) == -1) {
118 mdb_warn("failed to read sorted symbols at %p", src
);
121 count
= symtab
.sym_count
;
123 count
= symtab
.sym_symn
;
126 mdb_printf("%<u>%*s %*s %s%</u>\n", width
, "ADDRESS", width
,
129 for (i
= 0; i
< count
; i
++) {
135 /* If index is in range of primary symtab, look it up there */
136 if (idx
>= symtab
.sym_symn_aux
) {
138 idx
-= symtab
.sym_symn_aux
;
139 } else { /* Look it up in the auxiliary symtab */
143 if (mdb_vread(&sym
, sizeof (sym
), (uintptr_t)data
->d_buf
+
144 idx
* sizeof (sym
)) == -1) {
145 mdb_warn("failed to read symbol at %p",
146 (uintptr_t)data
->d_buf
+ idx
* sizeof (sym
));
148 mdb_free(symlist
, symlistsz
);
152 if (mdb_readstr(name
, sizeof (name
),
153 (uintptr_t)symtab
.sym_strs
+ sym
.st_name
) == -1) {
154 mdb_warn("failed to read symbol name at %p",
155 symtab
.sym_strs
+ sym
.st_name
);
159 mdb_printf("%0?p %0?p %s\n", sym
.st_value
, sym
.st_size
,
164 mdb_free(symlist
, symlistsz
);
170 * addr::pr_addr2map search
172 * Given a ps_prochandle_t, convert the given address to the corresponding
173 * map_info_t. Functionally equivalent to Paddr2mptr().
176 pr_addr2map(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
183 if (!(flags
& DCMD_ADDRSPEC
) || argc
!= 1)
186 if (argv
[0].a_type
== MDB_TYPE_IMMEDIATE
)
187 search
= argv
[0].a_un
.a_val
;
189 search
= mdb_strtoull(argv
[0].a_un
.a_str
);
191 if (mdb_vread(&psp
, sizeof (ps_prochandle_t
), addr
) == -1) {
192 mdb_warn("failed to read ps_prochandle at %p", addr
);
200 mp
= &psp
.mappings
[mid
];
202 if ((addr
- mp
->map_pmap
.pr_vaddr
) < mp
->map_pmap
.pr_size
) {
203 mdb_printf("%#lr\n", addr
+ offsetof(ps_prochandle_t
,
204 mappings
) + (mp
- psp
.mappings
) *
205 sizeof (map_info_t
));
209 if (addr
< mp
->map_pmap
.pr_vaddr
)
215 mdb_warn("no corresponding map for %p\n", search
);
220 * ::walk pr_file_info
222 * Given a ps_prochandle_t, walk all its file_info_t structures.
230 pr_file_info_walk_init(mdb_walk_state_t
*wsp
)
233 file_info_walk_t
*fiw
;
235 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
236 mdb_warn("pr_file_info doesn't support global walks\n");
240 if (mdb_vread(&psp
, sizeof (ps_prochandle_t
), wsp
->walk_addr
) == -1) {
241 mdb_warn("failed to read ps_prochandle at %p", wsp
->walk_addr
);
245 fiw
= mdb_alloc(sizeof (file_info_walk_t
), UM_SLEEP
);
247 fiw
->fiw_next
= (uintptr_t)psp
.file_head
.list_forw
;
248 fiw
->fiw_count
= psp
.num_files
;
249 wsp
->walk_data
= fiw
;
255 pr_file_info_walk_step(mdb_walk_state_t
*wsp
)
257 file_info_walk_t
*fiw
= wsp
->walk_data
;
261 if (fiw
->fiw_count
== 0)
264 if (mdb_vread(&f
, sizeof (file_info_t
), fiw
->fiw_next
) == -1) {
265 mdb_warn("failed to read file_info_t at %p", fiw
->fiw_next
);
269 status
= wsp
->walk_callback(fiw
->fiw_next
, &f
, wsp
->walk_cbdata
);
271 fiw
->fiw_next
= (uintptr_t)f
.file_list
.list_forw
;
278 pr_file_info_walk_fini(mdb_walk_state_t
*wsp
)
280 file_info_walk_t
*fiw
= wsp
->walk_data
;
281 mdb_free(fiw
, sizeof (file_info_walk_t
));
287 * Given a ps_prochandle_t, walk all its map_info_t structures.
296 pr_map_info_walk_init(mdb_walk_state_t
*wsp
)
299 map_info_walk_t
*miw
;
301 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
302 mdb_warn("pr_map_info doesn't support global walks\n");
306 if (mdb_vread(&psp
, sizeof (ps_prochandle_t
), wsp
->walk_addr
) == -1) {
307 mdb_warn("failed to read ps_prochandle at %p", wsp
->walk_addr
);
311 miw
= mdb_alloc(sizeof (map_info_walk_t
), UM_SLEEP
);
313 miw
->miw_next
= (uintptr_t)psp
.mappings
;
314 miw
->miw_count
= psp
.map_count
;
315 miw
->miw_current
= 0;
316 wsp
->walk_data
= miw
;
322 pr_map_info_walk_step(mdb_walk_state_t
*wsp
)
324 map_info_walk_t
*miw
= wsp
->walk_data
;
328 if (miw
->miw_current
== miw
->miw_count
)
331 if (mdb_vread(&m
, sizeof (map_info_t
), miw
->miw_next
) == -1) {
332 mdb_warn("failed to read map_info_t at %p", miw
->miw_next
);
336 status
= wsp
->walk_callback(miw
->miw_next
, &m
, wsp
->walk_cbdata
);
339 miw
->miw_next
+= sizeof (map_info_t
);
345 pr_map_info_walk_fini(mdb_walk_state_t
*wsp
)
347 map_info_walk_t
*miw
= wsp
->walk_data
;
348 mdb_free(miw
, sizeof (map_info_walk_t
));
351 static const mdb_dcmd_t dcmds
[] = {
352 { "pr_addr2map", ":addr", "convert an adress into a map_info_t",
354 { "pr_symtab", ":[-a | -n]", "print the contents of a sym_tbl_t",
359 static const mdb_walker_t walkers
[] = {
360 { "pr_file_info", "given a ps_prochandle, walk its file_info "
361 "structures", pr_file_info_walk_init
, pr_file_info_walk_step
,
362 pr_file_info_walk_fini
},
363 { "pr_map_info", "given a ps_prochandle, walk its map_info structures",
364 pr_map_info_walk_init
, pr_map_info_walk_step
,
365 pr_map_info_walk_fini
},
369 static const mdb_modinfo_t modinfo
= {
370 MDB_API_VERSION
, dcmds
, walkers
373 const mdb_modinfo_t
*