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