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