4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/machelf.h>
28 #include <sys/modctl.h>
31 #include <mdb/mdb_modapi.h>
33 static uintptr_t module_head
; /* Head of kernel modctl list */
35 struct modctl_walk_data
{
37 struct modctl mwd_modctl
;
41 modctl_walk_init(mdb_walk_state_t
*wsp
)
43 struct modctl_walk_data
*mwd
= mdb_alloc(
44 sizeof (struct modctl_walk_data
), UM_SLEEP
);
46 mwd
->mwd_head
= (wsp
->walk_addr
== (uintptr_t)NULL
?
47 module_head
: wsp
->walk_addr
);
49 wsp
->walk_addr
= (uintptr_t)NULL
;
55 modctl_walk_step(mdb_walk_state_t
*wsp
)
57 struct modctl_walk_data
*mwd
= wsp
->walk_data
;
60 if (wsp
->walk_addr
== mwd
->mwd_head
)
63 if (wsp
->walk_addr
== (uintptr_t)NULL
)
64 wsp
->walk_addr
= mwd
->mwd_head
;
66 if (mdb_vread(&mwd
->mwd_modctl
, sizeof (struct modctl
),
67 wsp
->walk_addr
) == -1) {
68 mdb_warn("failed to read modctl at %p", wsp
->walk_addr
);
72 status
= wsp
->walk_callback(wsp
->walk_addr
, &mwd
->mwd_modctl
,
75 wsp
->walk_addr
= (uintptr_t)mwd
->mwd_modctl
.mod_next
;
81 modctl_walk_fini(mdb_walk_state_t
*wsp
)
83 mdb_free(wsp
->walk_data
, sizeof (struct modctl_walk_data
));
88 modctl_format(uintptr_t addr
, const void *data
, void *private)
90 const struct modctl
*mcp
= (const struct modctl
*)data
;
91 char name
[MAXPATHLEN
], bits
[6], *bp
= &bits
[0];
93 if (mdb_readstr(name
, sizeof (name
),
94 (uintptr_t)mcp
->mod_filename
) == -1)
95 (void) strcpy(name
, "???");
105 if (mcp
->mod_installed
)
109 mdb_printf("%?p %?p %6s 0x%02x %3d %s\n",
110 (uintptr_t)addr
, (uintptr_t)mcp
->mod_mp
, bits
, mcp
->mod_loadflags
,
118 modctls(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
123 if ((flags
& DCMD_LOOPFIRST
) || !(flags
& DCMD_LOOP
)) {
124 mdb_printf("%<u>%?s %?s %6s %4s %3s %s%</u>\n",
125 "MODCTL", "MODULE", "BITS", "FLAGS", "REF", "FILE");
128 if (flags
& DCMD_ADDRSPEC
) {
131 (void) mdb_vread(&mc
, sizeof (mc
), addr
);
132 return (modctl_format(addr
, &mc
, NULL
));
135 if (mdb_walk("modctl", modctl_format
, NULL
) == -1)
142 dump_ehdr(const Ehdr
*ehdr
)
144 mdb_printf("\nELF Header\n");
146 mdb_printf(" ei_magic: { 0x%02x, %c, %c, %c }\n",
147 ehdr
->e_ident
[EI_MAG0
], ehdr
->e_ident
[EI_MAG1
],
148 ehdr
->e_ident
[EI_MAG2
], ehdr
->e_ident
[EI_MAG3
]);
150 mdb_printf(" ei_class: %-18u ei_data: %-16u\n",
151 ehdr
->e_ident
[EI_CLASS
], ehdr
->e_ident
[EI_DATA
]);
153 mdb_printf(" e_machine: %-18hu e_version: %-16u\n",
154 ehdr
->e_machine
, ehdr
->e_version
);
156 mdb_printf(" e_type: %-18hu\n", ehdr
->e_type
);
157 mdb_printf(" e_flags: %-18u\n", ehdr
->e_flags
);
159 mdb_printf(" e_entry: 0x%16lx e_ehsize: %8hu e_shstrndx: %hu\n",
160 ehdr
->e_entry
, ehdr
->e_ehsize
, ehdr
->e_shstrndx
);
162 mdb_printf(" e_shoff: 0x%16lx e_shentsize: %8hu e_shnum: %hu\n",
163 ehdr
->e_shoff
, ehdr
->e_shentsize
, ehdr
->e_shnum
);
165 mdb_printf(" e_phoff: 0x%16lx e_phentsize: %8hu e_phnum: %hu\n",
166 ehdr
->e_phoff
, ehdr
->e_phentsize
, ehdr
->e_phnum
);
170 dump_shdr(const Shdr
*shdr
, int i
)
172 static const mdb_bitmask_t sh_type_masks
[] = {
173 { "SHT_NULL", 0xffffffff, SHT_NULL
},
174 { "SHT_PROGBITS", 0xffffffff, SHT_PROGBITS
},
175 { "SHT_SYMTAB", 0xffffffff, SHT_SYMTAB
},
176 { "SHT_STRTAB", 0xffffffff, SHT_STRTAB
},
177 { "SHT_RELA", 0xffffffff, SHT_RELA
},
178 { "SHT_HASH", 0xffffffff, SHT_HASH
},
179 { "SHT_DYNAMIC", 0xffffffff, SHT_DYNAMIC
},
180 { "SHT_NOTE", 0xffffffff, SHT_NOTE
},
181 { "SHT_NOBITS", 0xffffffff, SHT_NOBITS
},
182 { "SHT_REL", 0xffffffff, SHT_REL
},
183 { "SHT_SHLIB", 0xffffffff, SHT_SHLIB
},
184 { "SHT_DYNSYM", 0xffffffff, SHT_DYNSYM
},
185 { "SHT_LOSUNW", 0xffffffff, SHT_LOSUNW
},
186 { "SHT_SUNW_COMDAT", 0xffffffff, SHT_SUNW_COMDAT
},
187 { "SHT_SUNW_syminfo", 0xffffffff, SHT_SUNW_syminfo
},
188 { "SHT_SUNW_verdef", 0xffffffff, SHT_SUNW_verdef
},
189 { "SHT_SUNW_verneed", 0xffffffff, SHT_SUNW_verneed
},
190 { "SHT_SUNW_versym", 0xffffffff, SHT_SUNW_versym
},
191 { "SHT_HISUNW", 0xffffffff, SHT_HISUNW
},
192 { "SHT_LOPROC", 0xffffffff, SHT_LOPROC
},
193 { "SHT_HIPROC", 0xffffffff, SHT_HIPROC
},
194 { "SHT_LOUSER", 0xffffffff, SHT_LOUSER
},
195 { "SHT_HIUSER", 0xffffffff, SHT_HIUSER
},
199 static const mdb_bitmask_t sh_flag_masks
[] = {
200 { "SHF_WRITE", SHF_WRITE
, SHF_WRITE
},
201 { "SHF_ALLOC", SHF_ALLOC
, SHF_ALLOC
},
202 { "SHF_EXECINSTR", SHF_EXECINSTR
, SHF_EXECINSTR
},
203 { "SHF_MASKPROC", SHF_MASKPROC
, SHF_MASKPROC
},
207 mdb_printf("\nSection Header[%d]:\n", i
);
209 mdb_printf(" sh_addr: 0x%-16lx sh_flags: [ %#lb ]\n",
210 shdr
->sh_addr
, shdr
->sh_flags
, sh_flag_masks
);
212 mdb_printf(" sh_size: 0x%-16lx sh_type: [ %#lb ]\n",
213 shdr
->sh_size
, shdr
->sh_type
, sh_type_masks
);
215 mdb_printf(" sh_offset: 0x%-16lx sh_entsize: 0x%lx\n",
216 shdr
->sh_offset
, shdr
->sh_entsize
);
218 mdb_printf(" sh_link: 0x%-16lx sh_info: 0x%lx\n",
219 shdr
->sh_link
, shdr
->sh_info
);
221 mdb_printf(" sh_addralign: 0x%-16lx\n", shdr
->sh_addralign
);
226 modhdrs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
235 if (!(flags
& DCMD_ADDRSPEC
)) {
236 mdb_warn("expected address of struct modctl before ::\n");
243 mdb_vread(&ctl
, sizeof (struct modctl
), addr
);
244 mdb_vread(&mod
, sizeof (struct module
), (uintptr_t)ctl
.mod_mp
);
247 nbytes
= sizeof (Shdr
) * mod
.hdr
.e_shnum
;
248 shdrs
= mdb_alloc(nbytes
, UM_SLEEP
| UM_GC
);
249 mdb_vread(shdrs
, nbytes
, (uintptr_t)mod
.shdrs
);
251 for (i
= 0; i
< mod
.hdr
.e_shnum
; i
++)
252 dump_shdr(&shdrs
[i
], i
);
259 modinfo_format(uintptr_t addr
, const void *data
, void *private)
261 const struct modctl
*mcp
= (const struct modctl
*)data
;
263 struct modlinkage linkage
;
264 struct modlmisc lmisc
;
267 char info
[MODMAXLINKINFOLEN
];
268 char name
[MODMAXNAMELEN
];
278 if (mcp
->mod_mp
!= NULL
)
279 (void) mdb_vread(&mod
, sizeof (mod
), (uintptr_t)mcp
->mod_mp
);
281 if (mcp
->mod_linkage
!= NULL
) {
282 (void) mdb_vread(&linkage
, sizeof (linkage
),
283 (uintptr_t)mcp
->mod_linkage
);
285 if (linkage
.ml_linkage
[0] != NULL
) {
286 (void) mdb_vread(&lmisc
, sizeof (lmisc
),
287 (uintptr_t)linkage
.ml_linkage
[0]);
288 mdb_readstr(info
, sizeof (info
),
289 (uintptr_t)lmisc
.misc_linkinfo
);
293 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)mcp
->mod_modname
) == -1)
294 (void) strcpy(name
, "???");
296 mdb_printf("%3d %?p %8lx %3d %s (%s)\n",
297 mcp
->mod_id
, mod
.text
, mod
.text_size
+ mod
.data_size
,
298 linkage
.ml_rev
, name
, info
[0] != '\0' ? info
: "?");
305 modinfo(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
310 if ((flags
& DCMD_LOOPFIRST
) || !(flags
& DCMD_LOOP
)) {
311 mdb_printf("%<u>%3s %?s %8s %3s %s%</u>\n",
312 "ID", "LOADADDR", "SIZE", "REV", "MODULE NAME");
315 if (flags
& DCMD_ADDRSPEC
) {
318 (void) mdb_vread(&mc
, sizeof (mc
), addr
);
319 return (modinfo_format(addr
, &mc
, NULL
));
322 if (mdb_walk("modctl", modinfo_format
, NULL
) == -1)
330 ctfinfo_format(uintptr_t addr
, const struct modctl
*mcp
, void *private)
332 char name
[MODMAXNAMELEN
];
335 if (mcp
->mod_mp
== NULL
)
336 return (WALK_NEXT
); /* module is not loaded */
338 if (mdb_vread(&mod
, sizeof (mod
), (uintptr_t)mcp
->mod_mp
) == -1) {
339 mdb_warn("failed to read module at %p for modctl %p\n",
344 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)mcp
->mod_modname
) == -1)
345 (void) mdb_snprintf(name
, sizeof (name
), "%a", mcp
->mod_mp
);
347 mdb_printf("%-30s %?p %lu\n", name
, mod
.ctfdata
, (ulong_t
)mod
.ctfsize
);
353 ctfinfo(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
355 if ((flags
& DCMD_ADDRSPEC
) || argc
!= 0)
358 mdb_printf("%<u>%-30s %?s %s%</u>\n", "MODULE", "CTFDATA", "CTFSIZE");
359 if (mdb_walk("modctl", (mdb_walk_cb_t
)ctfinfo_format
, NULL
) == -1)
365 static const mdb_dcmd_t dcmds
[] = {
366 { "modctl", NULL
, "list modctl structures", modctls
},
367 { "modhdrs", ":", "given modctl, dump module ehdr and shdrs", modhdrs
},
368 { "modinfo", NULL
, "list module information", modinfo
},
369 { "ctfinfo", NULL
, "list module CTF information", ctfinfo
},
373 static const mdb_walker_t walkers
[] = {
374 { "modctl", "list of modctl structures",
375 modctl_walk_init
, modctl_walk_step
, modctl_walk_fini
},
379 static const mdb_modinfo_t krtld_modinfo
= { MDB_API_VERSION
, dcmds
, walkers
};
381 const mdb_modinfo_t
*
386 if (mdb_lookup_by_name("modules", &sym
) == -1) {
387 mdb_warn("failed to lookup 'modules'");
391 module_head
= (uintptr_t)sym
.st_value
;
392 return (&krtld_modinfo
);