Print this page
4785 mdb crashes in ::ldi_handle
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/modules/genunix/ldi.c
+++ new/usr/src/cmd/mdb/common/modules/genunix/ldi.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 #include <sys/types.h>
30 28 #include <sys/sysmacros.h>
31 29 #include <sys/dditypes.h>
32 30 #include <sys/ddi_impldefs.h>
33 31 #include <sys/ddipropdefs.h>
34 32 #include <sys/modctl.h>
35 33 #include <sys/file.h>
36 34 #include <sys/sunldi_impl.h>
37 35
38 36 #include <mdb/mdb_modapi.h>
39 37 #include <mdb/mdb_ks.h>
40 38
41 39 #include "ldi.h"
42 40
43 41 /*
44 42 * ldi handle walker structure
45 43 */
46 44 typedef struct lh_walk {
47 45 struct ldi_handle **hash; /* current bucket pointer */
48 46 struct ldi_handle *lhp; /* ldi handle pointer */
49 47 size_t index; /* hash table index */
50 48 struct ldi_handle buf; /* buffer used for handle reads */
51 49 } lh_walk_t;
52 50
53 51 /*
54 52 * ldi identifier walker structure
55 53 */
56 54 typedef struct li_walk {
57 55 struct ldi_ident **hash; /* current bucket pointer */
58 56 struct ldi_ident *lip; /* ldi handle pointer */
59 57 size_t index; /* hash table index */
60 58 struct ldi_ident buf; /* buffer used for ident reads */
61 59 } li_walk_t;
62 60
63 61 /*
64 62 * Options for ldi_handles dcmd
65 63 */
66 64 #define LH_IDENTINFO 0x1
67 65
68 66 /*
69 67 * LDI walkers
70 68 */
71 69 int
72 70 ldi_handle_walk_init(mdb_walk_state_t *wsp)
73 71 {
74 72 lh_walk_t *lhwp;
75 73 GElf_Sym sym;
76 74
77 75 /* get the address of the hash table */
78 76 if (mdb_lookup_by_name("ldi_handle_hash", &sym) == -1) {
79 77 mdb_warn("couldn't find ldi_handle_hash");
80 78 return (WALK_ERR);
81 79 }
82 80
83 81 lhwp = mdb_alloc(sizeof (lh_walk_t), UM_SLEEP|UM_GC);
84 82 lhwp->hash = (struct ldi_handle **)(uintptr_t)sym.st_value;
85 83 lhwp->index = 0;
86 84
87 85 /* get the address of the first element in the first hash bucket */
88 86 if ((mdb_vread(&lhwp->lhp, sizeof (struct ldi_handle *),
89 87 (uintptr_t)lhwp->hash)) == -1) {
90 88 mdb_warn("couldn't read ldi handle hash at %p", lhwp->hash);
91 89 return (WALK_ERR);
92 90 }
93 91
94 92 wsp->walk_addr = (uintptr_t)lhwp->lhp;
95 93 wsp->walk_data = lhwp;
96 94
97 95 return (WALK_NEXT);
98 96 }
99 97
100 98 int
101 99 ldi_handle_walk_step(mdb_walk_state_t *wsp)
102 100 {
103 101 lh_walk_t *lhwp = (lh_walk_t *)wsp->walk_data;
104 102 int status;
105 103
106 104 /* check if we need to go to the next hash bucket */
107 105 while (wsp->walk_addr == NULL) {
108 106
109 107 /* advance to the next bucket */
110 108 if (++(lhwp->index) >= LH_HASH_SZ)
111 109 return (WALK_DONE);
112 110
113 111 /* get handle address from the hash bucket */
114 112 if ((mdb_vread(&lhwp->lhp, sizeof (struct ldi_handle *),
115 113 (uintptr_t)(lhwp->hash + lhwp->index))) == -1) {
116 114 mdb_warn("couldn't read ldi handle hash at %p",
117 115 (uintptr_t)lhwp->hash + lhwp->index);
118 116 return (WALK_ERR);
119 117 }
120 118
121 119 wsp->walk_addr = (uintptr_t)lhwp->lhp;
122 120 }
123 121
124 122 /* invoke the walker callback for this hash element */
125 123 status = wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata);
126 124 if (status != WALK_NEXT)
127 125 return (status);
128 126
129 127 /* get a pointer to the next hash element */
130 128 if (mdb_vread(&lhwp->buf, sizeof (struct ldi_handle),
131 129 wsp->walk_addr) == -1) {
132 130 mdb_warn("couldn't read ldi handle at %p", wsp->walk_addr);
133 131 return (WALK_ERR);
134 132 }
135 133 wsp->walk_addr = (uintptr_t)lhwp->buf.lh_next;
136 134 return (WALK_NEXT);
137 135 }
138 136
139 137 int
140 138 ldi_ident_walk_init(mdb_walk_state_t *wsp)
141 139 {
142 140 li_walk_t *liwp;
143 141 GElf_Sym sym;
144 142
145 143 /* get the address of the hash table */
146 144 if (mdb_lookup_by_name("ldi_ident_hash", &sym) == -1) {
147 145 mdb_warn("couldn't find ldi_ident_hash");
148 146 return (WALK_ERR);
149 147 }
150 148
151 149 liwp = mdb_alloc(sizeof (li_walk_t), UM_SLEEP|UM_GC);
152 150 liwp->hash = (struct ldi_ident **)(uintptr_t)sym.st_value;
153 151 liwp->index = 0;
154 152
155 153 /* get the address of the first element in the first hash bucket */
156 154 if ((mdb_vread(&liwp->lip, sizeof (struct ldi_ident *),
157 155 (uintptr_t)liwp->hash)) == -1) {
158 156 mdb_warn("couldn't read ldi ident hash at %p", liwp->hash);
159 157 return (WALK_ERR);
160 158 }
161 159
162 160 wsp->walk_addr = (uintptr_t)liwp->lip;
163 161 wsp->walk_data = liwp;
164 162
165 163 return (WALK_NEXT);
166 164 }
167 165
168 166 int
169 167 ldi_ident_walk_step(mdb_walk_state_t *wsp)
170 168 {
171 169 li_walk_t *liwp = (li_walk_t *)wsp->walk_data;
172 170 int status;
173 171
174 172 /* check if we need to go to the next hash bucket */
175 173 while (wsp->walk_addr == NULL) {
176 174
177 175 /* advance to the next bucket */
178 176 if (++(liwp->index) >= LI_HASH_SZ)
179 177 return (WALK_DONE);
180 178
181 179 /* get handle address from the hash bucket */
182 180 if ((mdb_vread(&liwp->lip, sizeof (struct ldi_ident *),
183 181 (uintptr_t)(liwp->hash + liwp->index))) == -1) {
184 182 mdb_warn("couldn't read ldi ident hash at %p",
185 183 (uintptr_t)liwp->hash + liwp->index);
186 184 return (WALK_ERR);
187 185 }
188 186
189 187 wsp->walk_addr = (uintptr_t)liwp->lip;
190 188 }
191 189
192 190 /* invoke the walker callback for this hash element */
193 191 status = wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata);
194 192 if (status != WALK_NEXT)
195 193 return (status);
196 194
197 195 /* get a pointer to the next hash element */
198 196 if (mdb_vread(&liwp->buf, sizeof (struct ldi_ident),
199 197 wsp->walk_addr) == -1) {
200 198 mdb_warn("couldn't read ldi ident at %p", wsp->walk_addr);
201 199 return (WALK_ERR);
202 200 }
203 201 wsp->walk_addr = (uintptr_t)liwp->buf.li_next;
204 202 return (WALK_NEXT);
205 203 }
206 204
207 205 /*
208 206 * LDI dcmds
209 207 */
210 208 static void
211 209 ldi_ident_header(int start, int refs)
212 210 {
213 211 if (start) {
214 212 mdb_printf("%-?s ", "IDENT");
215 213 } else {
216 214 mdb_printf("%?s ", "IDENT");
217 215 }
218 216
219 217 if (refs)
220 218 mdb_printf("%4s ", "REFS");
221 219
222 220 mdb_printf("%?s %5s %5s %s\n", "DIP", "MINOR", "MODID", "MODULE NAME");
223 221 }
224 222
225 223 static int
226 224 ldi_ident_print(uintptr_t addr, int refs)
227 225 {
228 226 struct ldi_ident li;
229 227
230 228 /* read the ldi ident */
231 229 if (mdb_vread(&li, sizeof (struct ldi_ident), addr) == -1) {
232 230 mdb_warn("couldn't read ldi ident at %p", addr);
233 231 return (1);
234 232 }
235 233
236 234 /* display the ident address */
237 235 mdb_printf("%0?p ", addr);
238 236
239 237 /* display the ref count */
240 238 if (refs)
241 239 mdb_printf("%4u ", li.li_ref);
242 240
243 241 /* display the dip (if any) */
244 242 if (li.li_dip != NULL) {
245 243 mdb_printf("%0?p ", li.li_dip);
246 244 } else {
247 245 mdb_printf("%?s ", "-");
248 246 }
249 247
250 248 /* display the minor node (if any) */
251 249 if (li.li_dev != DDI_DEV_T_NONE) {
252 250 mdb_printf("%5u ", getminor(li.li_dev));
253 251 } else {
254 252 mdb_printf("%5s ", "-");
255 253 }
256 254
257 255 /* display the module info */
258 256 mdb_printf("%5d %s\n", li.li_modid, li.li_modname);
259 257
260 258 return (0);
261 259 }
262 260
263 261 int
264 262 ldi_ident(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
265 263 {
266 264 int start = 1;
267 265 int refs = 1;
268 266
269 267 /* Determine if there is an ldi identifier address */
270 268 if (!(flags & DCMD_ADDRSPEC)) {
271 269 if (mdb_walk_dcmd("ldi_ident", "ldi_ident",
272 270 argc, argv) == -1) {
273 271 mdb_warn("can't walk ldi idents");
274 272 return (DCMD_ERR);
275 273 }
276 274 return (DCMD_OK);
277 275 }
278 276
279 277 /* display the header line */
280 278 if (DCMD_HDRSPEC(flags))
281 279 ldi_ident_header(start, refs);
282 280
283 281 /* display the ldi ident */
284 282 if (ldi_ident_print(addr, refs))
285 283 return (DCMD_ERR);
286 284
287 285 return (DCMD_OK);
288 286 }
289 287
290 288 static void
291 289 ldi_handle_header(int refs, int ident) {
292 290 mdb_printf("%-?s ", "HANDLE");
293 291
294 292 if (refs)
295 293 mdb_printf("%4s ", "REFS");
296 294
297 295 mdb_printf("%?s %10s %5s %?s ", "VNODE", "DRV", "MINOR", "EVENTS");
298 296
299 297 if (!ident) {
300 298 mdb_printf("%?s\n", "IDENT");
301 299 } else {
302 300 ldi_ident_header(0, 0);
303 301 }
304 302 }
305 303
306 304 static int
307 305 ldi_handle_print(uintptr_t addr, int ident, int refs)
308 306 {
309 307 vnode_t vnode;
310 308 struct ldi_handle lh;
311 309 const char *name;
312 310
313 311 /* read in the ldi handle */
314 312 if (mdb_vread(&lh, sizeof (struct ldi_handle), addr) == -1) {
315 313 mdb_warn("couldn't read ldi handle at %p", addr);
316 314 return (DCMD_ERR);
317 315 }
318 316
319 317 /* display the handle address */
320 318 mdb_printf("%0?p ", addr);
321 319
322 320 /* display the ref count */
323 321 if (refs)
324 322 mdb_printf("%4u ", lh.lh_ref);
325 323
326 324 /* display the vnode */
327 325 mdb_printf("%0?p ", lh.lh_vp);
328 326
329 327 /* read in the vnode associated with the handle */
330 328 addr = (uintptr_t)lh.lh_vp;
331 329 if (mdb_vread(&vnode, sizeof (vnode_t), addr) == -1) {
332 330 mdb_warn("couldn't read vnode at %p", addr);
333 331 return (1);
334 332 }
335 333
336 334 /* display the driver name */
337 335 if ((name = mdb_major_to_name(getmajor(vnode.v_rdev))) == NULL) {
338 336 mdb_warn("failed to convert major number to name\n");
339 337 return (1);
340 338 }
341 339 mdb_printf("%10s ", name);
342 340
343 341 /* display the minor number */
344 342 mdb_printf("%5d ", getminor(vnode.v_rdev));
345 343
346 344 /* display the event pointer (if any) */
347 345 if (lh.lh_events != NULL) {
348 346 mdb_printf("%0?p ", lh.lh_events);
349 347 } else {
350 348 mdb_printf("%?s ", "-");
351 349 }
352 350
353 351 if (!ident) {
354 352 /* display the ident address */
355 353 mdb_printf("%0?p\n", lh.lh_ident);
356 354 return (0);
357 355 }
358 356
↓ open down ↓ |
320 lines elided |
↑ open up ↑ |
359 357 /* display the entire ident */
360 358 return (ldi_ident_print((uintptr_t)lh.lh_ident, refs));
361 359 }
362 360
363 361 int
364 362 ldi_handle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
365 363 {
366 364 int ident = 0;
367 365 int refs = 1;
368 366
369 - if (mdb_getopts(argc, argv,
370 - 'i', MDB_OPT_SETBITS, TRUE, &ident) != argc)
371 - return (DCMD_USAGE);
372 -
373 - if (ident)
374 - refs = 0;
375 -
376 367 /* Determine if there is an ldi handle address */
377 368 if (!(flags & DCMD_ADDRSPEC)) {
378 369 if (mdb_walk_dcmd("ldi_handle", "ldi_handle",
379 370 argc, argv) == -1) {
380 371 mdb_warn("can't walk ldi handles");
381 372 return (DCMD_ERR);
382 373 } return (DCMD_OK);
383 374 }
384 375
376 + if (mdb_getopts(argc, argv,
377 + 'i', MDB_OPT_SETBITS, TRUE, &ident) != argc)
378 + return (DCMD_USAGE);
379 +
380 + if (ident)
381 + refs = 0;
382 +
385 383 /* display the header line */
386 384 if (DCMD_HDRSPEC(flags))
387 385 ldi_handle_header(refs, ident);
388 386
389 387 /* display the ldi handle */
390 388 if (ldi_handle_print(addr, ident, refs))
391 389 return (DCMD_ERR);
392 390
393 391 return (DCMD_OK);
394 392 }
395 393
396 394 void
397 395 ldi_ident_help(void)
398 396 {
399 397 mdb_printf("Displays an ldi identifier.\n"
400 398 "Without the address of an \"ldi_ident_t\", "
401 399 "print all identifiers.\n"
402 400 "With an address, print the specified identifier.\n");
403 401 }
404 402
405 403 void
406 404 ldi_handle_help(void)
407 405 {
408 406 mdb_printf("Displays an ldi handle.\n"
409 407 "Without the address of an \"ldi_handle_t\", "
410 408 "print all handles.\n"
411 409 "With an address, print the specified handle.\n\n"
412 410 "Switches:\n"
413 411 " -i print the module identifier information\n");
414 412 }
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX