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