1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2025 Oxide Computer Company
28 */
29
30 /*
31 * Postmortem type identification
32 * ------------------------------
33 *
34 * When debugging kernel memory corruption problems, one often determines that
35 * the corrupted buffer has been erroneously written to by a user of an
36 * adjacent buffer -- determining the specifics of the adjacent buffer can
37 * therefore offer insight into the cause of the corruption. To determine the
38 * type of an arbitrary memory buffer, however, one has historically been
39 * forced to use dcmds ::kgrep and ::whatis in alternating succession; when an
40 * object of known type is finally reached, types can be back-propagated to
41 * determine the type of the unknown object.
42 *
43 * This process is labor-intensive and error-prone. Using CTF data and a
44 * collection of heuristics, we would like to both automate this process and
45 * improve on it.
46 *
47 * We start by constructing the pointer graph. Each node in the graph is
48 * a memory object (either a static object from module data, or a dynamically
49 * allocated memory object); the node's outgoing edges represent pointers from
50 * the object to other memory objects in the system.
51 *
52 * Once the graph is constructed, we start at nodes of known type, and use the
53 * type information to determine the type of each pointer represented by an
54 * outgoing edge. Determining the pointer type allows us to determine the
55 * type of the edge's destination node, and therefore to iteratively continue
56 * the process of type identification. This process works as long as all
57 * pointed-to objects are exactly the size of their inferred types.
58 *
59 * Unfortunately, pointed-to objects are often _not_ the size of the pointed-to
60 * type. This is largely due to three phenomena:
61 *
62 * (a) C makes no distinction between a pointer to a single object and a
63 * pointer to some number of objects of like type.
64 *
65 * (b) C performs no bounds checking on array indexing, allowing declarations
66 * of structures that are implicitly followed by arrays of the type of the
67 * structure's last member. These declarations most often look like:
68 *
69 * typedef struct foo {
70 * int foo_bar;
71 * int foo_baz;
72 * mumble_t foo_mumble[1];
73 * } foo_t;
74 *
75 * When a foo_t is allocated, the size of n - 1 mumble_t's is added to the
76 * size of a foo_t to derive the size of the allocation; this allows for
77 * the n trailing mumble_t's to be referenced from the allocated foo_t
78 * using C's convenient array syntax -- without requiring an additional
79 * memory dereference. ISO C99 calls the last member in such a structure
80 * the "flexible array member" (FAM); we adhere to this terminology.
81 *
82 * (c) It is not uncommon for structures to embed smaller structures, and
83 * to pass pointers to these smaller structures to routines that track
84 * the structures only by the smaller type. This can be thought of as
85 * a sort of crude-but-efficient polymorphism; see e.g., struct seg and
86 * its embedded avl_node_t. It is less common (but by no means unheard
87 * of) for the smaller structures to be used as place holders in data
88 * structures consisting of the larger structure. That is, instead of an
89 * instance of the larger structure being pointed to by the smaller
90 * structure pointer, an instance of the smaller structure is pointed to
91 * the larger structure pointer; see e.g., struct buf and struct hbuf or
92 * struct seg_pcache and struct seg_phash. This construct is particularly
93 * important to identify when the smaller structures are in a contiguous
94 * array (as they are in each of the two examples provided): by examining
95 * only the data structure of larger structures, one would erroneously
96 * assume that the array of the smaller structure is actually an array of
97 * the larger structure.
98 *
99 * Taken together, these three phenomena imply that if we have a pointer to
100 * an object that is larger than the pointed-to type, we don't know if the
101 * object is an array of objects of the pointed-to type, the pointed-to type
102 * followed by an array of that type's last member, or some other larger type
103 * that we haven't yet discovered.
104 *
105 * Differentiating these three situations is the focus of many of the
106 * type graph heuristics. Type graph processing is performed in an initial
107 * pass, four type-determining passes, and a final, post-pass:
108 *
109 * Initial: Graph construction
110 *
111 * The initial pass constructs the nodes from the kmem caches and module data,
112 * and constructs the edges by propagating out from module data. Nodes that
113 * are in module data or known kmem caches (see tg_cachetab[], below) are
114 * marked with their known type. This pass takes the longest amount of
115 * wall-clock time, for it frequently induces I/O to read the postmortem image
116 * into memory from permanent storage.
117 *
118 * pass1: Conservative propagation
119 *
120 * In pass1, we propagate types out from the known nodes, adding types to
121 * nodes' tgn_typelists as they are inferred. Nodes are marked as they are
122 * processed to guarantee halting. We proceed as conservatively as possible
123 * in this pass; if we discover that a node is larger than twice its inferred
124 * type (that is, we've run into one of the three phenomena described above),
125 * we add the inferred type to the node's tgn_typelist, but we don't descend.
126 *
127 * pass2: Array determination
128 *
129 * In pass2, we visit those nodes through which we refused to descend in pass1.
130 * If we find one (and only one) structural interpretation for the object, we
131 * have determined that -- to the best of our knowledge -- we are not seeing
132 * phenomenon (c). To further differentiate (a) from (b), we check if the
133 * structure ends with an array of size one; if it does, we assume that it has
134 * a flexible array member. Otherwise, we perform an additional check: we
135 * calculate the size of the object modulo the size of the inferred type and
136 * subtract it from the size of the object. If this value is less than or
137 * equal to the size of the next-smaller kmem cache, we know that it's not an
138 * array of the inferred type -- if it were an array of the inferred type, it
139 * would have been instead allocated out of the next-smaller cache.
140 *
141 * In either case (FAM or no FAM), we iterate through each element of the
142 * hypothesised array, checking that each pointer member points to either NULL
143 * or valid memory. If pointer members do not satisfy these criteria, it is
144 * assumed that we have not satisfactorily determined that the given object is
145 * an array of the inferred type, and we abort processing of the node. Note
146 * that uninitialized pointers can potentially prevent an otherwise valid
147 * array from being interpreted as such. Because array misinterpretation
148 * can induce substantial cascading type misinterpretation, it is preferred to
149 * be conservative and accurate in such cases -- even if it means a lower type
150 * recognition rate.
151 *
152 * pass3: Type coalescence
153 *
154 * pass3 coalesces type possibilities by preferring structural possibilities
155 * over non-structural ones. For example, if an object is either of type
156 * "char" (pointed to by a caddr_t) or type "struct frotz", the possibilities
157 * will be coalesced into just "struct frotz."
158 *
159 * pass4: Non-array type inference
160 *
161 * pass4 is the least conservative: it is assumed that phenomenon (c) has been
162 * completely ferreted out by prior passes. All unknown types are visited, and
163 * incoming edges are checked. If there is only one possible structural
164 * inference for the unknown type, the node is inferred to be of that type, and
165 * the type is propagated. This pass picks up those nodes that are larger than
166 * their inferred type, but for which the inferred type is likely accurate.
167 * (struct dcentry, with its FAM of characters, is an example type that is
168 * frequently determined by this pass.)
169 *
170 * Post-pass: Greatest unknown reach
171 *
172 * If recognition rate is low (or, from a more practical perspective, if the
173 * object of interest is not automatically identified), it can be useful
174 * to know which node is the greatest impediment to further recognition.
175 * If the user can -- by hook or by crook -- determine the true type of this
176 * node (and set it with ::istype), much more type identification should be
177 * possible. To facilitate this, we therefore define the _reach_ of a node to
178 * be the number of unknown nodes that could potentially be identified were the
179 * node's type better known. We determine the reach by performing a
180 * depth-first pass through the graph. The node of greatest reach (along with
181 * the reach itself) are reported upon completion of the post-pass.
182 */
183
184 #include <mdb/mdb_param.h>
185 #include <mdb/mdb_modapi.h>
186 #include <mdb/mdb_ctf.h>
187 #include <sys/sysmacros.h>
188 #include <sys/kmem_impl.h>
189 #include <sys/vmem_impl.h>
190 #include <sys/modctl.h>
191 #include <sys/kobj.h>
192 #include <stdio.h>
193 #include "kmem.h"
194
195 struct tg_node;
196
197 typedef struct tg_edge {
198 struct tg_node *tge_src; /* source node */
199 struct tg_node *tge_dest; /* destination node */
200 uintptr_t tge_srcoffs; /* offset in source node */
201 uintptr_t tge_destoffs; /* offset in destination node */
202 struct tg_edge *tge_nextin; /* next incoming edge */
203 struct tg_edge *tge_nextout; /* next outgoing edge */
204 int tge_marked; /* mark */
205 } tg_edge_t;
206
207 typedef struct tg_type {
208 mdb_ctf_id_t tgt_type; /* CTF type */
209 mdb_ctf_id_t tgt_utype; /* unresolved CTF type */
210 mdb_ctf_id_t tgt_rtype; /* referring type */
211 size_t tgt_roffs; /* referring offset */
212 const char *tgt_rmember; /* referring member */
213 tg_edge_t *tgt_redge; /* referring edge */
214 struct tg_type *tgt_next; /* next type */
215 int tgt_flags; /* flags */
216 } tg_type_t;
217
218 #define TG_TYPE_ARRAY 0x0001
219 #define TG_TYPE_NOTARRAY 0x0002
220 #define TG_TYPE_HASFAM 0x0004
221
222 typedef struct tg_node {
223 uintptr_t tgn_base; /* address base of object */
224 uintptr_t tgn_limit; /* address limit of object */
225 tg_edge_t *tgn_incoming; /* incoming edges */
226 tg_edge_t *tgn_outgoing; /* outgoing edges */
227 tg_type_t *tgn_typelist; /* conjectured typelist */
228 tg_type_t *tgn_fraglist; /* type fragment list */
229 char tgn_marked; /* marked */
230 char tgn_postmarked; /* marked in postpass */
231 int tgn_smaller; /* size of next-smaller cache */
232 int tgn_reach; /* number of reachable unknown nodes */
233 mdb_ctf_id_t tgn_type; /* known type */
234 } tg_node_t;
235
236 #define TG_NODE_SIZE(n) ((n)->tgn_limit - (n)->tgn_base)
237
238 typedef struct tg_stats {
239 size_t tgs_buffers;
240 size_t tgs_nodes;
241 size_t tgs_unmarked;
242 size_t tgs_known;
243 size_t tgs_typed;
244 size_t tgs_conflicts;
245 size_t tgs_frag;
246 size_t tgs_candidates;
247 } tg_stats_t;
248
249 typedef struct tg_typeoffs {
250 mdb_ctf_id_t tgto_type; /* found type */
251 ulong_t tgto_offs; /* offset of interest */
252 const char **tgto_memberp; /* referring member name */
253 tg_edge_t *tgto_edge; /* outbound edge */
254 } tg_typeoffs_t;
255
256 typedef struct tg_buildstate {
257 uintptr_t tgbs_addr; /* address of region */
258 uintptr_t *tgbs_buf; /* in-core copy of region */
259 size_t tgbs_ndx; /* current pointer index */
260 size_t tgbs_nptrs; /* number of pointers */
261 tg_node_t *tgbs_src; /* corresponding node */
262 struct tg_buildstate *tgbs_next; /* next stacked or free */
263 } tg_buildstate_t;
264
265 typedef struct tg_poststate {
266 tg_node_t *tgps_node; /* current node */
267 tg_edge_t *tgps_edge; /* current edge */
268 size_t tgps_total; /* current total */
269 struct tg_poststate *tgps_next; /* next stacked or free */
270 } tg_poststate_t;
271
272 typedef struct tg_todo {
273 tg_node_t *tgtd_node; /* node to process */
274 uintptr_t tgtd_offs; /* offset within node */
275 mdb_ctf_id_t tgtd_type; /* conjectured type */
276 struct tg_todo *tgtd_next; /* next todo */
277 } tg_todo_t;
278
279 typedef struct tg_nodedata {
280 tg_node_t *tgd_next; /* next node to fill in */
281 size_t tgd_size; /* size of this node */
282 } tg_nodedata_t;
283
284 /*
285 * Some caches can be pretty arduous to identify (or are rife with conflicts).
286 * To assist type identification, specific caches are identified with the
287 * types of their contents. Each cache need _not_ be listed here; in general,
288 * a cache should only be added to the tg_cachetab[] if the identification rate
289 * for the cache is less than 95%Every . (The identification rate for a
290 * specific cache can be quickly determined by specifying the cache to
291 * ::typegraph.)
292 */
293 struct {
294 char *tgc_name;
295 char *tgc_type;
296 } tg_cachetab[] = {
297 { "streams_mblk", "mblk_t" },
298 { "seg_cache", "struct seg" },
299 { "segvn_cache", "struct segvn_data" },
300 { "anon_cache", "struct anon" },
301 { "ufs_inode_cache", "inode_t" },
302 { "hme_cache", "struct hment" },
303 { "queue_cache", "queinfo_t" },
304 { "sock_cache", "struct sonode" },
305 { "ire_cache", "ire_t" },
306 { NULL, NULL }
307 };
308
309 /*
310 * Some types are only known by their opaque handles. While this is a good way
311 * to keep interface clients from eating the Forbidden Fruit, it can make type
312 * identification difficult -- which can be especially important for big
313 * structures like dev_info_t. To assist type identification, we keep a table
314 * to translate from opaque handles to their underlying structures. A
315 * translation should only be added to the tg_typetab[] if the lack of
316 * translation is preventing substantial type identification. (This can be
317 * determined by using the "typeunknown" walker on a dump with bufctl auditing
318 * enabled, and using "::whatis -b" to determine the types of unknown buffers;
319 * if many of these unknown types are structures behind an opaque handle, a
320 * new entry in tg_typetab[] is likely warranted.)
321 */
322 struct {
323 char *tgt_type_name; /* filled in statically */
324 char *tgt_actual_name; /* filled in statically */
325 mdb_ctf_id_t tgt_type; /* determined dynamically */
326 mdb_ctf_id_t tgt_actual_type; /* determined dynamically */
327 } tg_typetab[] = {
328 { "dev_info_t", "struct dev_info" },
329 { "ddi_dma_handle_t", "ddi_dma_impl_t *" },
330 { NULL, NULL }
331 };
332
333 static enum {
334 TG_PASS1 = 1,
335 TG_PASS2,
336 TG_PASS3,
337 TG_PASS4
338 } tg_pass;
339
340 static size_t tg_nnodes; /* number of nodes */
341 static size_t tg_nanchored; /* number of anchored nodes */
342 static tg_node_t *tg_node; /* array of nodes */
343 static tg_node_t **tg_sorted; /* sorted array of pointers into tg_node */
344 static size_t tg_nsorted; /* number of pointers in tg_sorted */
345 static int *tg_sizes; /* copy of kmem_alloc_sizes[] array */
346 static int tg_nsizes; /* number of sizes in tg_sizes */
347 static hrtime_t tg_start; /* start time */
348 static int tg_improved; /* flag indicating that we have improved */
349 static int tg_built; /* flag indicating that type graph is built */
350 static uint_t tg_verbose; /* flag to increase verbosity */
351
352 struct typegraph_ctf_module {
353 unsigned int nsyms;
354 char *data;
355 uintptr_t bss;
356 size_t data_size;
357 size_t bss_size;
358 };
359
360 static mdb_ctf_id_t typegraph_type_offset(mdb_ctf_id_t, size_t,
361 tg_edge_t *, const char **);
362
363 static void
typegraph_typetab_init(void)364 typegraph_typetab_init(void)
365 {
366 int i;
367
368 for (i = 0; tg_typetab[i].tgt_type_name != NULL; i++) {
369 if (mdb_ctf_lookup_by_name(tg_typetab[i].tgt_type_name,
370 &tg_typetab[i].tgt_type) == -1) {
371 mdb_warn("can't find type '%s'\n",
372 tg_typetab[i].tgt_type_name);
373 mdb_ctf_type_invalidate(&tg_typetab[i].tgt_type);
374 continue;
375 }
376
377 if (mdb_ctf_lookup_by_name(tg_typetab[i].tgt_actual_name,
378 &tg_typetab[i].tgt_actual_type) == -1) {
379 mdb_warn("can't find type '%s'\n",
380 tg_typetab[i].tgt_actual_name);
381 mdb_ctf_type_invalidate(&tg_typetab[i].tgt_actual_type);
382 }
383 }
384 }
385
386 /*
387 * A wrapper around mdb_ctf_type_resolve() that first checks the type
388 * translation table.
389 */
390 static mdb_ctf_id_t
typegraph_resolve(mdb_ctf_id_t type)391 typegraph_resolve(mdb_ctf_id_t type)
392 {
393 int i;
394 mdb_ctf_id_t ret;
395
396 /*
397 * This could be _much_ more efficient...
398 */
399 for (i = 0; tg_typetab[i].tgt_type_name != NULL; i++) {
400 if (mdb_ctf_type_cmp(type, tg_typetab[i].tgt_type) == 0) {
401 type = tg_typetab[i].tgt_actual_type;
402 break;
403 }
404 }
405
406 (void) mdb_ctf_type_resolve(type, &ret);
407 return (ret);
408 }
409
410 /*
411 * A wrapper around mdb_ctf_type_name() that deals with anonymous structures.
412 * Anonymous structures are those that have no name associated with them.
413 * Nearly always, these structures are referred to by a typedef (e.g.
414 * "typedef struct { int bar } foo_t"); we expect the unresolved type to
415 * be passed as utype.
416 */
417 static char *
typegraph_type_name(mdb_ctf_id_t type,mdb_ctf_id_t utype)418 typegraph_type_name(mdb_ctf_id_t type, mdb_ctf_id_t utype)
419 {
420 static char buf[MDB_SYM_NAMLEN];
421
422 if (mdb_ctf_type_name(type, buf, sizeof (buf)) == NULL) {
423 (void) strcpy(buf, "<unknown>");
424 } else {
425 /*
426 * Perhaps a CTF interface would be preferable to this kludgey
427 * strcmp()? Perhaps.
428 */
429 if (strcmp(buf, "struct ") == 0)
430 (void) mdb_ctf_type_name(utype, buf, sizeof (buf));
431 }
432
433 return (buf);
434 }
435
436 /*
437 * A wrapper around mdb_ctf_type_size() that accurately accounts for arrays.
438 */
439 static ssize_t
typegraph_size(mdb_ctf_id_t type)440 typegraph_size(mdb_ctf_id_t type)
441 {
442 mdb_ctf_arinfo_t arr;
443 ssize_t size;
444
445 if (!mdb_ctf_type_valid(type))
446 return (-1);
447
448 if (mdb_ctf_type_kind(type) != CTF_K_ARRAY)
449 return (mdb_ctf_type_size(type));
450
451 if (mdb_ctf_array_info(type, &arr) == -1)
452 return (-1);
453
454 type = typegraph_resolve(arr.mta_contents);
455
456 if (!mdb_ctf_type_valid(type))
457 return (-1);
458
459 if ((size = mdb_ctf_type_size(type)) == -1)
460 return (-1);
461
462 return (size * arr.mta_nelems);
463 }
464
465 /*
466 * The mdb_ctf_member_iter() callback for typegraph_type_offset().
467 */
468 static int
typegraph_offiter(const char * name,mdb_ctf_id_t type,ulong_t off,tg_typeoffs_t * toffs)469 typegraph_offiter(const char *name, mdb_ctf_id_t type,
470 ulong_t off, tg_typeoffs_t *toffs)
471 {
472 int kind;
473 ssize_t size;
474 mdb_ctf_arinfo_t arr;
475
476 off /= NBBY;
477
478 if (off > toffs->tgto_offs) {
479 /*
480 * We went past it; return failure.
481 */
482 return (1);
483 }
484
485 if (!mdb_ctf_type_valid(type = typegraph_resolve(type)))
486 return (0);
487
488 if ((size = mdb_ctf_type_size(type)) == -1)
489 return (0);
490
491 if (off < toffs->tgto_offs &&
492 size != 0 && off + size <= toffs->tgto_offs) {
493 /*
494 * Haven't reached it yet; continue looking.
495 */
496 return (0);
497 }
498
499 /*
500 * If the base type is not a structure, an array or a union, and
501 * the offset equals the desired offset, we have our type.
502 */
503 if ((kind = mdb_ctf_type_kind(type)) != CTF_K_STRUCT &&
504 kind != CTF_K_UNION && kind != CTF_K_ARRAY) {
505 if (off == toffs->tgto_offs)
506 toffs->tgto_type = type;
507
508 if (toffs->tgto_memberp != NULL)
509 *(toffs->tgto_memberp) = name;
510
511 return (1);
512 }
513
514 /*
515 * If the type is an array, see if we fall within the bounds.
516 */
517 if (kind == CTF_K_ARRAY) {
518 if (mdb_ctf_array_info(type, &arr) == -1)
519 return (0);
520
521 type = typegraph_resolve(arr.mta_contents);
522
523 if (!mdb_ctf_type_valid(type))
524 return (0);
525
526 size = mdb_ctf_type_size(type) * arr.mta_nelems;
527
528 if (off < toffs->tgto_offs && off + size <= toffs->tgto_offs) {
529 /*
530 * Nope, haven't found it yet; continue looking.
531 */
532 return (0);
533 }
534 }
535
536 toffs->tgto_type = typegraph_type_offset(type,
537 toffs->tgto_offs - off, toffs->tgto_edge, toffs->tgto_memberp);
538
539 return (1);
540 }
541
542 /*
543 * The mdb_ctf_member_iter() callback for typegraph_type_offset() when the type
544 * is found to be of kind CTF_K_UNION. With unions, we attempt to do better
545 * than just completely punting: if all but one of the members is impossible
546 * (due to, say, size constraints on the destination node), we can propagate
547 * the valid member.
548 */
549 static int
typegraph_union(const char * name,mdb_ctf_id_t type,ulong_t off,tg_typeoffs_t * toffs)550 typegraph_union(const char *name, mdb_ctf_id_t type, ulong_t off,
551 tg_typeoffs_t *toffs)
552 {
553 const char *member = name;
554 tg_edge_t *e = toffs->tgto_edge;
555 mdb_ctf_id_t rtype;
556 size_t rsize;
557 int kind;
558
559 if (!mdb_ctf_type_valid(type = typegraph_resolve(type)))
560 return (0);
561
562 kind = mdb_ctf_type_kind(type);
563
564 if (kind == CTF_K_STRUCT || kind != CTF_K_UNION ||
565 kind != CTF_K_ARRAY) {
566 type = typegraph_type_offset(type,
567 toffs->tgto_offs - off, e, &member);
568 }
569
570 if (!mdb_ctf_type_valid(type))
571 return (0);
572
573 if (mdb_ctf_type_kind(type) != CTF_K_POINTER)
574 return (0);
575
576 /*
577 * Now figure out what exactly we're pointing to.
578 */
579 if (mdb_ctf_type_reference(type, &rtype) == -1)
580 return (0);
581
582 if (!mdb_ctf_type_valid(rtype = typegraph_resolve(rtype)))
583 return (0);
584
585 rsize = mdb_ctf_type_size(rtype);
586
587 /*
588 * Compare this size to the size of the thing we're pointing to --
589 * if it's larger than the node that we're pointing to, we know that
590 * the alleged pointer type must be an invalid interpretation of the
591 * union.
592 */
593 if (rsize > TG_NODE_SIZE(e->tge_dest) - e->tge_destoffs) {
594 /*
595 * We're in luck -- it's not possibly this pointer.
596 */
597 return (0);
598 }
599
600 /*
601 * This looks like it could be legit. If the type hasn't been
602 * specified, we could be in business.
603 */
604 if (mdb_ctf_type_valid(toffs->tgto_type)) {
605 /*
606 * There are two potentially valid interpretations for this
607 * union. Invalidate the type.
608 */
609 mdb_ctf_type_invalidate(&toffs->tgto_type);
610 return (1);
611 }
612
613 toffs->tgto_type = type;
614
615 if (toffs->tgto_memberp != NULL)
616 *(toffs->tgto_memberp) = member;
617
618 return (0);
619 }
620
621 /*ARGSUSED*/
622 static int
typegraph_lastmember(const char * name,mdb_ctf_id_t type,ulong_t off,void * last)623 typegraph_lastmember(const char *name,
624 mdb_ctf_id_t type, ulong_t off, void *last)
625 {
626 *((mdb_ctf_id_t *)last) = type;
627
628 return (0);
629 }
630
631 /*
632 * To determine if a structure is has a flexible array member, we iterate over
633 * the members; if the structure has more than one member, and the last member
634 * is an array of size 1, we're going to assume that this structure has a
635 * flexible array member. Yes, this heuristic is a little sloppy -- but cut me
636 * some slack: why the hell else would you have an array of size 1? (Don't
637 * answer that.)
638 */
639 static int
typegraph_hasfam(mdb_ctf_id_t type,mdb_ctf_id_t * atype)640 typegraph_hasfam(mdb_ctf_id_t type, mdb_ctf_id_t *atype)
641 {
642 mdb_ctf_arinfo_t arr;
643 mdb_ctf_id_t last;
644 int kind;
645
646 if (!mdb_ctf_type_valid(type))
647 return (0);
648
649 if ((kind = mdb_ctf_type_kind(type)) != CTF_K_STRUCT)
650 return (0);
651
652 mdb_ctf_type_invalidate(&last);
653 mdb_ctf_member_iter(type, typegraph_lastmember, &last, 0);
654
655 if (!mdb_ctf_type_valid(last))
656 return (0);
657
658 if ((kind = mdb_ctf_type_kind(last)) == CTF_K_STRUCT)
659 return (typegraph_hasfam(last, atype));
660
661 if (kind != CTF_K_ARRAY)
662 return (0);
663
664 if (typegraph_size(last) == typegraph_size(type)) {
665 /*
666 * This structure has only one member; even if that member is
667 * an array of size 1, we'll assume that there is something
668 * stranger going on than a run-of-the-mill FAM (e.g., a
669 * kmutex_t).
670 */
671 return (0);
672 }
673
674 if (mdb_ctf_array_info(last, &arr) == -1)
675 return (0);
676
677 if (arr.mta_nelems != 1)
678 return (0);
679
680 if (atype != NULL)
681 *atype = typegraph_resolve(arr.mta_contents);
682
683 return (1);
684 }
685
686 /*
687 * This routine takes a type and offset, and returns the type at the specified
688 * offset. It additionally takes an optional edge to help bust unions, and
689 * an optional address of a character pointer to set to the name of the member
690 * found at the specified offset.
691 */
692 static mdb_ctf_id_t
typegraph_type_offset(mdb_ctf_id_t type,size_t offset,tg_edge_t * e,const char ** member)693 typegraph_type_offset(mdb_ctf_id_t type, size_t offset, tg_edge_t *e,
694 const char **member)
695 {
696 mdb_ctf_arinfo_t arr;
697 uint_t kind;
698 mdb_ctf_id_t last;
699 ssize_t size;
700 ssize_t lsize;
701 tg_typeoffs_t toffs;
702 mdb_ctf_id_t inval;
703
704 mdb_ctf_type_invalidate(&inval);
705
706 if (member != NULL)
707 *member = NULL;
708
709 /*
710 * Resolve type to its base type.
711 */
712 type = typegraph_resolve(type);
713 kind = mdb_ctf_type_kind(type);
714
715 switch (kind) {
716 case CTF_K_ARRAY:
717 /*
718 * If this is an array, we need to figure out what it's an
719 * array _of_. We must then figure out the size of the array
720 * structure, and then determine our offset within that type.
721 * From there, we can recurse.
722 */
723 if (mdb_ctf_array_info(type, &arr) == -1)
724 return (inval);
725
726 type = typegraph_resolve(arr.mta_contents);
727
728 if (!mdb_ctf_type_valid(type))
729 return (inval);
730
731 /*
732 * If the type is not a structure/union, then check that the
733 * offset doesn't point to the middle of the base type and
734 * return it.
735 */
736 kind = mdb_ctf_type_kind(type);
737 size = mdb_ctf_type_size(type);
738
739 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
740 if (offset % size) {
741 /*
742 * The offset is pointing to the middle of a
743 * type; return failure.
744 */
745 return (inval);
746 }
747
748 return (type);
749 }
750
751 return (typegraph_type_offset(type, offset % size, e, member));
752
753 case CTF_K_STRUCT:
754 /*
755 * If the offset is larger than the size, we need to figure
756 * out what exactly we're looking at. There are several
757 * possibilities:
758 *
759 * (a) A structure that has this type as its first member.
760 *
761 * (b) An array of structures of this type.
762 *
763 * (c) A structure has a flexible array member.
764 *
765 * The differentiation between (a) and (b) has hopefully
766 * happened before entering this function. To differentiate
767 * between (b) and (c), we call typegraph_hasfam().
768 */
769 size = mdb_ctf_type_size(type);
770
771 if (offset >= size) {
772 if (typegraph_hasfam(type, &last)) {
773 /*
774 * We have a live one. Take the size, subtract
775 * the size of the last element, and recurse.
776 */
777 if (!mdb_ctf_type_valid(last))
778 return (inval);
779
780 lsize = mdb_ctf_type_size(last);
781
782 return (typegraph_type_offset(last,
783 offset - size - lsize, e, member));
784 }
785
786 offset %= size;
787 }
788
789 toffs.tgto_offs = offset;
790 toffs.tgto_memberp = member;
791 toffs.tgto_edge = e;
792 mdb_ctf_type_invalidate(&toffs.tgto_type);
793
794 mdb_ctf_member_iter(type,
795 (mdb_ctf_member_f *)typegraph_offiter, &toffs, 0);
796
797 return (toffs.tgto_type);
798
799 case CTF_K_POINTER:
800 if (!mdb_ctf_type_valid(type = typegraph_resolve(type)))
801 return (inval);
802
803 size = mdb_ctf_type_size(type);
804
805 if (offset % size) {
806 /*
807 * The offset is pointing to the middle of a type;
808 * return failure.
809 */
810 return (inval);
811 }
812
813 return (type);
814
815 case CTF_K_UNION:
816 if (e == NULL) {
817 /*
818 * We've been given no outbound edge -- we have no way
819 * of figuring out what the hell this union is.
820 */
821 return (inval);
822 }
823
824 toffs.tgto_offs = offset;
825 toffs.tgto_memberp = member;
826 toffs.tgto_edge = e;
827 mdb_ctf_type_invalidate(&toffs.tgto_type);
828
829 /*
830 * Try to bust the union...
831 */
832 if (mdb_ctf_member_iter(type,
833 (mdb_ctf_member_f *)typegraph_union, &toffs, 0) != 0) {
834 /*
835 * There was at least one valid pointer in there.
836 * Return "void *".
837 */
838 (void) mdb_ctf_lookup_by_name("void *", &type);
839
840 return (type);
841 }
842
843 return (toffs.tgto_type);
844
845 default:
846 /*
847 * If the offset is anything other than zero, no dice.
848 */
849 if (offset != 0)
850 return (inval);
851
852 return (type);
853 }
854 }
855
856 /*
857 * This routine takes an address and a type, and determines if the memory
858 * pointed to by the specified address could be of the specified type.
859 * This could become significantly more sophisticated, but for now it's pretty
860 * simple: this is _not_ of the specified type if it's a pointer, and either:
861 *
862 * (a) The alignment is not correct given the type that is pointed to.
863 *
864 * (b) The memory pointed to is invalid. Note that structures that have
865 * uninitialized pointers may cause us to erroneously fail -- but these
866 * structures are a bug anyway (uninitialized pointers can confuse many
867 * analysis tools, including ::findleaks).
868 */
869 static int
typegraph_couldbe(uintptr_t addr,mdb_ctf_id_t type)870 typegraph_couldbe(uintptr_t addr, mdb_ctf_id_t type)
871 {
872 int rkind;
873 mdb_ctf_id_t rtype;
874 uintptr_t val, throwaway;
875 size_t rsize;
876 char buf[MDB_SYM_NAMLEN];
877
878 if (mdb_ctf_type_kind(type) != CTF_K_POINTER)
879 return (1);
880
881 if (mdb_ctf_type_reference(type, &rtype) == -1)
882 return (1);
883
884 if (!mdb_ctf_type_valid(rtype = typegraph_resolve(rtype)))
885 return (1);
886
887 if (mdb_vread(&val, sizeof (val), addr) == -1) {
888 /*
889 * This is definitely unexpected. We should not be getting
890 * back an error on a node that was successfully read in.
891 * Lacking something better to do, we'll print an error
892 * and return.
893 */
894 mdb_warn("failed to evaluate pointer type at address %p", addr);
895 return (1);
896 }
897
898 rkind = mdb_ctf_type_kind(rtype);
899
900 if (rkind == CTF_K_STRUCT || rkind == CTF_K_UNION) {
901 /*
902 * If it's a pointer to a structure or union, it must be
903 * aligned to sizeof (uintptr_t).
904 */
905 if (val & (sizeof (uintptr_t) - 1)) {
906 if (tg_verbose) {
907 mdb_printf("typegraph: pass %d: rejecting "
908 "*%p (%p) as %s: misaligned pointer\n",
909 tg_pass, addr, val,
910 mdb_ctf_type_name(type, buf, sizeof (buf)));
911 }
912
913 return (0);
914 }
915 }
916
917 rsize = mdb_ctf_type_size(rtype);
918
919 if (val == 0 || rsize == 0)
920 return (1);
921
922 /*
923 * For our speculative read, we're going to clamp the referenced size
924 * at the size of a pointer.
925 */
926 if (rsize > sizeof (uintptr_t))
927 rsize = sizeof (uintptr_t);
928
929 if (mdb_vread(&throwaway, rsize, val) == -1) {
930 if (tg_verbose) {
931 mdb_printf("typegraph: pass %d: rejecting *%p (%p) as"
932 " %s: bad pointer\n", tg_pass, addr, val,
933 mdb_ctf_type_name(type, buf, sizeof (buf)));
934 }
935 return (0);
936 }
937
938 return (1);
939 }
940
941 static int
typegraph_nodecmp(const void * l,const void * r)942 typegraph_nodecmp(const void *l, const void *r)
943 {
944 tg_node_t *lhs = *(tg_node_t **)l;
945 tg_node_t *rhs = *(tg_node_t **)r;
946
947 if (lhs->tgn_base < rhs->tgn_base)
948 return (-1);
949 if (lhs->tgn_base > rhs->tgn_base)
950 return (1);
951
952 return (0);
953 }
954
955 static tg_node_t *
typegraph_search(uintptr_t addr)956 typegraph_search(uintptr_t addr)
957 {
958 ssize_t left = 0, right = tg_nnodes - 1, guess;
959
960 while (right >= left) {
961 guess = (right + left) >> 1;
962
963 if (addr < tg_sorted[guess]->tgn_base) {
964 right = guess - 1;
965 continue;
966 }
967
968 if (addr >= tg_sorted[guess]->tgn_limit) {
969 left = guess + 1;
970 continue;
971 }
972
973 return (tg_sorted[guess]);
974 }
975
976 return (NULL);
977 }
978
979 static int
typegraph_interested(const kmem_cache_t * c)980 typegraph_interested(const kmem_cache_t *c)
981 {
982 vmem_t vmem;
983
984 if (mdb_vread(&vmem, sizeof (vmem), (uintptr_t)c->cache_arena) == -1) {
985 mdb_warn("cannot read arena %p for cache '%s'",
986 (uintptr_t)c->cache_arena, c->cache_name);
987 return (0);
988 }
989
990 /*
991 * If this cache isn't allocating from the kmem_default or the
992 * kmem_firewall vmem arena, we're not interested.
993 */
994 if (strcmp(vmem.vm_name, "kmem_default") != 0 &&
995 strcmp(vmem.vm_name, "kmem_firewall") != 0)
996 return (0);
997
998 return (1);
999 }
1000
1001 static int
typegraph_estimate(uintptr_t addr,const kmem_cache_t * c,size_t * est)1002 typegraph_estimate(uintptr_t addr, const kmem_cache_t *c, size_t *est)
1003 {
1004 if (!typegraph_interested(c))
1005 return (WALK_NEXT);
1006
1007 *est += kmem_estimate_allocated(addr, c);
1008
1009 return (WALK_NEXT);
1010 }
1011
1012 static int
typegraph_estimate_modctl(uintptr_t addr,const struct modctl * m,size_t * est)1013 typegraph_estimate_modctl(uintptr_t addr, const struct modctl *m, size_t *est)
1014 {
1015 struct typegraph_ctf_module mod;
1016
1017 if (m->mod_mp == NULL)
1018 return (WALK_NEXT);
1019
1020 if (mdb_ctf_vread(&mod, "struct module", "struct typegraph_ctf_module",
1021 (uintptr_t)m->mod_mp, 0) == -1) {
1022 mdb_warn("couldn't read modctl %p's module", addr);
1023 return (WALK_NEXT);
1024 }
1025
1026 (*est) += mod.nsyms;
1027
1028 return (WALK_NEXT);
1029 }
1030
1031 /*ARGSUSED*/
1032 static int
typegraph_estimate_vmem(uintptr_t addr,const vmem_t * vmem,size_t * est)1033 typegraph_estimate_vmem(uintptr_t addr, const vmem_t *vmem, size_t *est)
1034 {
1035 if (strcmp(vmem->vm_name, "kmem_oversize") != 0)
1036 return (WALK_NEXT);
1037
1038 *est += (size_t)(vmem->vm_kstat.vk_alloc.value.ui64 -
1039 vmem->vm_kstat.vk_free.value.ui64);
1040
1041 return (WALK_NEXT);
1042 }
1043
1044 /*ARGSUSED*/
1045 static int
typegraph_buf(uintptr_t addr,void * ignored,tg_nodedata_t * tgd)1046 typegraph_buf(uintptr_t addr, void *ignored, tg_nodedata_t *tgd)
1047 {
1048 tg_node_t *node = tgd->tgd_next++;
1049 uintptr_t limit = addr + tgd->tgd_size;
1050
1051 node->tgn_base = addr;
1052 node->tgn_limit = limit;
1053
1054 return (WALK_NEXT);
1055 }
1056
1057 /*ARGSUSED*/
1058 static int
typegraph_kmem(uintptr_t addr,const kmem_cache_t * c,tg_node_t ** tgp)1059 typegraph_kmem(uintptr_t addr, const kmem_cache_t *c, tg_node_t **tgp)
1060 {
1061 tg_node_t *node = *tgp;
1062 tg_nodedata_t tgd;
1063 mdb_ctf_id_t type;
1064 int i, smaller;
1065
1066 mdb_ctf_type_invalidate(&type);
1067
1068 if (!typegraph_interested(c))
1069 return (WALK_NEXT);
1070
1071 tgd.tgd_size = c->cache_bufsize;
1072 tgd.tgd_next = *tgp;
1073
1074 if (mdb_pwalk("kmem", (mdb_walk_cb_t)typegraph_buf, &tgd, addr) == -1) {
1075 mdb_warn("can't walk kmem for cache %p (%s)", addr,
1076 c->cache_name);
1077 return (WALK_DONE);
1078 }
1079
1080 *tgp = tgd.tgd_next;
1081
1082 for (i = 0; tg_cachetab[i].tgc_name != NULL; i++) {
1083 if (strcmp(tg_cachetab[i].tgc_name, c->cache_name) != 0)
1084 continue;
1085
1086 if (mdb_ctf_lookup_by_name(tg_cachetab[i].tgc_type,
1087 &type) == -1) {
1088 mdb_warn("could not find type '%s', allegedly type "
1089 "for cache %s", tg_cachetab[i].tgc_type,
1090 c->cache_name);
1091 break;
1092 }
1093
1094 break;
1095 }
1096
1097 /*
1098 * If this is a named cache (i.e., not from a kmem_alloc_[n] cache),
1099 * the nextsize is 0.
1100 */
1101 if (strncmp(c->cache_name, "kmem_alloc_", strlen("kmem_alloc_")) == 0) {
1102 GElf_Sym sym;
1103 GElf_Sym sym2;
1104
1105 if (tg_sizes == NULL) {
1106 size_t nsizes = 0;
1107 size_t nsizes_reg = 0;
1108 size_t nsizes_big = 0;
1109
1110 if (mdb_lookup_by_name("kmem_alloc_sizes",
1111 &sym) == -1) {
1112 mdb_warn("failed to find 'kmem_alloc_sizes'");
1113 return (WALK_ERR);
1114 }
1115 nsizes_reg = sym.st_size / sizeof (int);
1116
1117 if (mdb_lookup_by_name("kmem_big_alloc_sizes",
1118 &sym2) != -1) {
1119 nsizes_big = sym2.st_size / sizeof (int);
1120 }
1121
1122 nsizes = nsizes_reg + nsizes_big;
1123
1124 tg_sizes = mdb_zalloc(nsizes * sizeof (int), UM_SLEEP);
1125 tg_nsizes = nsizes;
1126
1127 if (mdb_vread(tg_sizes, sym.st_size,
1128 (uintptr_t)sym.st_value) == -1) {
1129 mdb_warn("failed to read kmem_alloc_sizes");
1130 return (WALK_ERR);
1131 }
1132 if (nsizes_big > 0 &&
1133 mdb_vread(&tg_sizes[nsizes_reg], sym2.st_size,
1134 (uintptr_t)sym2.st_value) == -1) {
1135 mdb_warn("failed to read kmem_big_alloc_sizes");
1136 return (WALK_ERR);
1137 }
1138 }
1139
1140 /*
1141 * Yes, this is a linear search -- but we're talking about
1142 * a pretty small array (38 elements as of this writing), and
1143 * only executed a handful of times (for each sized kmem
1144 * cache).
1145 */
1146 for (i = 0; i < tg_nsizes; i++) {
1147 if (tg_sizes[i] == c->cache_bufsize)
1148 break;
1149 }
1150
1151 if (i == tg_nsizes) {
1152 /*
1153 * Something is wrong -- this appears to be a sized
1154 * kmem cache, but we can't find its size in the
1155 * kmem_alloc_sizes array. Emit a warning and return
1156 * failure.
1157 */
1158 mdb_warn("couldn't find buffer size for %s (%d)"
1159 " in kmem_alloc_sizes array\n", c->cache_name,
1160 c->cache_bufsize);
1161
1162 return (WALK_ERR);
1163 }
1164
1165 if (i == 0) {
1166 smaller = 1;
1167 } else {
1168 smaller = tg_sizes[i - 1];
1169 }
1170 } else {
1171 smaller = 0;
1172 }
1173
1174 for (; node < *tgp; node++) {
1175 node->tgn_type = type;
1176 node->tgn_smaller = smaller;
1177 }
1178
1179 *tgp = tgd.tgd_next;
1180
1181 return (WALK_NEXT);
1182 }
1183
1184 /*ARGSUSED*/
1185 static int
typegraph_seg(uintptr_t addr,const vmem_seg_t * seg,tg_node_t ** tgp)1186 typegraph_seg(uintptr_t addr, const vmem_seg_t *seg, tg_node_t **tgp)
1187 {
1188 tg_nodedata_t tgd;
1189
1190 tgd.tgd_next = *tgp;
1191 tgd.tgd_size = seg->vs_end - seg->vs_start;
1192
1193 typegraph_buf(seg->vs_start, NULL, &tgd);
1194
1195 *tgp = tgd.tgd_next;
1196 return (WALK_NEXT);
1197 }
1198
1199 static int
typegraph_vmem(uintptr_t addr,const vmem_t * vmem,tg_node_t ** tgp)1200 typegraph_vmem(uintptr_t addr, const vmem_t *vmem, tg_node_t **tgp)
1201 {
1202 if (strcmp(vmem->vm_name, "kmem_oversize") != 0)
1203 return (WALK_NEXT);
1204
1205 if (mdb_pwalk("vmem_alloc",
1206 (mdb_walk_cb_t)typegraph_seg, tgp, addr) == -1)
1207 mdb_warn("can't walk vmem for arena %p", addr);
1208
1209 return (WALK_NEXT);
1210 }
1211
1212 static void
typegraph_build_anchored(uintptr_t addr,size_t size,mdb_ctf_id_t type)1213 typegraph_build_anchored(uintptr_t addr, size_t size, mdb_ctf_id_t type)
1214 {
1215 uintptr_t *buf;
1216 tg_buildstate_t *state = NULL, *new_state, *free = NULL;
1217 tg_node_t *node, *src;
1218 tg_edge_t *edge;
1219 size_t nptrs, ndx;
1220 uintptr_t min = tg_sorted[0]->tgn_base;
1221 uintptr_t max = tg_sorted[tg_nnodes - 1]->tgn_limit;
1222 ssize_t rval;
1223 int mask = sizeof (uintptr_t) - 1;
1224
1225 if (addr == 0 || size < sizeof (uintptr_t))
1226 return;
1227
1228 /*
1229 * Add an anchored node.
1230 */
1231 src = &tg_node[tg_nnodes + tg_nanchored++];
1232 src->tgn_base = addr;
1233 src->tgn_limit = addr + size;
1234 src->tgn_type = type;
1235
1236 push:
1237 /*
1238 * If our address isn't pointer-aligned, we need to align it and
1239 * whack the size appropriately.
1240 */
1241 if (addr & mask) {
1242 if ((mask + 1) - (addr & mask) >= size)
1243 goto out;
1244
1245 size -= (mask + 1) - (addr & mask);
1246 addr += (mask + 1) - (addr & mask);
1247 }
1248
1249 nptrs = size / sizeof (uintptr_t);
1250 buf = mdb_alloc(size, UM_SLEEP);
1251 ndx = 0;
1252
1253 if ((rval = mdb_vread(buf, size, addr)) != size) {
1254 mdb_warn("couldn't read ptr at %p (size %ld); rval is %d",
1255 addr, size, rval);
1256 goto out;
1257 }
1258 pop:
1259 for (; ndx < nptrs; ndx++) {
1260 uintptr_t ptr = buf[ndx];
1261
1262 if (ptr < min || ptr >= max)
1263 continue;
1264
1265 if ((node = typegraph_search(ptr)) == NULL)
1266 continue;
1267
1268 /*
1269 * We need to record an edge to us.
1270 */
1271 edge = mdb_zalloc(sizeof (tg_edge_t), UM_SLEEP);
1272
1273 edge->tge_src = src;
1274 edge->tge_dest = node;
1275 edge->tge_nextout = src->tgn_outgoing;
1276 src->tgn_outgoing = edge;
1277
1278 edge->tge_srcoffs += ndx * sizeof (uintptr_t);
1279 edge->tge_destoffs = ptr - node->tgn_base;
1280 edge->tge_nextin = node->tgn_incoming;
1281 node->tgn_incoming = edge;
1282
1283 /*
1284 * If this node is marked, we don't need to descend.
1285 */
1286 if (node->tgn_marked)
1287 continue;
1288
1289 /*
1290 * We need to descend. To minimize the resource consumption
1291 * of type graph construction, we avoid recursing.
1292 */
1293 node->tgn_marked = 1;
1294
1295 if (free != NULL) {
1296 new_state = free;
1297 free = free->tgbs_next;
1298 } else {
1299 new_state =
1300 mdb_zalloc(sizeof (tg_buildstate_t), UM_SLEEP);
1301 }
1302
1303 new_state->tgbs_src = src;
1304 src = node;
1305
1306 new_state->tgbs_addr = addr;
1307 addr = node->tgn_base;
1308 size = node->tgn_limit - addr;
1309
1310 new_state->tgbs_next = state;
1311 new_state->tgbs_buf = buf;
1312 new_state->tgbs_ndx = ndx + 1;
1313 new_state->tgbs_nptrs = nptrs;
1314 state = new_state;
1315 goto push;
1316 }
1317
1318 /*
1319 * If we're here, then we have completed this region. We need to
1320 * free our buffer, and update our "resident" counter accordingly.
1321 */
1322 mdb_free(buf, size);
1323
1324 out:
1325 /*
1326 * If we have pushed state, we need to pop it.
1327 */
1328 if (state != NULL) {
1329 buf = state->tgbs_buf;
1330 ndx = state->tgbs_ndx;
1331 src = state->tgbs_src;
1332 nptrs = state->tgbs_nptrs;
1333 addr = state->tgbs_addr;
1334
1335 size = nptrs * sizeof (uintptr_t);
1336
1337 new_state = state->tgbs_next;
1338 state->tgbs_next = free;
1339 free = state;
1340 state = new_state;
1341
1342 goto pop;
1343 }
1344
1345 while (free != NULL) {
1346 state = free;
1347 free = free->tgbs_next;
1348 mdb_free(state, sizeof (tg_buildstate_t));
1349 }
1350 }
1351
1352 static void
typegraph_build(uintptr_t addr,size_t size)1353 typegraph_build(uintptr_t addr, size_t size)
1354 {
1355 uintptr_t limit = addr + size;
1356 char name[MDB_SYM_NAMLEN];
1357 GElf_Sym sym;
1358 mdb_ctf_id_t type;
1359
1360 do {
1361 if (mdb_lookup_by_addr(addr, MDB_SYM_EXACT, name,
1362 sizeof (name), &sym) == -1) {
1363 addr++;
1364 continue;
1365 }
1366
1367 if (sym.st_size == 0) {
1368 addr++;
1369 continue;
1370 }
1371
1372 if (strcmp(name, "kstat_initial") == 0) {
1373 /*
1374 * Yes, this is a kludge. "kstat_initial" ends up
1375 * backing the kstat vmem arena -- so we don't want
1376 * to include it as an anchor node.
1377 */
1378 addr += sym.st_size;
1379 continue;
1380 }
1381
1382 /*
1383 * We have the symbol; now get its type.
1384 */
1385 if (mdb_ctf_lookup_by_addr(addr, &type) == -1) {
1386 addr += sym.st_size;
1387 continue;
1388 }
1389
1390 if (!mdb_ctf_type_valid(type)) {
1391 addr += sym.st_size;
1392 continue;
1393 }
1394
1395 if (!mdb_ctf_type_valid(type = typegraph_resolve(type))) {
1396 addr += sym.st_size;
1397 continue;
1398 }
1399
1400 typegraph_build_anchored(addr, (size_t)sym.st_size, type);
1401 addr += sym.st_size;
1402 } while (addr < limit);
1403 }
1404
1405 /*ARGSUSED*/
1406 static int
typegraph_thread(uintptr_t addr,const kthread_t * t,mdb_ctf_id_t * type)1407 typegraph_thread(uintptr_t addr, const kthread_t *t, mdb_ctf_id_t *type)
1408 {
1409 /*
1410 * If this thread isn't already a node, add it as an anchor. And
1411 * regardless, set its type to be the specified type.
1412 */
1413 tg_node_t *node;
1414
1415 if ((node = typegraph_search(addr)) == NULL) {
1416 typegraph_build_anchored(addr, mdb_ctf_type_size(*type), *type);
1417 } else {
1418 node->tgn_type = *type;
1419 }
1420
1421 return (WALK_NEXT);
1422 }
1423
1424 /*ARGSUSED*/
1425 static int
typegraph_kstat(uintptr_t addr,const vmem_seg_t * seg,mdb_ctf_id_t * type)1426 typegraph_kstat(uintptr_t addr, const vmem_seg_t *seg, mdb_ctf_id_t *type)
1427 {
1428 size_t size = mdb_ctf_type_size(*type);
1429
1430 typegraph_build_anchored(seg->vs_start, size, *type);
1431
1432 return (WALK_NEXT);
1433 }
1434
1435 static void
typegraph_node_addtype(tg_node_t * node,tg_edge_t * edge,mdb_ctf_id_t rtype,const char * rmember,size_t roffs,mdb_ctf_id_t utype,mdb_ctf_id_t type)1436 typegraph_node_addtype(tg_node_t *node, tg_edge_t *edge, mdb_ctf_id_t rtype,
1437 const char *rmember, size_t roffs, mdb_ctf_id_t utype, mdb_ctf_id_t type)
1438 {
1439 tg_type_t *tp;
1440 tg_type_t **list;
1441
1442 if (edge->tge_destoffs == 0) {
1443 list = &node->tgn_typelist;
1444 } else {
1445 list = &node->tgn_fraglist;
1446 }
1447
1448 /*
1449 * First, search for this type in the type list.
1450 */
1451 for (tp = *list; tp != NULL; tp = tp->tgt_next) {
1452 if (mdb_ctf_type_cmp(tp->tgt_type, type) == 0)
1453 return;
1454 }
1455
1456 tp = mdb_zalloc(sizeof (tg_type_t), UM_SLEEP);
1457 tp->tgt_next = *list;
1458 tp->tgt_type = type;
1459 tp->tgt_rtype = rtype;
1460 tp->tgt_utype = utype;
1461 tp->tgt_redge = edge;
1462 tp->tgt_roffs = roffs;
1463 tp->tgt_rmember = rmember;
1464 *list = tp;
1465
1466 tg_improved = 1;
1467 }
1468
1469 static void
typegraph_stats_node(tg_node_t * node,tg_stats_t * stats)1470 typegraph_stats_node(tg_node_t *node, tg_stats_t *stats)
1471 {
1472 tg_edge_t *e;
1473
1474 stats->tgs_nodes++;
1475
1476 if (!node->tgn_marked)
1477 stats->tgs_unmarked++;
1478
1479 if (mdb_ctf_type_valid(node->tgn_type)) {
1480 stats->tgs_known++;
1481 return;
1482 }
1483
1484 if (node->tgn_typelist != NULL) {
1485 stats->tgs_typed++;
1486
1487 if (node->tgn_typelist->tgt_next)
1488 stats->tgs_conflicts++;
1489
1490 return;
1491 }
1492
1493 if (node->tgn_fraglist != NULL) {
1494 stats->tgs_frag++;
1495 return;
1496 }
1497
1498 /*
1499 * This node is not typed -- but check if any of its outgoing edges
1500 * were successfully typed; such nodes represent candidates for
1501 * an exhaustive type search.
1502 */
1503 for (e = node->tgn_outgoing; e != NULL; e = e->tge_nextout) {
1504 if (e->tge_dest->tgn_typelist) {
1505 stats->tgs_candidates++;
1506 break;
1507 }
1508 }
1509 }
1510
1511 /*ARGSUSED*/
1512 static int
typegraph_stats_buffer(uintptr_t addr,void * ignored,tg_stats_t * stats)1513 typegraph_stats_buffer(uintptr_t addr, void *ignored, tg_stats_t *stats)
1514 {
1515 tg_node_t *node;
1516
1517 stats->tgs_buffers++;
1518
1519 if ((node = typegraph_search(addr)) == NULL) {
1520 return (WALK_NEXT);
1521 }
1522
1523 typegraph_stats_node(node, stats);
1524
1525 return (WALK_NEXT);
1526 }
1527
1528 /*ARGSUSED*/
1529 void
typegraph_stat_print(char * name,size_t stat)1530 typegraph_stat_print(char *name, size_t stat)
1531 {
1532 mdb_printf("typegraph: ");
1533
1534 if (name == NULL) {
1535 mdb_printf("\n");
1536 return;
1537 }
1538
1539 mdb_printf("%30s => %ld\n", name, stat);
1540 }
1541
1542 static void
typegraph_stat_str(char * name,char * str)1543 typegraph_stat_str(char *name, char *str)
1544 {
1545 mdb_printf("typegraph: %30s => %s\n", name, str);
1546 }
1547
1548 static void
typegraph_stat_perc(char * name,size_t stat,size_t total)1549 typegraph_stat_perc(char *name, size_t stat, size_t total)
1550 {
1551 int perc = (stat * 100) / total;
1552 int tenths = ((stat * 1000) / total) % 10;
1553
1554 mdb_printf("typegraph: %30s => %-13ld (%2d.%1d%%)\n", name, stat,
1555 perc, tenths);
1556 }
1557
1558 static void
typegraph_stat_time(int last)1559 typegraph_stat_time(int last)
1560 {
1561 static hrtime_t ts;
1562 hrtime_t pass;
1563
1564 if (ts == 0) {
1565 pass = (ts = gethrtime()) - tg_start;
1566 } else {
1567 hrtime_t now = gethrtime();
1568
1569 pass = now - ts;
1570 ts = now;
1571 }
1572
1573 mdb_printf("typegraph: %30s => %lld seconds\n",
1574 "time elapsed, this pass", pass / NANOSEC);
1575 mdb_printf("typegraph: %30s => %lld seconds\n",
1576 "time elapsed, total", (ts - tg_start) / NANOSEC);
1577 mdb_printf("typegraph:\n");
1578
1579 if (last)
1580 ts = 0;
1581 }
1582
1583 static void
typegraph_stats(void)1584 typegraph_stats(void)
1585 {
1586 size_t i, n;
1587 tg_stats_t stats;
1588
1589 bzero(&stats, sizeof (stats));
1590
1591 for (i = 0; i < tg_nnodes - tg_nanchored; i++)
1592 typegraph_stats_node(&tg_node[i], &stats);
1593
1594 n = stats.tgs_nodes;
1595
1596 typegraph_stat_print("pass", tg_pass);
1597 typegraph_stat_print("nodes", n);
1598 typegraph_stat_perc("unmarked", stats.tgs_unmarked, n);
1599 typegraph_stat_perc("known", stats.tgs_known, n);
1600 typegraph_stat_perc("conjectured", stats.tgs_typed, n);
1601 typegraph_stat_perc("conjectured fragments", stats.tgs_frag, n);
1602 typegraph_stat_perc("known or conjectured",
1603 stats.tgs_known + stats.tgs_typed + stats.tgs_frag, n);
1604 typegraph_stat_print("conflicts", stats.tgs_conflicts);
1605 typegraph_stat_print("candidates", stats.tgs_candidates);
1606 typegraph_stat_time(0);
1607 }
1608
1609 /*
1610 * This is called both in pass1 and in subsequent passes (to propagate new type
1611 * inferences).
1612 */
1613 static void
typegraph_pass1_node(tg_node_t * node,mdb_ctf_id_t type)1614 typegraph_pass1_node(tg_node_t *node, mdb_ctf_id_t type)
1615 {
1616 tg_todo_t *first = NULL, *last = NULL, *free = NULL, *this = NULL;
1617 tg_todo_t *todo;
1618 tg_edge_t *e;
1619 uintptr_t offs = 0;
1620 size_t size;
1621 const char *member;
1622
1623 if (!mdb_ctf_type_valid(type))
1624 return;
1625 again:
1626 /*
1627 * For each of the nodes corresponding to our outgoing edges,
1628 * determine their type.
1629 */
1630 size = typegraph_size(type);
1631
1632 for (e = node->tgn_outgoing; e != NULL; e = e->tge_nextout) {
1633 mdb_ctf_id_t ntype, rtype;
1634 size_t nsize;
1635 int kind;
1636
1637 /*
1638 * If we're being called in pass1, we're very conservative:
1639 *
1640 * (a) If the outgoing edge is beyond the size of the type
1641 * (and the current node is not the root), we refuse to
1642 * descend. This situation isn't actually hopeless -- we
1643 * could be looking at array of the projected type -- but
1644 * we'll allow a later phase to pass in that node and its
1645 * conjectured type as the root.
1646 *
1647 * (b) If the outgoing edge has a destination offset of
1648 * something other than 0, we'll descend, but we won't
1649 * add the type to the type list of the destination node.
1650 * This allows us to gather information that can later be
1651 * used to perform a more constrained search.
1652 */
1653 if (tg_pass == TG_PASS1 && e->tge_srcoffs - offs > size)
1654 continue;
1655
1656 if (offs >= typegraph_size(type))
1657 continue;
1658
1659 if (e->tge_srcoffs < offs)
1660 continue;
1661
1662 if (e->tge_marked)
1663 continue;
1664
1665 ntype = typegraph_type_offset(type,
1666 e->tge_srcoffs - offs, e, &member);
1667
1668 if (!mdb_ctf_type_valid(ntype))
1669 continue;
1670
1671 if ((kind = mdb_ctf_type_kind(ntype)) != CTF_K_POINTER)
1672 continue;
1673
1674 if (mdb_ctf_type_reference(ntype, &rtype) == -1)
1675 continue;
1676
1677 if (!mdb_ctf_type_valid(ntype = typegraph_resolve(rtype)))
1678 continue;
1679
1680 kind = mdb_ctf_type_kind(ntype);
1681 nsize = mdb_ctf_type_size(ntype);
1682
1683 if (nsize > TG_NODE_SIZE(e->tge_dest) - e->tge_destoffs)
1684 continue;
1685
1686 typegraph_node_addtype(e->tge_dest, e, type,
1687 member, e->tge_srcoffs - offs, rtype, ntype);
1688
1689 if (e->tge_dest->tgn_marked)
1690 continue;
1691
1692 /*
1693 * If our destination offset is 0 and the type that we marked
1694 * it with is useful, mark the node that we're
1695 * going to visit. And regardless, mark the edge.
1696 */
1697 if (e->tge_destoffs == 0 && kind == CTF_K_STRUCT)
1698 e->tge_dest->tgn_marked = 1;
1699
1700 e->tge_marked = 1;
1701
1702 /*
1703 * If this isn't a structure, it's pointless to descend.
1704 */
1705 if (kind != CTF_K_STRUCT)
1706 continue;
1707
1708 if (nsize <= TG_NODE_SIZE(e->tge_dest) / 2) {
1709 tg_node_t *dest = e->tge_dest;
1710
1711 /*
1712 * If the conjectured type is less than half of the
1713 * size of the object, we might be dealing with a
1714 * polymorphic type. It's dangerous to descend in
1715 * this case -- if our conjectured type is larger than
1716 * the actual type, we will mispropagate. (See the
1717 * description for phenomenon (c) in the block comment
1718 * for how this condition can arise.) We therefore
1719 * only descend if we are in pass4 and there is only
1720 * one inference for this node.
1721 */
1722 if (tg_pass < TG_PASS4)
1723 continue;
1724
1725 if (dest->tgn_typelist == NULL ||
1726 dest->tgn_typelist->tgt_next != NULL) {
1727 /*
1728 * There is either no inference for this node,
1729 * or more than one -- in either case, chicken
1730 * out.
1731 */
1732 continue;
1733 }
1734 }
1735
1736 if (free != NULL) {
1737 todo = free;
1738 free = free->tgtd_next;
1739 } else {
1740 todo = mdb_alloc(sizeof (tg_todo_t), UM_SLEEP);
1741 }
1742
1743 todo->tgtd_node = e->tge_dest;
1744 todo->tgtd_type = ntype;
1745 todo->tgtd_offs = e->tge_destoffs;
1746 todo->tgtd_next = NULL;
1747
1748 if (last == NULL) {
1749 first = last = todo;
1750 } else {
1751 last->tgtd_next = todo;
1752 last = todo;
1753 }
1754 }
1755
1756 /*
1757 * If this was from a to-do list, it needs to be freed.
1758 */
1759 if (this != NULL) {
1760 this->tgtd_next = free;
1761 free = this;
1762 }
1763
1764 /*
1765 * Now peel something off of the to-do list.
1766 */
1767 if (first != NULL) {
1768 this = first;
1769 first = first->tgtd_next;
1770 if (first == NULL)
1771 last = NULL;
1772
1773 node = this->tgtd_node;
1774 offs = this->tgtd_offs;
1775 type = this->tgtd_type;
1776 goto again;
1777 }
1778
1779 /*
1780 * Nothing more to do -- free the to-do list.
1781 */
1782 while (free != NULL) {
1783 this = free->tgtd_next;
1784 mdb_free(free, sizeof (tg_todo_t));
1785 free = this;
1786 }
1787 }
1788
1789 static void
typegraph_pass1(void)1790 typegraph_pass1(void)
1791 {
1792 int i;
1793
1794 tg_pass = TG_PASS1;
1795 for (i = 0; i < tg_nnodes; i++)
1796 typegraph_pass1_node(&tg_node[i], tg_node[i].tgn_type);
1797 }
1798
1799 static void
typegraph_pass2_node(tg_node_t * node)1800 typegraph_pass2_node(tg_node_t *node)
1801 {
1802 mdb_ctf_id_t type, ntype;
1803 size_t tsize, nsize, rem, offs, limit;
1804 uintptr_t base, addr;
1805 int fam, kind;
1806 tg_type_t *tp, *found = NULL;
1807
1808 if (mdb_ctf_type_valid(node->tgn_type))
1809 return;
1810
1811 for (tp = node->tgn_typelist; tp != NULL; tp = tp->tgt_next) {
1812 if ((kind = mdb_ctf_type_kind(tp->tgt_type)) == CTF_K_UNION) {
1813 /*
1814 * Fucking unions...
1815 */
1816 found = NULL;
1817 break;
1818 }
1819
1820 if (kind == CTF_K_POINTER || kind == CTF_K_STRUCT) {
1821 if (found != NULL) {
1822 /*
1823 * There's more than one interpretation for
1824 * this structure; for now, we punt.
1825 */
1826 found = NULL;
1827 break;
1828 }
1829 found = tp;
1830 }
1831 }
1832
1833 if (found == NULL ||
1834 (found->tgt_flags & (TG_TYPE_ARRAY | TG_TYPE_NOTARRAY)))
1835 return;
1836
1837 fam = typegraph_hasfam(type = found->tgt_type, &ntype);
1838
1839 if (fam) {
1840 /*
1841 * If this structure has a flexible array member, and the
1842 * FAM type isn't a struct or pointer, we're going to treat
1843 * it as if it did not have a FAM.
1844 */
1845 kind = mdb_ctf_type_kind(ntype);
1846
1847 if (kind != CTF_K_POINTER && kind != CTF_K_STRUCT)
1848 fam = 0;
1849 }
1850
1851 tsize = typegraph_size(type);
1852 nsize = TG_NODE_SIZE(node);
1853
1854 if (!fam) {
1855 /*
1856 * If this doesn't have a flexible array member, and our
1857 * preferred type is greater than half the size of the node, we
1858 * won't try to treat it as an array.
1859 */
1860 if (tsize > nsize / 2)
1861 return;
1862
1863 if ((rem = (nsize % tsize)) != 0) {
1864 /*
1865 * If the next-smaller cache size is zero, we were
1866 * expecting the type size to evenly divide the node
1867 * size -- we must not have the right type.
1868 */
1869 if (node->tgn_smaller == 0)
1870 return;
1871
1872 if (nsize - rem <= node->tgn_smaller) {
1873 /*
1874 * If this were really an array of this type,
1875 * we would have allocated it out of a smaller
1876 * cache -- it's either not an array (e.g.,
1877 * it's a bigger, unknown structure) or it's an
1878 * array of some other type. In either case,
1879 * we punt.
1880 */
1881 return;
1882 }
1883 }
1884 }
1885
1886 /*
1887 * So far, this looks like it might be an array.
1888 */
1889 if (node->tgn_smaller != 0) {
1890 limit = node->tgn_smaller;
1891 } else {
1892 limit = TG_NODE_SIZE(node);
1893 }
1894
1895 base = node->tgn_base;
1896
1897 if (fam) {
1898 found->tgt_flags |= TG_TYPE_HASFAM;
1899
1900 for (offs = 0; offs < limit; ) {
1901 ntype = typegraph_type_offset(type, offs, NULL, NULL);
1902
1903 if (!mdb_ctf_type_valid(ntype)) {
1904 offs++;
1905 continue;
1906 }
1907
1908 if (!typegraph_couldbe(base + offs, ntype)) {
1909 found->tgt_flags |= TG_TYPE_NOTARRAY;
1910 return;
1911 }
1912
1913 offs += mdb_ctf_type_size(ntype);
1914 }
1915 } else {
1916 for (offs = 0; offs < tsize; ) {
1917 ntype = typegraph_type_offset(type, offs, NULL, NULL);
1918
1919 if (!mdb_ctf_type_valid(ntype)) {
1920 offs++;
1921 continue;
1922 }
1923
1924 for (addr = base + offs; addr < base + limit;
1925 addr += tsize) {
1926 if (typegraph_couldbe(addr, ntype))
1927 continue;
1928
1929 found->tgt_flags |= TG_TYPE_NOTARRAY;
1930 return;
1931 }
1932
1933 offs += mdb_ctf_type_size(ntype);
1934 continue;
1935 }
1936 }
1937
1938 /*
1939 * Now mark this type as an array, and reattempt pass1 from this node.
1940 */
1941 found->tgt_flags |= TG_TYPE_ARRAY;
1942 typegraph_pass1_node(node, type);
1943 }
1944
1945 static void
typegraph_pass2(void)1946 typegraph_pass2(void)
1947 {
1948 int i;
1949
1950 tg_pass = TG_PASS2;
1951 do {
1952 tg_improved = 0;
1953
1954 for (i = 0; i < tg_nnodes; i++)
1955 typegraph_pass2_node(&tg_node[i]);
1956 } while (tg_improved);
1957 }
1958
1959 static void
typegraph_pass3(void)1960 typegraph_pass3(void)
1961 {
1962 tg_node_t *node;
1963 tg_type_t *tp;
1964 size_t i;
1965 uintptr_t loffs;
1966
1967 tg_pass = TG_PASS3;
1968 loffs = offsetof(tg_node_t, tgn_typelist);
1969
1970 again:
1971 /*
1972 * In this pass, we're going to coalesce types. We're looking for
1973 * nodes where one possible type is a structure, and another is
1974 * either a CTF_K_INTEGER variant (e.g. "char", "void") or a
1975 * CTF_K_FORWARD (an opaque forward definition).
1976 *
1977 * N.B. It might appear to be beneficial to coalesce types when
1978 * the possibilities include two structures, and one is contained
1979 * within the other (e.g., "door_node" contains a "vnode" as its
1980 * first member; "vnode" could be smooshed, leaving just "door_node").
1981 * This optimization is overly aggressive, however: there are too
1982 * many places where we pull stunts with structures such that they're
1983 * actually polymorphic (e.g., "nc_cache" and "ncache"). Performing
1984 * this optimization would run the risk of false propagation --
1985 * which we want to avoid if at all possible.
1986 */
1987 for (i = 0; i < tg_nnodes; i++) {
1988 tg_type_t **list;
1989
1990 list = (tg_type_t **)((uintptr_t)(node = &tg_node[i]) + loffs);
1991
1992 if (mdb_ctf_type_valid(node->tgn_type))
1993 continue;
1994
1995 if (*list == NULL)
1996 continue;
1997
1998 /*
1999 * First, scan for type CTF_K_STRUCT. If we find it, eliminate
2000 * everything that's a CTF_K_INTEGER or CTF_K_FORWARD.
2001 */
2002 for (tp = *list; tp != NULL; tp = tp->tgt_next) {
2003 if (mdb_ctf_type_kind(tp->tgt_type) == CTF_K_STRUCT)
2004 break;
2005 }
2006
2007 if (tp != NULL) {
2008 tg_type_t *prev = NULL, *next;
2009
2010 for (tp = *list; tp != NULL; tp = next) {
2011 int kind = mdb_ctf_type_kind(tp->tgt_type);
2012
2013 next = tp->tgt_next;
2014
2015 if (kind == CTF_K_INTEGER ||
2016 kind == CTF_K_FORWARD) {
2017 if (prev == NULL) {
2018 *list = next;
2019 } else {
2020 prev->tgt_next = next;
2021 }
2022
2023 mdb_free(tp, sizeof (tg_type_t));
2024 } else {
2025 prev = tp;
2026 }
2027 }
2028 }
2029 }
2030
2031 if (loffs == offsetof(tg_node_t, tgn_typelist)) {
2032 loffs = offsetof(tg_node_t, tgn_fraglist);
2033 goto again;
2034 }
2035 }
2036
2037 static void
typegraph_pass4_node(tg_node_t * node)2038 typegraph_pass4_node(tg_node_t *node)
2039 {
2040 tg_edge_t *e;
2041 mdb_ctf_id_t type, ntype;
2042 tg_node_t *src = NULL;
2043 int kind;
2044
2045 if (mdb_ctf_type_valid(node->tgn_type))
2046 return;
2047
2048 if (node->tgn_typelist != NULL)
2049 return;
2050
2051 mdb_ctf_type_invalidate(&type);
2052
2053 /*
2054 * Now we want to iterate over all incoming edges. If we can find an
2055 * incoming edge pointing to offset 0 from a node of known or
2056 * conjectured type, check the types of the referring node.
2057 */
2058 for (e = node->tgn_incoming; e != NULL; e = e->tge_nextin) {
2059 tg_node_t *n = e->tge_src;
2060
2061 if (e->tge_destoffs != 0)
2062 continue;
2063
2064 if (!mdb_ctf_type_valid(ntype = n->tgn_type)) {
2065 if (n->tgn_typelist != NULL &&
2066 n->tgn_typelist->tgt_next == NULL) {
2067 ntype = n->tgn_typelist->tgt_type;
2068 }
2069
2070 if (!mdb_ctf_type_valid(ntype))
2071 continue;
2072 }
2073
2074 kind = mdb_ctf_type_kind(ntype);
2075
2076 if (kind != CTF_K_STRUCT && kind != CTF_K_POINTER)
2077 continue;
2078
2079 if (src != NULL && mdb_ctf_type_cmp(type, ntype) != 0) {
2080 /*
2081 * We have two valid, potentially conflicting
2082 * interpretations for this node -- chicken out.
2083 */
2084 src = NULL;
2085 break;
2086 }
2087
2088 src = n;
2089 type = ntype;
2090 }
2091
2092 if (src != NULL)
2093 typegraph_pass1_node(src, type);
2094 }
2095
2096 static void
typegraph_pass4(void)2097 typegraph_pass4(void)
2098 {
2099 size_t i, conjectured[2], gen = 0;
2100
2101 conjectured[1] = tg_nnodes;
2102
2103 tg_pass = TG_PASS4;
2104 do {
2105 conjectured[gen] = 0;
2106
2107 for (i = 0; i < tg_nnodes; i++) {
2108 if (tg_node[i].tgn_typelist != NULL)
2109 conjectured[gen]++;
2110 typegraph_pass4_node(&tg_node[i]);
2111 }
2112
2113 /*
2114 * Perform another pass3 to coalesce any new conflicts.
2115 */
2116 typegraph_pass3();
2117 tg_pass = TG_PASS4;
2118 gen ^= 1;
2119 } while (conjectured[gen ^ 1] < conjectured[gen]);
2120 }
2121
2122 static void
typegraph_postpass_node(tg_node_t * node)2123 typegraph_postpass_node(tg_node_t *node)
2124 {
2125 size_t total = 0;
2126 tg_edge_t *e, *edge = node->tgn_outgoing;
2127 tg_poststate_t *free = NULL, *stack = NULL, *state;
2128 tg_node_t *dest;
2129
2130 if (node->tgn_postmarked)
2131 return;
2132
2133 push:
2134 node->tgn_postmarked = 1;
2135 node->tgn_reach = 0;
2136
2137 pop:
2138 for (e = edge; e != NULL; e = e->tge_nextout) {
2139 dest = e->tge_dest;
2140
2141 if (dest->tgn_postmarked)
2142 continue;
2143
2144 /*
2145 * Add a new element and descend.
2146 */
2147 if (free == NULL) {
2148 state = mdb_alloc(sizeof (tg_poststate_t), UM_SLEEP);
2149 } else {
2150 state = free;
2151 free = free->tgps_next;
2152 }
2153
2154 state->tgps_node = node;
2155 state->tgps_edge = e;
2156 state->tgps_total = total;
2157 state->tgps_next = stack;
2158 stack = state;
2159
2160 node = dest;
2161 edge = dest->tgn_outgoing;
2162 goto push;
2163 }
2164
2165 if (!mdb_ctf_type_valid(node->tgn_type) &&
2166 node->tgn_typelist == NULL && node->tgn_fraglist == NULL) {
2167 /*
2168 * We are an unknown node; our count must reflect this.
2169 */
2170 node->tgn_reach++;
2171 }
2172
2173 /*
2174 * Now we need to check for state to pop.
2175 */
2176 if ((state = stack) != NULL) {
2177 edge = state->tgps_edge;
2178 node = state->tgps_node;
2179 total = state->tgps_total;
2180 dest = edge->tge_dest;
2181
2182 stack = state->tgps_next;
2183 state->tgps_next = free;
2184 free = state;
2185
2186 if (!mdb_ctf_type_valid(dest->tgn_type) &&
2187 dest->tgn_typelist == NULL && dest->tgn_fraglist == NULL) {
2188 /*
2189 * We only sum our child's reach into our own if
2190 * that child is of unknown type. This prevents long
2191 * chains of non-increasing reach.
2192 */
2193 node->tgn_reach += dest->tgn_reach;
2194 }
2195
2196 edge = edge->tge_nextout;
2197 goto pop;
2198 }
2199
2200 /*
2201 * We need to free our freelist.
2202 */
2203 while (free != NULL) {
2204 state = free;
2205 free = free->tgps_next;
2206 mdb_free(state, sizeof (tg_poststate_t));
2207 }
2208 }
2209
2210 static void
typegraph_postpass(void)2211 typegraph_postpass(void)
2212 {
2213 int i, max = 0;
2214 tg_node_t *node, *maxnode = NULL;
2215 char c[256];
2216
2217 for (i = 0; i < tg_nnodes; i++)
2218 tg_node[i].tgn_postmarked = 0;
2219
2220 /*
2221 * From those nodes with unknown type and no outgoing edges, we want
2222 * to eminate towards the root.
2223 */
2224 for (i = tg_nnodes - tg_nanchored; i < tg_nnodes; i++) {
2225 node = &tg_node[i];
2226
2227 typegraph_postpass_node(node);
2228 }
2229
2230 for (i = 0; i < tg_nnodes - tg_nanchored; i++) {
2231 node = &tg_node[i];
2232
2233 if (mdb_ctf_type_valid(node->tgn_type))
2234 continue;
2235
2236 if (node->tgn_reach < max)
2237 continue;
2238
2239 maxnode = node;
2240 max = node->tgn_reach;
2241 }
2242
2243 typegraph_stat_str("pass", "post");
2244
2245 if (maxnode != NULL) {
2246 mdb_snprintf(c, sizeof (c), "%p",
2247 maxnode->tgn_base, maxnode->tgn_reach);
2248 } else {
2249 strcpy(c, "-");
2250 }
2251
2252 typegraph_stat_print("nodes", tg_nnodes - tg_nanchored);
2253 typegraph_stat_str("greatest unknown node reach", c);
2254 typegraph_stat_perc("reachable unknown nodes",
2255 max, tg_nnodes - tg_nanchored);
2256 typegraph_stat_time(1);
2257 }
2258
2259 static void
typegraph_allpass(int first)2260 typegraph_allpass(int first)
2261 {
2262 size_t i;
2263 tg_edge_t *e;
2264
2265 if (!first)
2266 tg_start = gethrtime();
2267
2268 for (i = 0; i < tg_nnodes; i++) {
2269 tg_node[i].tgn_marked = 0;
2270 tg_node[i].tgn_postmarked = 0;
2271
2272 for (e = tg_node[i].tgn_incoming; e != NULL; e = e->tge_nextin)
2273 e->tge_marked = 0;
2274 }
2275
2276 typegraph_pass1();
2277 typegraph_stats();
2278 typegraph_pass2();
2279 typegraph_stats();
2280 typegraph_pass3();
2281 typegraph_stats();
2282 typegraph_pass4();
2283 typegraph_stats();
2284 typegraph_postpass();
2285 }
2286
2287 /*ARGSUSED*/
2288 static int
typegraph_modctl(uintptr_t addr,const struct modctl * m,int * ignored)2289 typegraph_modctl(uintptr_t addr, const struct modctl *m, int *ignored)
2290 {
2291 struct typegraph_ctf_module mod;
2292 tg_node_t *node;
2293 mdb_ctf_id_t type;
2294
2295 if (m->mod_mp == NULL)
2296 return (WALK_NEXT);
2297
2298 if (mdb_ctf_vread(&mod, "struct module", "struct typegraph_ctf_module",
2299 (uintptr_t)m->mod_mp, 0) == -1) {
2300 mdb_warn("couldn't read modctl %p's module", addr);
2301 return (WALK_NEXT);
2302 }
2303
2304 /*
2305 * As long as we're here, we're going to mark the address pointed
2306 * to by mod_mp as a "struct module" (mod_mp is defined to be a
2307 * void *). Yes, this is a horrible kludge -- but it's not like
2308 * this code isn't already depending on the fact that mod_mp is
2309 * actually a pointer to "struct module" (see the mdb_vread(), above).
2310 * Without this, we can't identify any of the objects allocated by
2311 * krtld.
2312 */
2313 if ((node = typegraph_search((uintptr_t)m->mod_mp)) != NULL) {
2314 if (mdb_ctf_lookup_by_name("struct module", &type) != -1)
2315 node->tgn_type = type;
2316 }
2317
2318 typegraph_build((uintptr_t)mod.data, mod.data_size);
2319 typegraph_build((uintptr_t)mod.bss, mod.bss_size);
2320
2321 return (WALK_NEXT);
2322 }
2323
2324 static void
typegraph_sort(void)2325 typegraph_sort(void)
2326 {
2327 size_t i;
2328
2329 if (tg_sorted)
2330 mdb_free(tg_sorted, tg_nsorted * sizeof (tg_node_t *));
2331
2332 tg_nsorted = tg_nnodes;
2333 tg_sorted = mdb_alloc(tg_nsorted * sizeof (tg_node_t *), UM_SLEEP);
2334
2335 for (i = 0; i < tg_nsorted; i++)
2336 tg_sorted[i] = &tg_node[i];
2337
2338 qsort(tg_sorted, tg_nsorted, sizeof (tg_node_t *), typegraph_nodecmp);
2339 }
2340
2341 static void
typegraph_known_node(uintptr_t addr,const char * typename)2342 typegraph_known_node(uintptr_t addr, const char *typename)
2343 {
2344 tg_node_t *node;
2345 mdb_ctf_id_t type;
2346
2347 if ((node = typegraph_search(addr)) == NULL) {
2348 mdb_warn("couldn't find node corresponding to "
2349 "%s at %p\n", typename, addr);
2350 return;
2351 }
2352
2353 if (mdb_ctf_lookup_by_name(typename, &type) == -1) {
2354 mdb_warn("couldn't find type for '%s'", typename);
2355 return;
2356 }
2357
2358 node->tgn_type = type;
2359 }
2360
2361 /*
2362 * There are a few important nodes that are impossible to figure out without
2363 * some carnal knowledge.
2364 */
2365 static void
typegraph_known_nodes(void)2366 typegraph_known_nodes(void)
2367 {
2368 uintptr_t segkp;
2369
2370 if (mdb_readvar(&segkp, "segkp") == -1) {
2371 mdb_warn("couldn't read 'segkp'");
2372 } else {
2373 struct seg seg;
2374
2375 if (mdb_vread(&seg, sizeof (seg), segkp) == -1) {
2376 mdb_warn("couldn't read seg at %p", segkp);
2377 } else {
2378 typegraph_known_node((uintptr_t)seg.s_data,
2379 "struct segkp_segdata");
2380 }
2381 }
2382 }
2383
2384 /*ARGSUSED*/
2385 int
typegraph(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2386 typegraph(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2387 {
2388 size_t est = 0;
2389 tg_node_t *tgp;
2390 kmem_cache_t c;
2391 tg_stats_t stats;
2392 mdb_ctf_id_t type;
2393 int wasbuilt = tg_built;
2394 uintptr_t kstat_arena;
2395 uint_t perc;
2396 int i;
2397
2398 if (!mdb_prop_postmortem) {
2399 mdb_warn("typegraph: can only be run on a system "
2400 "dump; see dumpadm(8)\n");
2401 return (DCMD_ERR);
2402 }
2403
2404 tg_verbose = 0;
2405
2406 if (mdb_getopts(argc, argv,
2407 'v', MDB_OPT_SETBITS, TRUE, &tg_verbose, NULL) != argc)
2408 return (DCMD_USAGE);
2409
2410 if (tg_built)
2411 goto trace;
2412
2413 tg_start = gethrtime();
2414 typegraph_stat_str("pass", "initial");
2415 typegraph_typetab_init();
2416
2417 /*
2418 * First, we need an estimate on the number of buffers.
2419 */
2420 if (mdb_walk("kmem_cache",
2421 (mdb_walk_cb_t)typegraph_estimate, &est) == -1) {
2422 mdb_warn("couldn't walk 'kmem_cache'");
2423 return (DCMD_ERR);
2424 }
2425
2426 if (mdb_walk("modctl",
2427 (mdb_walk_cb_t)typegraph_estimate_modctl, &est) == -1) {
2428 mdb_warn("couldn't walk 'modctl'");
2429 return (DCMD_ERR);
2430 }
2431
2432 if (mdb_walk("vmem",
2433 (mdb_walk_cb_t)typegraph_estimate_vmem, &est) == -1) {
2434 mdb_warn("couldn't walk 'vmem'");
2435 return (DCMD_ERR);
2436 }
2437
2438 typegraph_stat_print("maximum nodes", est);
2439
2440 tgp = tg_node = mdb_zalloc(sizeof (tg_node_t) * est, UM_SLEEP);
2441 for (i = 0; i < est; i++)
2442 mdb_ctf_type_invalidate(&tg_node[i].tgn_type);
2443
2444 if (mdb_walk("vmem", (mdb_walk_cb_t)typegraph_vmem, &tgp) == -1) {
2445 mdb_warn("couldn't walk 'vmem'");
2446 return (DCMD_ERR);
2447 }
2448
2449 if (mdb_walk("kmem_cache", (mdb_walk_cb_t)typegraph_kmem, &tgp) == -1) {
2450 mdb_warn("couldn't walk 'kmem_cache'");
2451 return (DCMD_ERR);
2452 }
2453
2454 tg_nnodes = tgp - tg_node;
2455
2456 typegraph_stat_print("actual nodes", tg_nnodes);
2457
2458 typegraph_sort();
2459
2460 if (mdb_ctf_lookup_by_name("kthread_t", &type) == -1) {
2461 mdb_warn("couldn't find 'kthread_t'");
2462 return (DCMD_ERR);
2463 }
2464
2465 if (mdb_walk("thread", (mdb_walk_cb_t)typegraph_thread, &type) == -1) {
2466 mdb_warn("couldn't walk 'thread'");
2467 return (DCMD_ERR);
2468 }
2469
2470 if (mdb_ctf_lookup_by_name("ekstat_t", &type) == -1) {
2471 mdb_warn("couldn't find 'ekstat_t'");
2472 return (DCMD_ERR);
2473 }
2474
2475 if (mdb_readvar(&kstat_arena, "kstat_arena") == -1) {
2476 mdb_warn("couldn't read 'kstat_arena'");
2477 return (DCMD_ERR);
2478 }
2479
2480 if (mdb_pwalk("vmem_alloc", (mdb_walk_cb_t)typegraph_kstat,
2481 &type, kstat_arena) == -1) {
2482 mdb_warn("couldn't walk kstat vmem arena");
2483 return (DCMD_ERR);
2484 }
2485
2486 if (mdb_walk("modctl", (mdb_walk_cb_t)typegraph_modctl, NULL) == -1) {
2487 mdb_warn("couldn't walk 'modctl'");
2488 return (DCMD_ERR);
2489 }
2490
2491 typegraph_stat_print("anchored nodes", tg_nanchored);
2492 tg_nnodes += tg_nanchored;
2493 typegraph_sort();
2494 typegraph_known_nodes();
2495 typegraph_stat_time(0);
2496 tg_built = 1;
2497
2498 trace:
2499 if (!wasbuilt || !(flags & DCMD_ADDRSPEC)) {
2500 typegraph_allpass(!wasbuilt);
2501 return (DCMD_OK);
2502 }
2503
2504 bzero(&stats, sizeof (stats));
2505
2506 /*
2507 * If we've been given an address, it's a kmem cache.
2508 */
2509 if (mdb_vread(&c, sizeof (c), addr) == -1) {
2510 mdb_warn("couldn't read kmem_cache at %p", addr);
2511 return (DCMD_ERR);
2512 }
2513
2514 if (mdb_pwalk("kmem",
2515 (mdb_walk_cb_t)typegraph_stats_buffer, &stats, addr) == -1) {
2516 mdb_warn("can't walk kmem for cache %p", addr);
2517 return (DCMD_ERR);
2518 }
2519
2520 if (DCMD_HDRSPEC(flags))
2521 mdb_printf("%-25s %7s %7s %7s %7s %7s %7s %5s\n", "NAME",
2522 "BUFS", "NODES", "UNMRK", "KNOWN",
2523 "INFER", "FRAG", "HIT%");
2524
2525 if (stats.tgs_nodes) {
2526 perc = ((stats.tgs_known + stats.tgs_typed +
2527 stats.tgs_frag) * 1000) / stats.tgs_nodes;
2528 } else {
2529 perc = 0;
2530 }
2531
2532 mdb_printf("%-25s %7ld %7ld %7ld %7ld %7ld %7ld %3d.%1d\n",
2533 c.cache_name, stats.tgs_buffers, stats.tgs_nodes,
2534 stats.tgs_unmarked, stats.tgs_known, stats.tgs_typed,
2535 stats.tgs_frag, perc / 10, perc % 10);
2536
2537 return (DCMD_OK);
2538 }
2539
2540 int
typegraph_built(void)2541 typegraph_built(void)
2542 {
2543 if (!tg_built) {
2544 mdb_warn("type graph not yet built; run ::typegraph.\n");
2545 return (0);
2546 }
2547
2548 return (1);
2549 }
2550
2551 int
whattype(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2552 whattype(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2553 {
2554 tg_node_t *node;
2555 tg_edge_t *e;
2556 char buf[MDB_SYM_NAMLEN];
2557 tg_type_t *tp;
2558 int verbose = 0;
2559
2560 if (mdb_getopts(argc, argv,
2561 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
2562 return (DCMD_USAGE);
2563
2564 if (!(flags & DCMD_ADDRSPEC))
2565 return (DCMD_USAGE);
2566
2567 if (!typegraph_built())
2568 return (DCMD_ABORT);
2569
2570 if ((node = typegraph_search(addr)) == NULL) {
2571 mdb_warn("%p does not correspond to a node.\n", addr);
2572 return (DCMD_OK);
2573 }
2574
2575 if (!verbose) {
2576 mdb_printf("%p is %p+%p, ", addr, node->tgn_base,
2577 addr - node->tgn_base);
2578
2579 if (mdb_ctf_type_valid(node->tgn_type)) {
2580 mdb_printf("%s\n", mdb_ctf_type_name(node->tgn_type,
2581 buf, sizeof (buf)));
2582 return (DCMD_OK);
2583 }
2584
2585 if ((tp = node->tgn_typelist) == NULL) {
2586 if ((tp = node->tgn_fraglist) == NULL) {
2587 mdb_printf("unknown type\n");
2588 return (DCMD_OK);
2589 }
2590 }
2591
2592 if (tp->tgt_next == NULL && mdb_ctf_type_valid(tp->tgt_type)) {
2593 int kind = mdb_ctf_type_kind(tp->tgt_type);
2594 size_t offs = tp->tgt_redge->tge_destoffs;
2595
2596 mdb_printf("possibly %s%s ",
2597 tp->tgt_flags & TG_TYPE_ARRAY ? "array of " : "",
2598 typegraph_type_name(tp->tgt_type, tp->tgt_utype));
2599
2600 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION &&
2601 mdb_ctf_type_valid(tp->tgt_rtype) &&
2602 tp->tgt_rmember != NULL) {
2603 mdb_printf("(%s.%s) ",
2604 mdb_ctf_type_name(tp->tgt_rtype, buf,
2605 sizeof (buf)), tp->tgt_rmember);
2606 }
2607
2608 if (offs != 0)
2609 mdb_printf("at %p", node->tgn_base + offs);
2610
2611 mdb_printf("\n");
2612 return (DCMD_OK);
2613 }
2614
2615 mdb_printf("possibly one of the following:\n");
2616
2617 for (; tp != NULL; tp = tp->tgt_next) {
2618 size_t offs = tp->tgt_redge->tge_destoffs;
2619
2620 mdb_printf(" %s%s ",
2621 tp->tgt_flags & TG_TYPE_ARRAY ? "array of " : "",
2622 typegraph_type_name(tp->tgt_type, tp->tgt_utype));
2623
2624 if (offs != 0)
2625 mdb_printf("at %p ", node->tgn_base + offs);
2626
2627 mdb_printf("(from %p+%p, type %s)\n",
2628 tp->tgt_redge->tge_src->tgn_base,
2629 tp->tgt_redge->tge_srcoffs,
2630 mdb_ctf_type_name(tp->tgt_rtype,
2631 buf, sizeof (buf)) != NULL ? buf : "<unknown>");
2632 }
2633
2634 mdb_printf("\n");
2635
2636 return (DCMD_OK);
2637 }
2638
2639 mdb_printf("%-?s %-?s %-29s %5s %5s %s\n", "BASE", "LIMIT", "TYPE",
2640 "SIZE", "REACH", "MRK");
2641 mdb_printf("%-?p %-?p %-29s %5d %5d %s\n",
2642 node->tgn_base, node->tgn_limit,
2643 mdb_ctf_type_name(node->tgn_type,
2644 buf, sizeof (buf)) != NULL ? buf : "<unknown>",
2645 typegraph_size(node->tgn_type), node->tgn_reach,
2646 node->tgn_marked ? "yes" : "no");
2647
2648 mdb_printf("\n");
2649 mdb_printf(" %-20s %?s %8s %-20s %s\n",
2650 "INFERENCE", "FROM", "SRCOFFS", "REFTYPE", "REFMEMBER");
2651
2652 for (tp = node->tgn_typelist; tp != NULL; tp = tp->tgt_next) {
2653 mdb_printf(" %-20s %?p %8p %-20s %s\n",
2654 typegraph_type_name(tp->tgt_type, tp->tgt_utype),
2655 tp->tgt_redge->tge_src->tgn_base,
2656 tp->tgt_redge->tge_srcoffs,
2657 mdb_ctf_type_name(tp->tgt_rtype,
2658 buf, sizeof (buf)) != NULL ? buf : "<unknown>",
2659 tp->tgt_rmember != NULL ? tp->tgt_rmember : "-");
2660 }
2661
2662 mdb_printf("\n");
2663 mdb_printf(" %-20s %?s %8s %-20s %s\n",
2664 "FRAGMENT", "FROM", "SRCOFFS", "REFTYPE", "REFMEMBER");
2665
2666 for (tp = node->tgn_fraglist; tp != NULL; tp = tp->tgt_next) {
2667 mdb_printf(" %-20s %?p %8p %-20s %s\n",
2668 typegraph_type_name(tp->tgt_type, tp->tgt_utype),
2669 tp->tgt_redge->tge_src->tgn_base,
2670 tp->tgt_redge->tge_srcoffs,
2671 mdb_ctf_type_name(tp->tgt_rtype,
2672 buf, sizeof (buf)) != NULL ? buf : "<unknown>",
2673 tp->tgt_rmember != NULL ? tp->tgt_rmember : "-");
2674 }
2675
2676 mdb_printf("\n");
2677
2678 mdb_printf(" %?s %8s %8s %6s %6s %5s\n", "FROM", "SRCOFFS", "DESTOFFS",
2679 "MARKED", "STATUS", "REACH");
2680
2681 for (e = node->tgn_incoming; e != NULL; e = e->tge_nextin) {
2682 tg_node_t *n = e->tge_src;
2683
2684 mdb_printf(" %?p %8p %8p %6s %6s %ld\n",
2685 n->tgn_base, e->tge_srcoffs, e->tge_destoffs,
2686 e->tge_marked ? "yes" : "no",
2687 mdb_ctf_type_valid(n->tgn_type) ? "known" :
2688 n->tgn_typelist != NULL ? "inferd" :
2689 n->tgn_fraglist != NULL ? "frgmnt" : "unknwn",
2690 n->tgn_reach);
2691 }
2692
2693 mdb_printf("\n %?s %8s %8s %6s %6s %5s\n", "TO", "SRCOFFS", "DESTOFFS",
2694 "MARKED", "STATUS", "REACH");
2695
2696 for (e = node->tgn_outgoing; e != NULL; e = e->tge_nextout) {
2697 tg_node_t *n = e->tge_dest;
2698
2699 mdb_printf(" %?p %8p %8p %6s %6s %ld\n",
2700 n->tgn_base, e->tge_srcoffs, e->tge_destoffs,
2701 e->tge_marked ? "yes" : "no",
2702 mdb_ctf_type_valid(n->tgn_type) ? "known" :
2703 n->tgn_typelist != NULL ? "inferd" :
2704 n->tgn_fraglist != NULL ? "frgmnt" : "unknwn",
2705 n->tgn_reach);
2706 }
2707
2708 mdb_printf("\n");
2709
2710 return (DCMD_OK);
2711 }
2712
2713 int
istype(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2714 istype(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2715 {
2716 tg_node_t *node;
2717 mdb_ctf_id_t type;
2718
2719 if (!(flags & DCMD_ADDRSPEC) || argc != 1 ||
2720 argv[0].a_type != MDB_TYPE_STRING)
2721 return (DCMD_USAGE);
2722
2723 if (!typegraph_built())
2724 return (DCMD_ABORT);
2725
2726 /*
2727 * Determine the node corresponding to the passed address.
2728 */
2729 if ((node = typegraph_search(addr)) == NULL) {
2730 mdb_warn("%p not found\n", addr);
2731 return (DCMD_ERR);
2732 }
2733
2734 /*
2735 * Now look up the specified type.
2736 */
2737 if (mdb_ctf_lookup_by_name(argv[0].a_un.a_str, &type) == -1) {
2738 mdb_warn("could not find type %s", argv[0].a_un.a_str);
2739 return (DCMD_ERR);
2740 }
2741
2742 node->tgn_type = type;
2743 typegraph_allpass(0);
2744
2745 return (DCMD_OK);
2746 }
2747
2748 /*ARGSUSED*/
2749 int
notype(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2750 notype(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2751 {
2752 tg_node_t *node;
2753
2754 if (!(flags & DCMD_ADDRSPEC) || argc != 0)
2755 return (DCMD_USAGE);
2756
2757 if (!typegraph_built())
2758 return (DCMD_ABORT);
2759
2760 if ((node = typegraph_search(addr)) == NULL) {
2761 mdb_warn("%p not found\n", addr);
2762 return (DCMD_ERR);
2763 }
2764
2765 mdb_ctf_type_invalidate(&node->tgn_type);
2766 typegraph_allpass(0);
2767
2768 return (DCMD_OK);
2769 }
2770
2771 int
typegraph_walk_init(mdb_walk_state_t * wsp)2772 typegraph_walk_init(mdb_walk_state_t *wsp)
2773 {
2774 wsp->walk_data = (void *)0;
2775 return (WALK_NEXT);
2776 }
2777
2778 int
typeconflict_walk_step(mdb_walk_state_t * wsp)2779 typeconflict_walk_step(mdb_walk_state_t *wsp)
2780 {
2781 size_t ndx;
2782 tg_node_t *node = NULL;
2783
2784 for (ndx = (size_t)wsp->walk_data; ndx < tg_nnodes; ndx++) {
2785 node = &tg_node[ndx];
2786
2787 if (mdb_ctf_type_valid(node->tgn_type))
2788 continue;
2789
2790 if (node->tgn_typelist == NULL)
2791 continue;
2792
2793 if (node->tgn_typelist->tgt_next == NULL)
2794 continue;
2795
2796 break;
2797 }
2798
2799 if (ndx == tg_nnodes)
2800 return (WALK_DONE);
2801
2802 wsp->walk_data = (void *)++ndx;
2803 return (wsp->walk_callback(node->tgn_base, NULL, wsp->walk_cbdata));
2804 }
2805
2806 int
typeunknown_walk_step(mdb_walk_state_t * wsp)2807 typeunknown_walk_step(mdb_walk_state_t *wsp)
2808 {
2809 size_t ndx;
2810 tg_node_t *node = NULL;
2811
2812 for (ndx = (size_t)wsp->walk_data; ndx < tg_nnodes; ndx++) {
2813 node = &tg_node[ndx];
2814
2815 if (mdb_ctf_type_valid(node->tgn_type))
2816 continue;
2817
2818 if (node->tgn_typelist != NULL)
2819 continue;
2820
2821 if (node->tgn_fraglist != NULL)
2822 continue;
2823
2824 break;
2825 }
2826
2827 if (ndx == tg_nnodes)
2828 return (WALK_DONE);
2829
2830 wsp->walk_data = (void *)++ndx;
2831 return (wsp->walk_callback(node->tgn_base, NULL, wsp->walk_cbdata));
2832 }
2833
2834 #define FINDLOCKS_DEPTH 32
2835
2836 typedef struct foundlock {
2837 uintptr_t fnd_addr;
2838 uintptr_t fnd_owner;
2839 const char *fnd_member[FINDLOCKS_DEPTH];
2840 mdb_ctf_id_t fnd_parent;
2841 tg_node_t *fnd_node;
2842 } foundlock_t;
2843
2844 typedef struct findlocks {
2845 uintptr_t fl_addr;
2846 uintptr_t fl_thread;
2847 size_t fl_ndx;
2848 size_t fl_nlocks;
2849 foundlock_t *fl_locks;
2850 mdb_ctf_id_t fl_parent;
2851 tg_node_t *fl_node;
2852 const char *fl_member[FINDLOCKS_DEPTH - 1];
2853 int fl_depth;
2854 } findlocks_t;
2855
2856 /*ARGSUSED*/
2857 static int
findlocks_owner(uintptr_t addr,const void * data,void * owner)2858 findlocks_owner(uintptr_t addr, const void *data, void *owner)
2859 {
2860 *((uintptr_t *)owner) = addr;
2861
2862 return (WALK_NEXT);
2863 }
2864
2865 static int
findlocks_findmutex(const char * name,mdb_ctf_id_t type,ulong_t offs,findlocks_t * fl)2866 findlocks_findmutex(const char *name, mdb_ctf_id_t type, ulong_t offs,
2867 findlocks_t *fl)
2868 {
2869 static int called = 0;
2870 static mdb_ctf_id_t mutex;
2871 static mdb_ctf_id_t thread;
2872 mdb_ctf_id_t parent = fl->fl_parent;
2873 uintptr_t addr = fl->fl_addr;
2874 int kind, depth = fl->fl_depth, i;
2875 foundlock_t *found;
2876
2877 offs /= NBBY;
2878
2879 if (!called) {
2880 if (mdb_ctf_lookup_by_name("kmutex_t", &mutex) == -1) {
2881 mdb_warn("can't find 'kmutex_t' type");
2882 return (1);
2883 }
2884
2885 if (!mdb_ctf_type_valid(mutex = typegraph_resolve(mutex))) {
2886 mdb_warn("can't resolve 'kmutex_t' type");
2887 return (1);
2888 }
2889
2890 if (mdb_ctf_lookup_by_name("kthread_t", &thread) == -1) {
2891 mdb_warn("can't find 'kthread_t' type");
2892 return (1);
2893 }
2894
2895 if (!mdb_ctf_type_valid(thread = typegraph_resolve(thread))) {
2896 mdb_warn("can't resolve 'kthread_t' type");
2897 return (1);
2898 }
2899
2900 called = 1;
2901 }
2902
2903 if (!mdb_ctf_type_valid(type))
2904 return (0);
2905
2906 type = typegraph_resolve(type);
2907 kind = mdb_ctf_type_kind(type);
2908
2909 if (!mdb_ctf_type_valid(type))
2910 return (0);
2911
2912 if (kind == CTF_K_ARRAY) {
2913 mdb_ctf_arinfo_t arr;
2914 ssize_t size;
2915
2916 if (mdb_ctf_array_info(type, &arr) == -1)
2917 return (0);
2918
2919 type = typegraph_resolve(arr.mta_contents);
2920
2921 if (!mdb_ctf_type_valid(type))
2922 return (0);
2923
2924 /*
2925 * Small optimization: don't bother running through the array
2926 * if we know that we can't process the type.
2927 */
2928 kind = mdb_ctf_type_kind(type);
2929 size = mdb_ctf_type_size(type);
2930
2931 if (kind == CTF_K_POINTER || kind == CTF_K_INTEGER)
2932 return (0);
2933
2934 for (i = 0; i < arr.mta_nelems; i++) {
2935 fl->fl_addr = addr + offs + (i * size);
2936 findlocks_findmutex(name, type, 0, fl);
2937 }
2938
2939 fl->fl_addr = addr;
2940
2941 return (0);
2942 }
2943
2944 if (kind != CTF_K_STRUCT)
2945 return (0);
2946
2947 if (mdb_ctf_type_cmp(type, mutex) == 0) {
2948 mdb_ctf_id_t ttype;
2949 uintptr_t owner = 0;
2950 tg_node_t *node;
2951
2952 if (mdb_pwalk("mutex_owner",
2953 findlocks_owner, &owner, addr + offs) == -1) {
2954 return (0);
2955 }
2956
2957 /*
2958 * Check to see if the owner is a thread.
2959 */
2960 if (owner == 0 || (node = typegraph_search(owner)) == NULL)
2961 return (0);
2962
2963 if (!mdb_ctf_type_valid(node->tgn_type))
2964 return (0);
2965
2966 ttype = typegraph_resolve(node->tgn_type);
2967
2968 if (!mdb_ctf_type_valid(ttype))
2969 return (0);
2970
2971 if (mdb_ctf_type_cmp(ttype, thread) != 0)
2972 return (0);
2973
2974 if (fl->fl_thread != 0 && owner != fl->fl_thread)
2975 return (0);
2976
2977 if (fl->fl_ndx >= fl->fl_nlocks) {
2978 size_t nlocks, osize, size;
2979 foundlock_t *locks;
2980
2981 if ((nlocks = (fl->fl_nlocks << 1)) == 0)
2982 nlocks = 1;
2983
2984 osize = fl->fl_nlocks * sizeof (foundlock_t);
2985 size = nlocks * sizeof (foundlock_t);
2986
2987 locks = mdb_zalloc(size, UM_SLEEP);
2988
2989 if (fl->fl_locks) {
2990 bcopy(fl->fl_locks, locks, osize);
2991 mdb_free(fl->fl_locks, osize);
2992 }
2993
2994 fl->fl_locks = locks;
2995 fl->fl_nlocks = nlocks;
2996 }
2997
2998 found = &fl->fl_locks[fl->fl_ndx++];
2999 found->fnd_addr = (uintptr_t)addr + offs;
3000 found->fnd_owner = owner;
3001
3002 for (i = 0; i < fl->fl_depth; i++)
3003 found->fnd_member[i] = fl->fl_member[i];
3004
3005 found->fnd_member[i] = name;
3006 found->fnd_parent = fl->fl_parent;
3007 found->fnd_node = fl->fl_node;
3008
3009 return (0);
3010 }
3011
3012 fl->fl_addr = (uintptr_t)addr + offs;
3013
3014 if (name == NULL) {
3015 fl->fl_parent = type;
3016 } else if (depth < FINDLOCKS_DEPTH - 1) {
3017 fl->fl_member[depth] = name;
3018 fl->fl_depth++;
3019 }
3020
3021 mdb_ctf_member_iter(type, (mdb_ctf_member_f *)findlocks_findmutex, fl,
3022 0);
3023
3024 fl->fl_addr = addr;
3025 fl->fl_parent = parent;
3026 fl->fl_depth = depth;
3027
3028 return (0);
3029 }
3030
3031 static void
findlocks_node(tg_node_t * node,findlocks_t * fl)3032 findlocks_node(tg_node_t *node, findlocks_t *fl)
3033 {
3034 mdb_ctf_id_t type = node->tgn_type, ntype;
3035 int kind;
3036 tg_type_t *tp, *found = NULL;
3037
3038 if (!mdb_ctf_type_valid(type)) {
3039 mdb_ctf_type_invalidate(&type);
3040
3041 for (tp = node->tgn_typelist; tp != NULL; tp = tp->tgt_next) {
3042 kind = mdb_ctf_type_kind(ntype = tp->tgt_type);
3043
3044 if (kind == CTF_K_UNION) {
3045 /*
3046 * Insert disparaging comment about unions here.
3047 */
3048 return;
3049 }
3050
3051 if (kind != CTF_K_STRUCT && kind != CTF_K_ARRAY)
3052 continue;
3053
3054 if (found != NULL) {
3055 /*
3056 * There are multiple interpretations for this
3057 * node; we have to punt.
3058 */
3059 return;
3060 }
3061
3062 found = tp;
3063 }
3064 }
3065
3066 if (found != NULL)
3067 type = found->tgt_type;
3068
3069 fl->fl_parent = type;
3070 fl->fl_node = node;
3071
3072 /*
3073 * We have our type. Now iterate for locks. Note that we don't yet
3074 * deal with locks in flexible array members.
3075 */
3076 if (found != NULL && (found->tgt_flags & TG_TYPE_ARRAY) &&
3077 !(found->tgt_flags & TG_TYPE_HASFAM)) {
3078 uintptr_t base, limit = node->tgn_limit;
3079 size_t size = mdb_ctf_type_size(found->tgt_type);
3080
3081 for (base = node->tgn_base; base < limit; base += size) {
3082 fl->fl_addr = base;
3083 findlocks_findmutex(NULL, type, 0, fl);
3084 }
3085 } else {
3086 fl->fl_addr = node->tgn_base;
3087 findlocks_findmutex(NULL, type, 0, fl);
3088 }
3089
3090 if (mdb_ctf_type_valid(type))
3091 return;
3092
3093 for (tp = node->tgn_fraglist; tp != NULL; tp = tp->tgt_next) {
3094 kind = mdb_ctf_type_kind(ntype = tp->tgt_type);
3095
3096 if (kind != CTF_K_STRUCT && kind != CTF_K_ARRAY)
3097 continue;
3098
3099 fl->fl_addr = node->tgn_base + tp->tgt_redge->tge_destoffs;
3100 fl->fl_parent = ntype;
3101 findlocks_findmutex(NULL, ntype, 0, fl);
3102 }
3103 }
3104
3105 /*ARGSUSED*/
3106 int
findlocks(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3107 findlocks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3108 {
3109 size_t i, j;
3110 findlocks_t fl;
3111
3112 if (argc != 0)
3113 return (DCMD_USAGE);
3114
3115 if (!typegraph_built())
3116 return (DCMD_ABORT);
3117
3118 if (!(flags & DCMD_ADDRSPEC))
3119 addr = 0;
3120
3121 bzero(&fl, sizeof (fl));
3122 fl.fl_thread = addr;
3123
3124 for (i = 0; i < tg_nnodes; i++) {
3125 findlocks_node(&tg_node[i], &fl);
3126 }
3127
3128 for (i = 0; i < fl.fl_ndx; i++) {
3129 foundlock_t *found = &fl.fl_locks[i];
3130 char buf[MDB_SYM_NAMLEN];
3131
3132 if (found->fnd_member[0] != NULL) {
3133 mdb_printf("%p (%s",
3134 found->fnd_addr,
3135 mdb_ctf_type_name(found->fnd_parent, buf,
3136 sizeof (buf)));
3137
3138 for (j = 0; found->fnd_member[j] != NULL; j++)
3139 mdb_printf(".%s", found->fnd_member[j]);
3140
3141 mdb_printf(") is owned by %p\n", found->fnd_owner);
3142 } else {
3143 if (found->fnd_node->tgn_incoming == NULL) {
3144 mdb_printf("%p (%a) is owned by %p\n",
3145 found->fnd_addr, found->fnd_addr,
3146 found->fnd_owner);
3147 } else {
3148 mdb_printf("%p is owned by %p\n",
3149 found->fnd_addr, found->fnd_owner);
3150 }
3151 }
3152 }
3153
3154 mdb_printf("findlocks: nota bene: %slocks may be held",
3155 fl.fl_nlocks ? "other " : "");
3156
3157 if (addr == 0) {
3158 mdb_printf("\n");
3159 } else {
3160 mdb_printf(" by %p\n", addr);
3161 }
3162
3163 if (fl.fl_nlocks)
3164 mdb_free(fl.fl_locks, fl.fl_nlocks * sizeof (foundlock_t));
3165
3166 return (DCMD_OK);
3167 }
3168
3169 /*
3170 * ::findfalse: Using type knowledge to detect potential false sharing
3171 *
3172 * In caching SMP systems, memory is kept coherent through bus-based snooping
3173 * protocols. Under these protocols, only a single cache may have a given line
3174 * of memory in a dirty state. If a different cache wishes to write to the
3175 * dirty line, the new cache must first read-to-own the dirty line from the
3176 * owning cache. The size of the line used for coherence (the coherence
3177 * granularity) has an immediate ramification for parallel software: because
3178 * only one cache may own a line at a given time, one wishes to avoid a
3179 * situation where two or more small, disjoint data structures are both
3180 * (a) contained within a single line and (b) accessed in parallel on disjoint
3181 * CPUs. This situation -- so-called "false sharing" -- can induce suboptimal
3182 * scalability in otherwise scalable software.
3183 *
3184 * Historically, one has been able to find false sharing only with some
3185 * combination of keen intuition and good luck. And where false sharing has
3186 * been discovered, it has almost always been after having induced suboptimal
3187 * scaling; one has historically not been able to detect false sharing before
3188 * the fact.
3189 *
3190 * Building on the mechanism for postmortem type information, however, we
3191 * can -- from a system crash dump -- detect the the potentially most egregious
3192 * cases of false sharing. Specifically, after having run through the type
3193 * identification passes described above, we can iterate over all nodes,
3194 * looking for nodes that satisfy the following criteria:
3195 *
3196 * (a) The node is an array. That is, the node was either determined to
3197 * be of type CTF_K_ARRAY, or the node was inferred to be an array in
3198 * pass2 of type identification (described above).
3199 *
3200 * (b) Each element of the array is a structure that is smaller than the
3201 * coherence granularity.
3202 *
3203 * (c) The total size of the array is greater than the coherence granularity.
3204 *
3205 * (d) Each element of the array is a structure that contains within it a
3206 * synchronization primitive (mutex, readers/writer lock, condition
3207 * variable or semaphore). We use the presence of a synchronization
3208 * primitive as a crude indicator that the disjoint elements of the
3209 * array are accessed in parallel.
3210 *
3211 * Any node satisfying these criteria is identified as an object that could
3212 * potentially suffer from false sharing, and the node's address, symbolic
3213 * name (if any), type, type size and total size are provided as output.
3214 *
3215 * While there are some instances of false sharing that do not meet the
3216 * above criteria (e.g., if the synchronization for each element is handled
3217 * in a separate structure, or if the elements are only manipulated with
3218 * atomic memory operations), these criteria yield many examples of false
3219 * sharing without swamping the user with false positives.
3220 */
3221 #define FINDFALSE_COHERENCE_SIZE 64
3222
3223 /*ARGSUSED*/
3224 static int
findfalse_findsync(const char * name,mdb_ctf_id_t type,ulong_t offs,void * ignored)3225 findfalse_findsync(const char *name, mdb_ctf_id_t type, ulong_t offs,
3226 void *ignored)
3227 {
3228 int i, kind;
3229 static int called = 0;
3230 static struct {
3231 char *name;
3232 mdb_ctf_id_t type;
3233 } sync[] = {
3234 { "kmutex_t" },
3235 { "krwlock_t" },
3236 { "kcondvar_t" },
3237 { "ksema_t" },
3238 { NULL }
3239 };
3240
3241 if (!called) {
3242 char *name;
3243
3244 called = 1;
3245
3246 for (i = 0; (name = sync[i].name) != NULL; i++) {
3247 if (mdb_ctf_lookup_by_name(name, &sync[i].type) == -1) {
3248 mdb_warn("can't find '%s' type", name);
3249 return (0);
3250 }
3251
3252 sync[i].type = typegraph_resolve(sync[i].type);
3253
3254 if (!mdb_ctf_type_valid(sync[i].type)) {
3255 mdb_warn("can't resolve '%s' type", name);
3256 return (0);
3257 }
3258 }
3259 }
3260
3261 /*
3262 * See if this type is any of the synchronization primitives.
3263 */
3264 if (!mdb_ctf_type_valid(type))
3265 return (0);
3266
3267 type = typegraph_resolve(type);
3268
3269 for (i = 0; sync[i].name != NULL; i++) {
3270 if (mdb_ctf_type_cmp(type, sync[i].type) == 0) {
3271 /*
3272 * We have a winner!
3273 */
3274 return (1);
3275 }
3276 }
3277
3278 if ((kind = mdb_ctf_type_kind(type)) == CTF_K_ARRAY) {
3279 mdb_ctf_arinfo_t arr;
3280
3281 if (mdb_ctf_array_info(type, &arr) == -1)
3282 return (0);
3283
3284 type = typegraph_resolve(arr.mta_contents);
3285
3286 return (findfalse_findsync(name, type, 0, NULL));
3287 }
3288
3289 if (kind != CTF_K_STRUCT)
3290 return (0);
3291
3292 if (mdb_ctf_member_iter(type,
3293 (mdb_ctf_member_f *)findfalse_findsync, NULL, 0) != 0)
3294 return (1);
3295
3296 return (0);
3297 }
3298
3299 static void
findfalse_node(tg_node_t * node)3300 findfalse_node(tg_node_t *node)
3301 {
3302 mdb_ctf_id_t type = node->tgn_type;
3303 tg_type_t *tp, *found = NULL;
3304 ssize_t size;
3305 int kind;
3306 char buf[MDB_SYM_NAMLEN + 1];
3307 GElf_Sym sym;
3308
3309 if (!mdb_ctf_type_valid(type)) {
3310 mdb_ctf_type_invalidate(&type);
3311
3312 for (tp = node->tgn_typelist; tp != NULL; tp = tp->tgt_next) {
3313 kind = mdb_ctf_type_kind(tp->tgt_type);
3314
3315 if (kind == CTF_K_UNION) {
3316 /*
3317 * Once again, the unions impede progress...
3318 */
3319 return;
3320 }
3321
3322 if (kind != CTF_K_STRUCT && kind != CTF_K_ARRAY)
3323 continue;
3324
3325 if (found != NULL) {
3326 /*
3327 * There are multiple interpretations for this
3328 * node; we have to punt.
3329 */
3330 return;
3331 }
3332
3333 found = tp;
3334 }
3335 }
3336
3337 if (found != NULL)
3338 type = found->tgt_type;
3339
3340 if (!mdb_ctf_type_valid(type))
3341 return;
3342
3343 kind = mdb_ctf_type_kind(type);
3344
3345 /*
3346 * If this isn't an array (or treated as one), it can't induce false
3347 * sharing. (Or at least, we can't detect it.)
3348 */
3349 if (found != NULL) {
3350 if (!(found->tgt_flags & TG_TYPE_ARRAY))
3351 return;
3352
3353 if (found->tgt_flags & TG_TYPE_HASFAM)
3354 return;
3355 } else {
3356 if (kind != CTF_K_ARRAY)
3357 return;
3358 }
3359
3360 if (kind == CTF_K_ARRAY) {
3361 mdb_ctf_arinfo_t arr;
3362
3363 if (mdb_ctf_array_info(type, &arr) == -1)
3364 return;
3365
3366 type = typegraph_resolve(arr.mta_contents);
3367
3368 if (!mdb_ctf_type_valid(type))
3369 return;
3370
3371 }
3372
3373 size = mdb_ctf_type_size(type);
3374
3375 /*
3376 * If the size is greater than or equal to the cache line size, it's
3377 * not false sharing. (Or at least, the false sharing is benign.)
3378 */
3379 if (size >= FINDFALSE_COHERENCE_SIZE)
3380 return;
3381
3382 if (TG_NODE_SIZE(node) <= FINDFALSE_COHERENCE_SIZE)
3383 return;
3384
3385 /*
3386 * This looks like it could be a falsely shared structure. If this
3387 * type contains a mutex, rwlock, semaphore or condition variable,
3388 * we're going to report it.
3389 */
3390 if (!findfalse_findsync(NULL, type, 0, NULL))
3391 return;
3392
3393 mdb_printf("%?p ", node->tgn_base);
3394
3395 if (mdb_lookup_by_addr(node->tgn_base, MDB_SYM_EXACT, buf,
3396 sizeof (buf), &sym) != -1) {
3397 mdb_printf("%-28s ", buf);
3398 } else {
3399 mdb_printf("%-28s ", "-");
3400 }
3401
3402 mdb_printf("%-22s %2d %7ld\n",
3403 mdb_ctf_type_name(type, buf, sizeof (buf)), size,
3404 TG_NODE_SIZE(node));
3405 }
3406
3407 /*ARGSUSED*/
3408 int
findfalse(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3409 findfalse(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3410 {
3411 ssize_t i;
3412
3413 if (argc != 0 || (flags & DCMD_ADDRSPEC))
3414 return (DCMD_USAGE);
3415
3416 if (!typegraph_built())
3417 return (DCMD_ABORT);
3418
3419 mdb_printf("%?s %-28s %-22s %2s %7s\n", "ADDR", "SYMBOL", "TYPE",
3420 "SZ", "TOTSIZE");
3421
3422 /*
3423 * We go from the back of the bus and move forward to report false
3424 * sharing in named symbols before reporting false sharing in dynamic
3425 * structures.
3426 */
3427 for (i = tg_nnodes - 1; i >= 0; i--)
3428 findfalse_node(&tg_node[i]);
3429
3430 return (DCMD_OK);
3431 }
3432