Print this page
OS-3561 lxbrand emulation library should execute on alternate stack
OS-3558 lxbrand add support for full in-kernel syscall handling
OS-3545 lx_syscall_regs should not walk stack
OS-3868 many LTP testcases now hang
OS-3901 lxbrand lx_recvmsg fails to translate control messages when 64-bit
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
OS-2844 lx brand should support 64-bit user-land
OS-3280 need a way to specify the root of a native system in the lx brand
OS-3279 lx brand should allow delegated datasets
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/mdb/common/modules/libc/libc.c
+++ new/usr/src/cmd/mdb/common/modules/libc/libc.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 (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2012 by Delphix. All rights reserved.
25 25 * Copyright 2016, Joyent, Inc.
26 26 */
27 27
28 28 #include <sys/mdb_modapi.h>
29 29 #include <mdb/mdb_whatis.h>
30 30 #include <mdb/mdb_ctf.h>
31 31 #include <procfs.h>
32 32 #include <ucontext.h>
33 33 #include <siginfo.h>
34 34 #include <signal.h>
35 35 #include <setjmp.h>
36 36 #include <string.h>
37 37 #include <thr_uberdata.h>
38 38 #include "findstack.h"
39 39
40 40 static const char *
41 41 stack_flags(const stack_t *sp)
42 42 {
43 43 static char buf[32];
44 44
45 45 if (sp->ss_flags == 0)
46 46 (void) strcpy(buf, " 0");
47 47 else if (sp->ss_flags & ~(SS_ONSTACK | SS_DISABLE))
48 48 (void) mdb_snprintf(buf, sizeof (buf), " 0x%x", sp->ss_flags);
49 49 else {
50 50 buf[0] = '\0';
51 51 if (sp->ss_flags & SS_ONSTACK)
52 52 (void) strcat(buf, "|ONSTACK");
53 53 if (sp->ss_flags & SS_DISABLE)
54 54 (void) strcat(buf, "|DISABLE");
55 55 }
56 56
57 57 return (buf + 1);
58 58 }
59 59
60 60 /*ARGSUSED*/
61 61 static int
62 62 d_jmp_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
63 63 {
64 64 jmp_buf jb;
65 65 const ulong_t *b = (const ulong_t *)jb;
66 66
67 67 if (argc != 0)
68 68 return (DCMD_USAGE);
69 69
70 70 if (mdb_vread(&jb, sizeof (jb), addr) != sizeof (jb)) {
71 71 mdb_warn("failed to read jmp_buf at %p", addr);
72 72 return (DCMD_ERR);
73 73 }
74 74
75 75 #if defined(__sparc)
76 76 mdb_printf(" %%sp = 0x%lx\n", b[1]);
77 77 mdb_printf(" %%pc = 0x%lx %lA\n", b[2], b[2]);
78 78 mdb_printf(" %%fp = 0x%lx\n", b[3]);
79 79 mdb_printf(" %%i7 = 0x%lx %lA\n", b[4], b[4]);
80 80 #elif defined(__amd64)
81 81 mdb_printf(" %%rbx = 0x%lx\n", b[0]);
82 82 mdb_printf(" %%r12 = 0x%lx\n", b[1]);
83 83 mdb_printf(" %%r13 = 0x%lx\n", b[2]);
84 84 mdb_printf(" %%r14 = 0x%lx\n", b[3]);
85 85 mdb_printf(" %%r15 = 0x%lx\n", b[4]);
86 86 mdb_printf(" %%rbp = 0x%lx\n", b[5]);
87 87 mdb_printf(" %%rsp = 0x%lx\n", b[6]);
88 88 mdb_printf(" %%rip = 0x%lx %lA\n", b[7], b[7]);
89 89 #elif defined(__i386)
90 90 mdb_printf(" %%ebx = 0x%lx\n", b[0]);
91 91 mdb_printf(" %%esi = 0x%lx\n", b[1]);
92 92 mdb_printf(" %%edi = 0x%lx\n", b[2]);
93 93 mdb_printf(" %%ebp = 0x%lx\n", b[3]);
94 94 mdb_printf(" %%esp = 0x%lx\n", b[4]);
95 95 mdb_printf(" %%eip = 0x%lx %lA\n", b[5], b[5]);
96 96 #endif
97 97 return (DCMD_OK);
98 98 }
99 99
100 100 const mdb_bitmask_t uc_flags_bits[] = {
101 101 { "UC_SIGMASK", UC_SIGMASK, UC_SIGMASK },
102 102 { "UC_STACK", UC_STACK, UC_STACK },
103 103 { "UC_CPU", UC_CPU, UC_CPU },
104 104 { "UC_FPU", UC_FPU, UC_FPU },
105 105 #if defined(UC_INTR)
106 106 { "UC_INTR", UC_INTR, UC_INTR },
107 107 #endif
108 108 #if defined(UC_ASR)
109 109 { "UC_ASR", UC_ASR, UC_ASR },
110 110 #endif
111 111 { NULL, 0, 0 }
112 112 };
113 113
114 114 /*ARGSUSED*/
115 115 static int
116 116 d_ucontext(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
117 117 {
118 118 ucontext_t uc;
119 119
120 120 if (argc != 0)
121 121 return (DCMD_USAGE);
122 122
123 123 if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
124 124 mdb_warn("failed to read ucontext at %p", addr);
125 125 return (DCMD_ERR);
126 126 }
127 127
|
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
128 128 mdb_printf(" flags = 0x%lx <%b>\n", uc.uc_flags,
129 129 (uint_t)uc.uc_flags, uc_flags_bits);
130 130 mdb_printf(" link = 0x%p\n", uc.uc_link);
131 131 mdb_printf(" sigmask = 0x%08x 0x%08x 0x%08x 0x%08x\n",
132 132 uc.uc_sigmask.__sigbits[0], uc.uc_sigmask.__sigbits[1],
133 133 uc.uc_sigmask.__sigbits[2], uc.uc_sigmask.__sigbits[3]);
134 134 mdb_printf(" stack = sp 0x%p size 0x%lx flags %s\n",
135 135 uc.uc_stack.ss_sp, uc.uc_stack.ss_size, stack_flags(&uc.uc_stack));
136 136 mdb_printf(" mcontext = 0x%p\n",
137 137 addr + OFFSETOF(ucontext_t, uc_mcontext));
138 + mdb_printf(" brand = 0x%p 0x%p 0x%p\n",
139 + uc.uc_brand_data[0], uc.uc_brand_data[1], uc.uc_brand_data[2]);
138 140
139 141 return (DCMD_OK);
140 142 }
141 143
142 144 /*ARGSUSED*/
143 145 static int
144 146 d_sigjmp_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
145 147 {
146 148 #if defined(__sparc)
147 149 struct {
148 150 int sjs_flags;
149 151 greg_t sjs_sp;
150 152 greg_t sjs_pc;
151 153 greg_t sjs_fp;
152 154 greg_t sjs_i7;
153 155 ucontext_t *sjs_uclink;
154 156 ulong_t sjs_pad[_JBLEN - 6];
155 157 sigset_t sjs_sigmask;
156 158 #if defined(_LP64)
157 159 greg_t sjs_asi;
158 160 greg_t sjs_fprs;
159 161 #endif
160 162 stack_t sjs_stack;
161 163 } s;
162 164
163 165 if (argc != 0)
164 166 return (DCMD_USAGE);
165 167
166 168 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
167 169 mdb_warn("failed to read sigjmp_buf at %p", addr);
168 170 return (DCMD_ERR);
169 171 }
170 172
171 173 mdb_printf(" flags = 0x%x\n", s.sjs_flags);
172 174 mdb_printf(" %%sp = 0x%lx %lA\n", s.sjs_sp, s.sjs_sp);
173 175 mdb_printf(" %%pc = 0x%lx %lA\n", s.sjs_pc, s.sjs_pc);
174 176 mdb_printf(" %%fp = 0x%lx %lA\n", s.sjs_fp, s.sjs_fp);
175 177 mdb_printf(" %%i7 = 0x%lx %lA\n", s.sjs_i7, s.sjs_i7);
176 178 mdb_printf(" uclink = %p\n", s.sjs_uclink);
177 179 mdb_printf(" sigset = 0x%08x 0x%08x 0x%08x 0x%08x\n",
178 180 s.sjs_sigmask.__sigbits[0], s.sjs_sigmask.__sigbits[1],
179 181 s.sjs_sigmask.__sigbits[2], s.sjs_sigmask.__sigbits[3]);
180 182 #if defined(_LP64)
181 183 mdb_printf(" %%asi = 0x%lx\n", s.sjs_asi);
182 184 mdb_printf(" %%fprs = 0x%lx\n", s.sjs_fprs);
183 185 #endif
184 186 mdb_printf(" stack = sp 0x%p size 0x%lx flags %s\n",
185 187 s.sjs_stack.ss_sp, s.sjs_stack.ss_size, stack_flags(&s.sjs_stack));
186 188
187 189 return (DCMD_OK);
188 190
189 191 #elif defined(__i386) || defined(__amd64)
190 192 return (d_ucontext(addr, flags, argc, argv));
191 193 #endif
192 194 }
193 195
194 196 /*ARGSUSED*/
195 197 static int
196 198 d_siginfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
197 199 {
198 200 static const char *const msname[] = {
199 201 "USER", "SYSTEM", "TRAP", "TFAULT", "DFAULT", "KFAULT",
200 202 "USER_LOCK", "SLEEP", "WAIT_CPU", "STOPPED"
201 203 };
202 204
203 205 char signame[SIG2STR_MAX];
204 206 siginfo_t si;
205 207 int i;
206 208
207 209 if (argc != 0)
208 210 return (DCMD_USAGE);
209 211
210 212 if (mdb_vread(&si, sizeof (si), addr) != sizeof (si)) {
211 213 mdb_warn("failed to read siginfo at %p", addr);
212 214 return (DCMD_ERR);
213 215 }
214 216
215 217 if (sig2str(si.si_signo, signame) == -1)
216 218 (void) strcpy(signame, "unknown");
217 219
218 220 mdb_printf(" signal %5d (%s)\n", si.si_signo, signame);
219 221 mdb_printf(" code %5d (", si.si_code);
220 222
221 223 switch (si.si_code) {
222 224 case SI_NOINFO:
223 225 mdb_printf("no info");
224 226 break;
225 227 case SI_DTRACE:
226 228 mdb_printf("from DTrace raise() action");
227 229 break;
228 230 case SI_RCTL:
229 231 mdb_printf("from rctl action");
230 232 break;
231 233 case SI_USER:
232 234 mdb_printf("user generated via kill");
233 235 break;
234 236 case SI_LWP:
235 237 mdb_printf("user generated via lwp_kill");
236 238 break;
237 239 case SI_QUEUE:
238 240 mdb_printf("user generated via sigqueue");
239 241 break;
240 242 case SI_TIMER:
241 243 mdb_printf("from timer expiration");
242 244 break;
243 245 case SI_ASYNCIO:
244 246 mdb_printf("from async i/o completion");
245 247 break;
246 248 case SI_MESGQ:
247 249 mdb_printf("from message arrival");
248 250 break;
249 251 default:
250 252 if (SI_FROMUSER(&si))
251 253 mdb_printf("from user process");
252 254 else
253 255 mdb_printf("from kernel");
254 256 }
255 257
256 258 mdb_printf(")\n errno %5d (%s)\n",
257 259 si.si_errno, strerror(si.si_errno));
258 260
259 261 if (si.si_code == SI_USER || si.si_code == SI_QUEUE) {
260 262 mdb_printf(" signal sent from PID %d (uid %d)\n",
261 263 si.si_pid, si.si_uid);
262 264 }
263 265
264 266 if (si.si_code == SI_QUEUE) {
265 267 mdb_printf(" signal value = 0t%d / %p\n",
266 268 si.si_value.sival_int, si.si_value.sival_ptr);
267 269 }
268 270
269 271 switch (si.si_signo) {
270 272 case SIGCLD:
271 273 mdb_printf(" signal sent from child PID %d (uid %d)\n",
272 274 si.si_pid, si.si_uid);
273 275 mdb_printf(" usr time = 0t%ld ticks, sys time = 0t%ld ticks\n",
274 276 si.si_utime, si.si_stime);
275 277 mdb_printf(" wait status = 0x%x\n", si.si_status);
276 278 break;
277 279
278 280 case SIGSEGV:
279 281 case SIGBUS:
280 282 case SIGILL:
281 283 case SIGTRAP:
282 284 case SIGFPE:
283 285 mdb_printf(" fault address = 0x%p\n trapno = %d\n",
284 286 si.si_addr, si.si_trapno);
285 287 mdb_printf(" instruction address = 0x%p %lA\n",
286 288 si.si_pc, si.si_pc);
287 289 break;
288 290
289 291 case SIGPOLL:
290 292 case SIGXFSZ:
291 293 mdb_printf(" fd = %d band = 0x%lx\n",
292 294 si.si_fd, si.si_band);
293 295 break;
294 296
295 297 case SIGPROF:
296 298 mdb_printf(" last fault address = 0x%p fault type = %d\n",
297 299 si.si_faddr, si.si_fault);
298 300 mdb_printf(" timestamp = 0t%ld sec 0t%ld nsec\n",
299 301 si.si_tstamp.tv_sec, si.si_tstamp.tv_nsec);
300 302
301 303 if (si.__data.__prof.__syscall != 0) {
302 304 mdb_printf(" system call %d (", si.si_syscall);
303 305 if (si.si_nsysarg > 0) {
304 306 mdb_printf("%lx", si.si_sysarg[0]);
305 307 for (i = 1; i < si.si_nsysarg; i++)
306 308 mdb_printf(", %lx", si.si_sysarg[i]);
307 309 }
308 310 mdb_printf(" )\n");
309 311 }
310 312
311 313 for (i = 0; i < sizeof (msname) / sizeof (msname[0]); i++) {
312 314 mdb_printf(" mstate[\"%s\"] = %d\n",
313 315 msname[i], si.si_mstate[i]);
314 316 }
315 317 break;
316 318 }
317 319
318 320 return (DCMD_OK);
319 321 }
320 322
321 323 static int
322 324 uc_walk_step(mdb_walk_state_t *wsp)
323 325 {
324 326 uintptr_t addr = wsp->walk_addr;
325 327 ucontext_t uc;
326 328
327 329 if (addr == NULL)
328 330 return (WALK_DONE);
329 331
330 332 if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
331 333 mdb_warn("failed to read ucontext at %p", addr);
332 334 return (WALK_ERR);
333 335 }
334 336
335 337 wsp->walk_addr = (uintptr_t)uc.uc_link;
336 338 return (wsp->walk_callback(addr, &uc, wsp->walk_cbdata));
337 339 }
338 340
339 341 static int
340 342 oldc_walk_init(mdb_walk_state_t *wsp)
341 343 {
342 344 ssize_t nbytes = mdb_get_xdata("lwpstatus", NULL, 0);
343 345
344 346 if (nbytes <= 0) {
345 347 mdb_warn("lwpstatus information not available");
346 348 return (WALK_ERR);
347 349 }
348 350
349 351 if (wsp->walk_addr != NULL) {
350 352 mdb_warn("walker only supports global walk\n");
351 353 return (WALK_ERR);
352 354 }
353 355
354 356 wsp->walk_addr = nbytes; /* Use walk_addr to track size */
355 357 wsp->walk_data = mdb_alloc(nbytes, UM_SLEEP);
356 358
357 359 if (mdb_get_xdata("lwpstatus", wsp->walk_data, nbytes) != nbytes) {
358 360 mdb_warn("failed to read lwpstatus information");
359 361 mdb_free(wsp->walk_data, nbytes);
360 362 return (WALK_ERR);
361 363 }
362 364
363 365 wsp->walk_arg = wsp->walk_data; /* Use walk_arg to track pointer */
364 366 return (WALK_NEXT);
365 367 }
366 368
367 369 static int
368 370 oldc_walk_step(mdb_walk_state_t *wsp)
369 371 {
370 372 const lwpstatus_t *lsp, *end;
371 373
372 374 end = (const lwpstatus_t *)((uintptr_t)wsp->walk_data + wsp->walk_addr);
373 375 lsp = wsp->walk_arg;
374 376
375 377 wsp->walk_arg = (void *)(lsp + 1);
376 378
377 379 if (lsp < end) {
378 380 uintptr_t addr = lsp->pr_oldcontext;
379 381 ucontext_t uc;
380 382
381 383 if (addr == NULL)
382 384 return (WALK_NEXT);
383 385
384 386 if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
385 387 mdb_warn("failed to read ucontext at %p", addr);
386 388 return (WALK_NEXT);
387 389 }
388 390
389 391 return (wsp->walk_callback(addr, &uc, wsp->walk_cbdata));
390 392 }
391 393
392 394 return (WALK_DONE);
393 395 }
394 396
395 397 static void
396 398 oldc_walk_fini(mdb_walk_state_t *wsp)
397 399 {
398 400 mdb_free(wsp->walk_data, wsp->walk_addr); /* walk_addr has size */
399 401 }
400 402
401 403 /*
402 404 * ==================== threads ==========================
403 405 * These are the interfaces that used to require libthread.
404 406 * Now, libthread has been folded into libc.
405 407 * =======================================================
406 408 */
407 409
408 410 /*
409 411 * prt_addr() is called up to three times to generate arguments for
410 412 * one call to mdb_printf(). We must return at least three different
411 413 * pointers to static storage for consecutive calls to prt_addr().
412 414 */
413 415 static const char *
414 416 prt_addr(void *addr, int pad)
415 417 {
416 418 static char buffer[4][24];
417 419 static int ix = 0;
418 420 char *buf;
419 421
420 422 if (ix == 4) /* use buffers in sequence: 0, 1, 2, 3 */
421 423 ix = 0;
422 424 buf = buffer[ix++];
423 425 if (addr == NULL)
424 426 return (pad? "<NULL> " : "<NULL>");
425 427 else {
426 428 #ifdef _LP64
427 429 (void) mdb_snprintf(buf, sizeof (buffer[0]), "0x%016lx", addr);
428 430 if (pad)
429 431 (void) strcpy(buf + 18, " ");
430 432 #else
431 433 (void) mdb_snprintf(buf, sizeof (buffer[0]), "0x%08lx", addr);
432 434 if (pad)
433 435 (void) strcpy(buf + 10, " ");
434 436 #endif /* _LP64 */
435 437 return (buf);
436 438 }
437 439 }
438 440
439 441 #define HD(str) mdb_printf(" " str "\n")
440 442 #define OFFSTR "+0x%-7lx "
441 443 #define OFFSET(member) ((size_t)OFFSETOF(ulwp_t, member))
442 444
443 445 /*ARGSUSED*/
444 446 static int
445 447 d_ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
446 448 {
447 449 ulwp_t ulwp;
448 450
449 451 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
450 452 return (DCMD_USAGE);
451 453
452 454 if (mdb_vread(&ulwp, sizeof (ulwp), addr) != sizeof (ulwp) &&
453 455 (bzero(&ulwp, sizeof (ulwp)),
454 456 mdb_vread(&ulwp, REPLACEMENT_SIZE, addr)) != REPLACEMENT_SIZE) {
455 457 mdb_warn("failed to read ulwp at 0x%p", addr);
456 458 return (DCMD_ERR);
457 459 }
458 460
459 461 mdb_printf("%#a\n", addr);
460 462
461 463 HD("self uberdata");
462 464 mdb_printf(OFFSTR "%s %s\n",
463 465 OFFSET(ul_self),
464 466 prt_addr(ulwp.ul_self, 1),
465 467 prt_addr(ulwp.ul_uberdata, 0));
466 468
467 469 HD("tlsent ntlsent");
468 470 mdb_printf(OFFSTR "%s %ld\n",
469 471 OFFSET(ul_tlsent),
470 472 prt_addr(ulwp.ul_tlsent, 1),
471 473 ulwp.ul_ntlsent);
472 474
473 475 HD("forw back next");
474 476 mdb_printf(OFFSTR "%s %s %s\n",
475 477 OFFSET(ul_forw),
476 478 prt_addr(ulwp.ul_forw, 1),
477 479 prt_addr(ulwp.ul_back, 1),
478 480 prt_addr(ulwp.ul_next, 0));
479 481
480 482 HD("hash rval stk");
481 483 mdb_printf(OFFSTR "%s %s %s\n",
482 484 OFFSET(ul_hash),
483 485 prt_addr(ulwp.ul_hash, 1),
484 486 prt_addr(ulwp.ul_rval, 1),
485 487 prt_addr(ulwp.ul_stk, 0));
486 488
487 489 HD("mapsiz guardsize stktop stksiz");
488 490 mdb_printf(OFFSTR "%-10ld %-10ld %s %ld\n",
489 491 OFFSET(ul_mapsiz),
490 492 ulwp.ul_mapsiz,
491 493 ulwp.ul_guardsize,
492 494 prt_addr((void *)ulwp.ul_stktop, 1),
493 495 ulwp.ul_stksiz);
494 496
495 497 HD("ustack.ss_sp ustack.ss_size ustack.ss_flags");
496 498 mdb_printf(OFFSTR "%s %-21ld %s\n",
497 499 OFFSET(ul_ustack.ss_sp),
498 500 prt_addr(ulwp.ul_ustack.ss_sp, 1),
499 501 ulwp.ul_ustack.ss_size,
500 502 stack_flags(&ulwp.ul_ustack));
501 503
502 504 HD("ix lwpid pri epri policy cid");
503 505 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
504 506 OFFSET(ul_ix),
505 507 ulwp.ul_ix,
506 508 ulwp.ul_lwpid,
507 509 ulwp.ul_pri,
508 510 ulwp.ul_epri,
509 511 ulwp.ul_policy,
510 512 ulwp.ul_cid);
511 513
512 514 HD("cursig pleasestop stop signalled dead unwind");
513 515 mdb_printf(OFFSTR "%-10d ",
514 516 OFFSET(ul_cursig),
515 517 ulwp.ul_cursig);
516 518 mdb_printf(ulwp.ul_pleasestop? "0x%-8x " : "%-10d ",
517 519 ulwp.ul_pleasestop);
518 520 mdb_printf(ulwp.ul_stop? "0x%-8x " : "%-10d ",
519 521 ulwp.ul_stop);
520 522 mdb_printf("%-10d %-10d %d\n",
521 523 ulwp.ul_signalled,
522 524 ulwp.ul_dead,
523 525 ulwp.ul_unwind);
524 526
525 527 HD("detached writer stopping can'prolog preempt savpreempt");
526 528 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
527 529 OFFSET(ul_detached),
528 530 ulwp.ul_detached,
529 531 ulwp.ul_writer,
530 532 ulwp.ul_stopping,
531 533 ulwp.ul_cancel_prologue,
532 534 ulwp.ul_preempt,
533 535 ulwp.ul_savpreempt);
534 536
535 537 HD("sigsuspend main fork primarymap m'spinners d'noreserv");
536 538 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
537 539 OFFSET(ul_sigsuspend),
538 540 ulwp.ul_sigsuspend,
539 541 ulwp.ul_main,
540 542 ulwp.ul_fork,
541 543 ulwp.ul_primarymap,
542 544 ulwp.ul_max_spinners,
543 545 ulwp.ul_door_noreserve);
544 546
545 547 HD("queue_fifo c'w'defer e'detect' async_safe rt rtqueued");
546 548 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
547 549 OFFSET(ul_queue_fifo),
548 550 ulwp.ul_queue_fifo,
549 551 ulwp.ul_cond_wait_defer,
550 552 ulwp.ul_error_detection,
551 553 ulwp.ul_async_safe,
552 554 ulwp.ul_rt,
553 555 ulwp.ul_rtqueued);
554 556
555 557 HD("misaligned adapt'spin queue_spin critical sigdefer vfork");
556 558 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
557 559 OFFSET(ul_misaligned),
558 560 ulwp.ul_misaligned,
559 561 ulwp.ul_adaptive_spin,
560 562 ulwp.ul_queue_spin,
561 563 ulwp.ul_critical,
562 564 ulwp.ul_sigdefer,
563 565 ulwp.ul_vfork);
564 566
565 567 HD("cancelable c'pending c'disabled c'async save_async mutator");
566 568 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
567 569 OFFSET(ul_cancelable),
568 570 ulwp.ul_cancelable,
569 571 ulwp.ul_cancel_pending,
570 572 ulwp.ul_cancel_disabled,
571 573 ulwp.ul_cancel_async,
572 574 ulwp.ul_save_async,
573 575 ulwp.ul_mutator);
574 576
575 577 HD("created replace nocancel errno errnop");
576 578 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %s\n",
577 579 OFFSET(ul_created),
578 580 ulwp.ul_created,
579 581 ulwp.ul_replace,
580 582 ulwp.ul_nocancel,
581 583 ulwp.ul_errno,
582 584 prt_addr(ulwp.ul_errnop, 0));
583 585
584 586 HD("clnup_hdr schedctl_called schedctl");
585 587 mdb_printf(OFFSTR "%s %s %s\n",
586 588 OFFSET(ul_clnup_hdr),
587 589 prt_addr(ulwp.ul_clnup_hdr, 1),
588 590 prt_addr(ulwp.ul_schedctl_called, 1),
589 591 prt_addr((void *)ulwp.ul_schedctl, 0));
590 592
591 593 HD("bindflags libc_locks stsd &ftsd");
592 594 mdb_printf(OFFSTR,
593 595 OFFSET(ul_bindflags));
594 596 mdb_printf(ulwp.ul_bindflags? "0x%-8x " : "%-10d ",
595 597 ulwp.ul_bindflags);
596 598 mdb_printf("%-10d ", ulwp.ul_libc_locks);
597 599 mdb_printf("%s %s\n",
598 600 prt_addr(ulwp.ul_stsd, 1),
599 601 prt_addr((void *)(addr + OFFSET(ul_ftsd[0])), 0));
600 602
601 603 HD("eventmask[0..1] eventnum eventdata");
602 604 mdb_printf(OFFSTR "0x%08x 0x%08x %-21d %s\n",
603 605 OFFSET(ul_td_evbuf.eventmask.event_bits[0]),
604 606 ulwp.ul_td_evbuf.eventmask.event_bits[0],
605 607 ulwp.ul_td_evbuf.eventmask.event_bits[1],
606 608 ulwp.ul_td_evbuf.eventnum,
607 609 prt_addr(ulwp.ul_td_evbuf.eventdata, 0));
608 610
609 611 HD("td'enable sync'reg qtype cv_wake rtld usropts");
610 612 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d ",
611 613 OFFSET(ul_td_events_enable),
612 614 ulwp.ul_td_events_enable,
613 615 ulwp.ul_sync_obj_reg,
614 616 ulwp.ul_qtype,
615 617 ulwp.ul_cv_wake,
616 618 ulwp.ul_rtld);
617 619 mdb_printf(ulwp.ul_usropts? "0x%x\n" : "%d\n",
618 620 ulwp.ul_usropts);
619 621
620 622 HD("startpc startarg wchan");
621 623 mdb_printf(OFFSTR "%s %s %s\n",
622 624 OFFSET(ul_startpc),
623 625 prt_addr((void *)ulwp.ul_startpc, 1),
624 626 prt_addr(ulwp.ul_startarg, 1),
625 627 prt_addr(ulwp.ul_wchan, 0));
626 628
627 629 HD("link sleepq cvmutex");
628 630 mdb_printf(OFFSTR "%s %s %s\n",
629 631 OFFSET(ul_link),
630 632 prt_addr(ulwp.ul_link, 1),
631 633 prt_addr(ulwp.ul_sleepq, 1),
632 634 prt_addr(ulwp.ul_cvmutex, 0));
633 635
634 636 HD("mxchain save_state");
635 637 mdb_printf(OFFSTR "%s %d\n",
636 638 OFFSET(ul_mxchain),
637 639 prt_addr(ulwp.ul_mxchain, 1),
638 640 ulwp.ul_save_state);
639 641
640 642 HD("rdlockcnt rd_rwlock rd_count");
641 643 mdb_printf(OFFSTR "%-21d %s %d\n",
642 644 OFFSET(ul_rdlockcnt),
643 645 ulwp.ul_rdlockcnt,
644 646 prt_addr(ulwp.ul_readlock.single.rd_rwlock, 1),
645 647 ulwp.ul_readlock.single.rd_count);
646 648
647 649 HD("heldlockcnt heldlocks tpdp");
648 650 mdb_printf(OFFSTR "%-21d %s %s\n",
649 651 OFFSET(ul_heldlockcnt),
650 652 ulwp.ul_heldlockcnt,
651 653 prt_addr(ulwp.ul_heldlocks.single, 1),
652 654 prt_addr(ulwp.ul_tpdp, 0));
653 655
654 656 HD("siglink s'l'spin s'l'spin2 s'l'sleep s'l'wakeup");
655 657 mdb_printf(OFFSTR "%s %-10d %-10d %-10d %d\n",
656 658 OFFSET(ul_siglink),
657 659 prt_addr(ulwp.ul_siglink, 1),
658 660 ulwp.ul_spin_lock_spin,
659 661 ulwp.ul_spin_lock_spin2,
660 662 ulwp.ul_spin_lock_sleep,
661 663 ulwp.ul_spin_lock_wakeup);
662 664
663 665 HD("&queue_root rtclassid pilocks");
664 666 mdb_printf(OFFSTR "%s %-10d %d\n",
665 667 OFFSET(ul_queue_root),
666 668 prt_addr((void *)(addr + OFFSET(ul_queue_root)), 1),
667 669 ulwp.ul_rtclassid,
668 670 ulwp.ul_pilocks);
669 671
670 672 /*
671 673 * The remainder of the ulwp_t structure
672 674 * is invalid if this is a replacement.
673 675 */
674 676 if (ulwp.ul_replace)
675 677 return (DCMD_OK);
676 678
677 679 HD("sigmask[0..3]");
678 680 mdb_printf(OFFSTR "0x%08x 0x%08x 0x%08x 0x%08x\n",
679 681 OFFSET(ul_sigmask.__sigbits[0]),
680 682 ulwp.ul_sigmask.__sigbits[0],
681 683 ulwp.ul_sigmask.__sigbits[1],
682 684 ulwp.ul_sigmask.__sigbits[2],
683 685 ulwp.ul_sigmask.__sigbits[3]);
684 686
685 687 HD("tmpmask[0..3]");
686 688 mdb_printf(OFFSTR "0x%08x 0x%08x 0x%08x 0x%08x\n",
687 689 OFFSET(ul_tmpmask.__sigbits[0]),
688 690 ulwp.ul_tmpmask.__sigbits[0],
689 691 ulwp.ul_tmpmask.__sigbits[1],
690 692 ulwp.ul_tmpmask.__sigbits[2],
691 693 ulwp.ul_tmpmask.__sigbits[3]);
692 694
693 695 HD("&siginfo &spinlock &fpuenv");
694 696 mdb_printf(OFFSTR "%s %s %s\n",
695 697 OFFSET(ul_siginfo),
696 698 prt_addr((void *)(addr + OFFSET(ul_siginfo)), 1),
697 699 prt_addr((void *)(addr + OFFSET(ul_spinlock)), 1),
698 700 prt_addr((void *)(addr + OFFSET(ul_fpuenv)), 0));
699 701
700 702 HD("tmem.size &tmem.roots");
701 703 mdb_printf(OFFSTR "%-21H %s\n",
702 704 OFFSET(ul_tmem),
703 705 ulwp.ul_tmem.tm_size,
704 706 prt_addr((void *)(addr + OFFSET(ul_tmem) + sizeof (size_t)), 0));
705 707
706 708 return (DCMD_OK);
707 709 }
708 710
709 711 /*
710 712 * Get the address of the unique uberdata_t structure.
711 713 */
712 714 static uintptr_t
713 715 uberdata_addr(void)
714 716 {
715 717 uintptr_t uaddr;
716 718 uintptr_t addr;
717 719 GElf_Sym sym;
718 720
719 721 if (mdb_lookup_by_obj("libc.so.1", "_tdb_bootstrap", &sym) != 0) {
720 722 mdb_warn("cannot find libc.so.1`_tdb_bootstrap");
721 723 return (NULL);
722 724 }
723 725 if (mdb_vread(&addr, sizeof (addr), sym.st_value) == sizeof (addr) &&
724 726 addr != NULL &&
725 727 mdb_vread(&uaddr, sizeof (uaddr), addr) == sizeof (uaddr) &&
726 728 uaddr != NULL) {
727 729 return (uaddr);
728 730 }
729 731 if (mdb_lookup_by_obj("libc.so.1", "_uberdata", &sym) != 0) {
730 732 mdb_warn("cannot find libc.so.1`_uberdata");
731 733 return (NULL);
732 734 }
733 735 return ((uintptr_t)sym.st_value);
734 736 }
735 737
736 738 #undef OFFSET
737 739 #define OFFSET(member) ((size_t)OFFSETOF(uberdata_t, member))
738 740
739 741 /*ARGSUSED*/
740 742 static int
741 743 d_uberdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
742 744 {
743 745 uberdata_t uberdata;
744 746 int i;
745 747
746 748 if (argc != 0)
747 749 return (DCMD_USAGE);
748 750 if (!(flags & DCMD_ADDRSPEC) && (addr = uberdata_addr()) == NULL)
749 751 return (DCMD_ERR);
750 752
751 753 if (mdb_vread(&uberdata, sizeof (uberdata), addr) !=
752 754 sizeof (uberdata)) {
753 755 mdb_warn("failed to read uberdata at 0x%p", addr);
754 756 return (DCMD_ERR);
755 757 }
756 758
757 759 mdb_printf("%#a\n", addr);
758 760
759 761 HD("&link_lock &ld_lock &fork_lock");
760 762 mdb_printf(OFFSTR "%s %s %s\n",
761 763 OFFSET(link_lock),
762 764 prt_addr((void *)(addr + OFFSET(link_lock)), 1),
763 765 prt_addr((void *)(addr + OFFSET(ld_lock)), 1),
764 766 prt_addr((void *)(addr + OFFSET(fork_lock)), 0));
765 767
766 768 HD("&atfork_lock &callout_lock &tdb_hash_lock");
767 769 mdb_printf(OFFSTR "%s %s %s\n",
768 770 OFFSET(atfork_lock),
769 771 prt_addr((void *)(addr + OFFSET(atfork_lock)), 1),
770 772 prt_addr((void *)(addr + OFFSET(callout_lock)), 1),
771 773 prt_addr((void *)(addr + OFFSET(tdb_hash_lock)), 0));
772 774
773 775 HD("&tdb_hash_lock_stats &siguaction[0]");
774 776 mdb_printf(OFFSTR "%s %s\n",
775 777 OFFSET(tdb_hash_lock_stats),
776 778 prt_addr((void *)(addr + OFFSET(tdb_hash_lock_stats)), 1),
777 779 prt_addr((void *)(addr + OFFSET(siguaction)), 0));
778 780
779 781 HD("&bucket free_list chunks");
780 782 for (i = 0; i < NBUCKETS; i++) {
781 783 mdb_printf(OFFSTR "%s %s %ld\n",
782 784 OFFSET(bucket[i]),
783 785 prt_addr((void *)(addr + OFFSET(bucket[i])), 1),
784 786 prt_addr(uberdata.bucket[i].free_list, 1),
785 787 uberdata.bucket[i].chunks);
786 788 }
787 789
788 790 HD("&atexit_root head exit_frame_monitor");
789 791 mdb_printf(OFFSTR "%s %s %s\n",
790 792 OFFSET(atexit_root),
791 793 prt_addr((void *)(addr + OFFSET(atexit_root.exitfns_lock)), 1),
792 794 prt_addr(uberdata.atexit_root.head, 1),
793 795 prt_addr(uberdata.atexit_root.exit_frame_monitor, 0));
794 796
795 797 HD("&quickexit_root head");
796 798 mdb_printf(OFFSTR "%s %s\n",
797 799 OFFSET(quickexit_root),
798 800 prt_addr((void *)(addr + OFFSET(quickexit_root.exitfns_lock)), 1),
799 801 prt_addr(uberdata.quickexit_root.head, 0));
800 802
801 803
802 804 HD("&tsd_metadata tsdm_nkeys tsdm_nused tsdm_destro");
803 805 mdb_printf(OFFSTR "%s %-10d %-10d %s\n",
804 806 OFFSET(tsd_metadata),
805 807 prt_addr((void *)(addr + OFFSET(tsd_metadata.tsdm_lock)), 1),
806 808 uberdata.tsd_metadata.tsdm_nkeys,
807 809 uberdata.tsd_metadata.tsdm_nused,
808 810 prt_addr((void *)uberdata.tsd_metadata.tsdm_destro, 0));
809 811
810 812 HD("&tls_metadata tls_modinfo.data tls_modinfo.size");
811 813 mdb_printf(OFFSTR "%s %s %ld\n",
812 814 OFFSET(tls_metadata),
813 815 prt_addr((void *)(addr + OFFSET(tls_metadata.tls_lock)), 1),
814 816 prt_addr(uberdata.tls_metadata.tls_modinfo.tls_data, 1),
815 817 uberdata.tls_metadata.tls_modinfo.tls_size);
816 818
817 819 HD(" static_tls.data static_tls.size");
818 820 mdb_printf(OFFSTR "%s %s %ld\n",
819 821 OFFSET(tls_metadata.static_tls),
820 822 " ",
821 823 prt_addr(uberdata.tls_metadata.static_tls.tls_data, 1),
822 824 uberdata.tls_metadata.static_tls.tls_size);
823 825
824 826 HD("primary_ma bucket_ini uflags.mt uflags.pad uflags.trs uflags.ted");
825 827 mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
826 828 OFFSET(primary_map),
827 829 uberdata.primary_map,
828 830 uberdata.bucket_init,
829 831 uberdata.uberflags.uf_x.x_mt,
830 832 uberdata.uberflags.uf_x.x_pad,
831 833 uberdata.uberflags.uf_x.x_tdb_register_sync,
832 834 uberdata.uberflags.uf_x.x_thread_error_detection);
833 835
834 836 HD("queue_head thr_hash_table hash_size hash_mask");
835 837 mdb_printf(OFFSTR "%s %s %-10d 0x%x\n",
836 838 OFFSET(queue_head),
837 839 prt_addr(uberdata.queue_head, 1),
838 840 prt_addr(uberdata.thr_hash_table, 1),
|
↓ open down ↓ |
691 lines elided |
↑ open up ↑ |
839 841 uberdata.hash_size,
840 842 uberdata.hash_mask);
841 843
842 844 HD("ulwp_one all_lwps all_zombies");
843 845 mdb_printf(OFFSTR "%s %s %s\n",
844 846 OFFSET(ulwp_one),
845 847 prt_addr(uberdata.ulwp_one, 1),
846 848 prt_addr(uberdata.all_lwps, 1),
847 849 prt_addr(uberdata.all_zombies, 0));
848 850
849 - HD("nthreads nzombies ndaemons pid sigacthandler");
850 - mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %s\n",
851 + HD("nthreads nzombies ndaemons pid");
852 + mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d\n",
851 853 OFFSET(nthreads),
852 854 uberdata.nthreads,
853 855 uberdata.nzombies,
854 856 uberdata.ndaemons,
855 - (int)uberdata.pid,
856 - prt_addr((void *)uberdata.sigacthandler, 0));
857 + (int)uberdata.pid);
857 858
859 + HD("sigacthandler setctxt");
860 + mdb_printf(OFFSTR "%s %s\n",
861 + OFFSET(sigacthandler),
862 + prt_addr((void *)uberdata.sigacthandler, 1),
863 + prt_addr((void *)uberdata.setctxt, 1));
864 +
858 865 HD("lwp_stacks lwp_laststack nfreestack stk_cache");
859 866 mdb_printf(OFFSTR "%s %s %-10d %d\n",
860 867 OFFSET(lwp_stacks),
861 868 prt_addr(uberdata.lwp_stacks, 1),
862 869 prt_addr(uberdata.lwp_laststack, 1),
863 870 uberdata.nfreestack,
864 871 uberdata.thread_stack_cache);
865 872
866 873 HD("ulwp_freelist ulwp_lastfree ulwp_replace_free");
867 874 mdb_printf(OFFSTR "%s %s %s\n",
868 875 OFFSET(ulwp_freelist),
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
869 876 prt_addr(uberdata.ulwp_freelist, 1),
870 877 prt_addr(uberdata.ulwp_lastfree, 1),
871 878 prt_addr(uberdata.ulwp_replace_free, 0));
872 879
873 880 HD("ulwp_replace_last atforklist");
874 881 mdb_printf(OFFSTR "%s %s\n",
875 882 OFFSET(ulwp_replace_last),
876 883 prt_addr(uberdata.ulwp_replace_last, 1),
877 884 prt_addr(uberdata.atforklist, 0));
878 885
879 - HD("robustlocks robustlist progname");
880 - mdb_printf(OFFSTR "%s %s %s\n",
886 + HD("robustlocks robustlist");
887 + mdb_printf(OFFSTR "%s %s\n",
881 888 OFFSET(robustlocks),
882 889 prt_addr(uberdata.robustlocks, 1),
883 - prt_addr(uberdata.robustlist, 1),
884 - prt_addr(uberdata.progname, 0));
890 + prt_addr(uberdata.robustlist, 1));
885 891
892 + HD("progname ub_broot");
893 + mdb_printf(OFFSTR "%s %s\n",
894 + OFFSET(progname),
895 + prt_addr(uberdata.progname, 1),
896 + prt_addr(uberdata.ub_broot, 1));
897 +
886 898 HD("tdb_bootstrap tdb_sync_addr_hash tdb_'count tdb_'fail");
887 899 mdb_printf(OFFSTR "%s %s %-10d %d\n",
888 900 OFFSET(tdb_bootstrap),
889 901 prt_addr(uberdata.tdb_bootstrap, 1),
890 902 prt_addr(uberdata.tdb.tdb_sync_addr_hash, 1),
891 903 uberdata.tdb.tdb_register_count,
892 904 uberdata.tdb.tdb_hash_alloc_failed);
893 905
894 906 HD("tdb_sync_addr_free tdb_sync_addr_last tdb_sync_alloc");
895 907 mdb_printf(OFFSTR "%s %s %ld\n",
896 908 OFFSET(tdb.tdb_sync_addr_free),
897 909 prt_addr(uberdata.tdb.tdb_sync_addr_free, 1),
898 910 prt_addr(uberdata.tdb.tdb_sync_addr_last, 1),
899 911 uberdata.tdb.tdb_sync_alloc);
900 912
901 913 HD("tdb_ev_global_mask tdb_events");
902 914 mdb_printf(OFFSTR "0x%08x 0x%08x %s\n",
903 915 OFFSET(tdb.tdb_ev_global_mask),
904 916 uberdata.tdb.tdb_ev_global_mask.event_bits[0],
905 917 uberdata.tdb.tdb_ev_global_mask.event_bits[1],
906 918 prt_addr((void *)uberdata.tdb.tdb_events, 0));
907 919
908 920 return (DCMD_OK);
909 921 }
910 922
911 923 static int
912 924 ulwp_walk_init(mdb_walk_state_t *wsp)
913 925 {
914 926 uintptr_t addr = wsp->walk_addr;
915 927 uintptr_t uber_addr;
916 928
917 929 if (addr == NULL &&
918 930 ((uber_addr = uberdata_addr()) == NULL ||
919 931 mdb_vread(&addr, sizeof (addr),
920 932 uber_addr + OFFSETOF(uberdata_t, all_lwps))
921 933 != sizeof (addr))) {
922 934 mdb_warn("cannot find 'uberdata.all_lwps'");
923 935 return (WALK_ERR);
924 936 }
925 937 if (addr == NULL)
926 938 return (WALK_DONE);
927 939 wsp->walk_addr = addr;
928 940 wsp->walk_data = (void *)addr;
929 941 return (WALK_NEXT);
930 942 }
931 943
932 944 static int
933 945 ulwp_walk_step(mdb_walk_state_t *wsp)
934 946 {
935 947 uintptr_t addr = wsp->walk_addr;
936 948 ulwp_t ulwp;
937 949
938 950 if (addr == NULL)
939 951 return (WALK_DONE);
940 952 if (mdb_vread(&ulwp, sizeof (ulwp), addr) != sizeof (ulwp) &&
941 953 (bzero(&ulwp, sizeof (ulwp)),
942 954 mdb_vread(&ulwp, REPLACEMENT_SIZE, addr)) != REPLACEMENT_SIZE) {
943 955 mdb_warn("failed to read ulwp at 0x%p", addr);
944 956 return (WALK_ERR);
945 957 }
946 958 /*
947 959 * If we have looped around to the beginning
948 960 * of the circular linked list, we are done.
949 961 */
950 962 if ((wsp->walk_addr = (uintptr_t)ulwp.ul_forw)
951 963 == (uintptr_t)wsp->walk_data)
952 964 wsp->walk_addr = NULL;
953 965 return (wsp->walk_callback(addr, &ulwp, wsp->walk_cbdata));
954 966 }
955 967
956 968 /* Avoid classifying NULL pointers as part of the main stack on x86 */
957 969 #define MIN_STACK_ADDR (0x10000ul)
958 970
959 971 static int
960 972 whatis_walk_ulwp(uintptr_t addr, const ulwp_t *ulwp, mdb_whatis_t *w)
961 973 {
962 974 uintptr_t cur;
963 975 lwpid_t id = ulwp->ul_lwpid;
964 976 uintptr_t top, base, size;
965 977
966 978 while (mdb_whatis_match(w, addr, sizeof (ulwp_t), &cur))
967 979 mdb_whatis_report_object(w, cur, addr,
968 980 "allocated as thread %#r's ulwp_t\n", id);
969 981
970 982 top = (uintptr_t)ulwp->ul_stktop;
971 983 size = ulwp->ul_stksiz;
972 984
973 985 /*
974 986 * The main stack ends up being a little weird, especially if
975 987 * the stack ulimit is unlimited. This tries to take that into
976 988 * account.
977 989 */
978 990 if (size > top)
979 991 size = top;
980 992 if (top > MIN_STACK_ADDR && top - size < MIN_STACK_ADDR)
981 993 size = top - MIN_STACK_ADDR;
982 994
983 995 base = top - size;
984 996
985 997 while (mdb_whatis_match(w, base, size, &cur))
986 998 mdb_whatis_report_address(w, cur, "in [ stack tid=%#r ]\n", id);
987 999
988 1000 if (ulwp->ul_ustack.ss_flags & SS_ONSTACK) {
989 1001 base = (uintptr_t)ulwp->ul_ustack.ss_sp;
990 1002 size = ulwp->ul_ustack.ss_size;
991 1003
992 1004 while (mdb_whatis_match(w, base, size, &cur))
993 1005 mdb_whatis_report_address(w, cur,
994 1006 "in [ altstack tid=%#r ]\n", id);
995 1007 }
996 1008
997 1009 return (WHATIS_WALKRET(w));
998 1010 }
999 1011
1000 1012 /*ARGSUSED*/
1001 1013 static int
1002 1014 whatis_run_ulwps(mdb_whatis_t *w, void *arg)
1003 1015 {
1004 1016 if (mdb_walk("ulwps", (mdb_walk_cb_t)whatis_walk_ulwp, w) == -1) {
1005 1017 mdb_warn("couldn't find ulwps walker");
1006 1018 return (1);
1007 1019 }
1008 1020 return (0);
1009 1021 }
1010 1022
1011 1023 /*
1012 1024 * =======================================================
1013 1025 * End of thread (previously libthread) interfaces.
1014 1026 * ==================== threads ==========================
1015 1027 */
1016 1028
1017 1029 int
1018 1030 stacks_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1019 1031 {
1020 1032 int rval = stacks(addr, flags, argc, argv);
1021 1033
1022 1034 /*
1023 1035 * For the user-level variant of ::stacks, we don't bother caching
1024 1036 * state, as even a very large program is unlikely to compare to the
1025 1037 * kernel in terms of number of threads. (And if you find yourself
1026 1038 * here in anger, frustrated about how long ::stacks is running on
1027 1039 * your galactically complicated zillion-thread program, hopefully
1028 1040 * you will find some solace in the irony. Okay, probably not...)
1029 1041 */
1030 1042 stacks_cleanup(B_TRUE);
1031 1043 return (rval);
1032 1044 }
1033 1045
1034 1046 typedef struct tid2ulwp_walk {
1035 1047 lwpid_t t2u_tid;
1036 1048 uintptr_t t2u_lwp;
1037 1049 boolean_t t2u_found;
1038 1050 } tid2ulwp_walk_t;
1039 1051
1040 1052 /*ARGSUSED*/
1041 1053 static int
1042 1054 tid2ulwp_walk(uintptr_t addr, ulwp_t *ulwp, tid2ulwp_walk_t *t2u)
1043 1055 {
1044 1056 if (ulwp->ul_lwpid == t2u->t2u_tid) {
1045 1057 t2u->t2u_lwp = addr;
1046 1058 t2u->t2u_found = B_TRUE;
1047 1059 return (WALK_DONE);
1048 1060 }
1049 1061
1050 1062 return (WALK_NEXT);
1051 1063 }
1052 1064
1053 1065 static int
1054 1066 tid2ulwp_impl(uintptr_t tid_addr, uintptr_t *ulwp_addrp)
1055 1067 {
1056 1068 tid2ulwp_walk_t t2u;
1057 1069
1058 1070 bzero(&t2u, sizeof (t2u));
1059 1071 t2u.t2u_tid = (lwpid_t)tid_addr;
1060 1072
1061 1073 if (mdb_walk("ulwp", (mdb_walk_cb_t)tid2ulwp_walk, &t2u) != 0) {
1062 1074 mdb_warn("can't walk 'ulwp'");
1063 1075 return (DCMD_ERR);
1064 1076 }
1065 1077
1066 1078 if (!t2u.t2u_found) {
1067 1079 mdb_warn("thread ID %d not found", t2u.t2u_tid);
1068 1080 return (DCMD_ERR);
1069 1081 }
1070 1082 *ulwp_addrp = t2u.t2u_lwp;
1071 1083 return (DCMD_OK);
1072 1084 }
1073 1085
1074 1086 /*ARGSUSED*/
1075 1087 static int
1076 1088 tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1077 1089 {
1078 1090 uintptr_t ulwp_addr;
1079 1091 int error;
1080 1092
1081 1093 if (argc != 0)
1082 1094 return (DCMD_USAGE);
1083 1095
1084 1096 error = tid2ulwp_impl(addr, &ulwp_addr);
1085 1097 if (error == DCMD_OK)
1086 1098 mdb_printf("%p\n", ulwp_addr);
1087 1099 return (error);
1088 1100 }
1089 1101
1090 1102 typedef struct mdb_libc_ulwp {
1091 1103 void *ul_ftsd[TSD_NFAST];
1092 1104 tsd_t *ul_stsd;
1093 1105 } mdb_libc_ulwp_t;
1094 1106
1095 1107 /*
1096 1108 * Map from thread pointer to tsd for given key
1097 1109 */
1098 1110 static int
1099 1111 d_tsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1100 1112 {
1101 1113 mdb_libc_ulwp_t u;
1102 1114 uintptr_t ulwp_addr;
1103 1115 uintptr_t key = NULL;
1104 1116 void *element = NULL;
1105 1117
1106 1118 if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc)
1107 1119 return (DCMD_USAGE);
1108 1120
1109 1121 if (!(flags & DCMD_ADDRSPEC) || key == NULL)
1110 1122 return (DCMD_USAGE);
1111 1123
1112 1124 if (tid2ulwp_impl(addr, &ulwp_addr) != DCMD_OK)
1113 1125 return (DCMD_ERR);
1114 1126
1115 1127 if (mdb_ctf_vread(&u, "ulwp_t", "mdb_libc_ulwp_t", ulwp_addr, 0) == -1)
1116 1128 return (DCMD_ERR);
1117 1129
1118 1130 if (key < TSD_NFAST) {
1119 1131 element = u.ul_ftsd[key];
1120 1132 } else if (u.ul_stsd != NULL) {
1121 1133 uint_t nalloc;
1122 1134 /* tsd_t is a union, so we can't use ctf_vread() on it. */
1123 1135 if (mdb_vread(&nalloc, sizeof (nalloc),
1124 1136 (uintptr_t)&u.ul_stsd->tsd_nalloc) == -1) {
1125 1137 mdb_warn("failed to read tsd_t at %p", u.ul_stsd);
1126 1138 return (DCMD_ERR);
1127 1139 }
1128 1140 if (key < nalloc) {
1129 1141 if (mdb_vread(&element, sizeof (element),
1130 1142 (uintptr_t)&u.ul_stsd->tsd_data[key]) == -1) {
1131 1143 mdb_warn("failed to read tsd_t at %p",
1132 1144 u.ul_stsd);
1133 1145 return (DCMD_ERR);
1134 1146 }
1135 1147 }
1136 1148 }
1137 1149
1138 1150 if (element == NULL && (flags & DCMD_PIPE))
1139 1151 return (DCMD_OK);
1140 1152
1141 1153 mdb_printf("%p\n", element);
1142 1154 return (DCMD_OK);
1143 1155 }
1144 1156
1145 1157 static const mdb_dcmd_t dcmds[] = {
1146 1158 { "jmp_buf", ":", "print jmp_buf contents", d_jmp_buf, NULL },
1147 1159 { "sigjmp_buf", ":", "print sigjmp_buf contents", d_sigjmp_buf, NULL },
1148 1160 { "siginfo", ":", "print siginfo_t structure", d_siginfo, NULL },
1149 1161 { "stacks", "?[-afiv] [-c func] [-C func] [-m module] [-M module] ",
1150 1162 "print unique thread stacks", stacks_dcmd, stacks_help },
1151 1163 { "tid2ulwp", "?", "convert TID to ulwp_t address", tid2ulwp },
1152 1164 { "ucontext", ":", "print ucontext_t structure", d_ucontext, NULL },
1153 1165 { "ulwp", ":", "print ulwp_t structure", d_ulwp, NULL },
1154 1166 { "uberdata", ":", "print uberdata_t structure", d_uberdata, NULL },
1155 1167 { "tsd", ":-k key", "print tsd for this thread", d_tsd, NULL },
1156 1168 { NULL }
1157 1169 };
1158 1170
1159 1171 static const mdb_walker_t walkers[] = {
1160 1172 { "ucontext", "walk ucontext_t uc_link list",
1161 1173 NULL, uc_walk_step, NULL, NULL },
1162 1174 { "oldcontext", "walk per-lwp oldcontext pointers",
1163 1175 oldc_walk_init, oldc_walk_step, oldc_walk_fini, NULL },
1164 1176 { "ulwps", "walk list of ulwp_t pointers",
1165 1177 ulwp_walk_init, ulwp_walk_step, NULL, NULL },
1166 1178 { "ulwp", "walk list of ulwp_t pointers",
1167 1179 ulwp_walk_init, ulwp_walk_step, NULL, NULL },
1168 1180 { NULL }
1169 1181 };
1170 1182
1171 1183 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
1172 1184
1173 1185 const mdb_modinfo_t *
1174 1186 _mdb_init(void)
1175 1187 {
1176 1188 mdb_whatis_register("threads", whatis_run_ulwps, NULL,
1177 1189 WHATIS_PRIO_EARLY, WHATIS_REG_NO_ID);
1178 1190
1179 1191 return (&modinfo);
1180 1192 }
|
↓ open down ↓ |
285 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX