1edb34883SAdam H. Leventhal /*
2edb34883SAdam H. Leventhal  * CDDL HEADER START
3edb34883SAdam H. Leventhal  *
4edb34883SAdam H. Leventhal  * This file and its contents are supplied under the terms of the
5edb34883SAdam H. Leventhal  * Common Development and Distribution License ("CDDL"), version 1.0.
6edb34883SAdam H. Leventhal  * You may only use this file in accordance with the terms of version
7edb34883SAdam H. Leventhal  * 1.0 of the CDDL.
8edb34883SAdam H. Leventhal  *
9edb34883SAdam H. Leventhal  * A full copy of the text of the CDDL should have accompanied this
10edb34883SAdam H. Leventhal  * source.  A copy of the CDDL is also available via the Internet at
11edb34883SAdam H. Leventhal  * http://www.illumos.org/license/CDDL.
12edb34883SAdam H. Leventhal  *
13edb34883SAdam H. Leventhal  * CDDL HEADER END
14edb34883SAdam H. Leventhal  */
15edb34883SAdam H. Leventhal 
16edb34883SAdam H. Leventhal /*
17edb34883SAdam H. Leventhal  * Copyright (c) 2012 by Delphix. All rights reserved.
18edb34883SAdam H. Leventhal  */
19edb34883SAdam H. Leventhal 
20edb34883SAdam H. Leventhal /*
21edb34883SAdam H. Leventhal  * This file implements an audit library that can be used to force the loading
22edb34883SAdam H. Leventhal  * of helper providers. The default disposition for a helper provider -- USDT
23edb34883SAdam H. Leventhal  * and ustack helpers -- is to load itself from it's containing object's .init
24edb34883SAdam H. Leventhal  * section. In cases where startup time is deemed critical, USDT authors can
25*bbf21555SRichard Lowe  * use the -xlazyload option to dtrace(8) to disable automatic loading (it's
26edb34883SAdam H. Leventhal  * difficult to make the case for the utility of this feature for anything
27edb34883SAdam H. Leventhal  * other than libc which, indeed, was the sole motivation). If a binary has
28edb34883SAdam H. Leventhal  * been compiled with automatic loading disabled, this audit library may be
29edb34883SAdam H. Leventhal  * used to force automatic loading:
30edb34883SAdam H. Leventhal  *
31edb34883SAdam H. Leventhal  *	LD_AUDIT_32=/usr/lib/dtrace/libdaudit.so
32edb34883SAdam H. Leventhal  *	LD_AUDIT_64=/usr/lib/dtrace/64/libdaudit.so
33edb34883SAdam H. Leventhal  */
34edb34883SAdam H. Leventhal 
35edb34883SAdam H. Leventhal #include <link.h>
36edb34883SAdam H. Leventhal #include <stdio.h>
37edb34883SAdam H. Leventhal #include <libproc.h>
38edb34883SAdam H. Leventhal #include <strings.h>
39edb34883SAdam H. Leventhal 
40edb34883SAdam H. Leventhal #include <dlink.h>
41edb34883SAdam H. Leventhal 
42edb34883SAdam H. Leventhal typedef struct obj_list {
43edb34883SAdam H. Leventhal 	struct obj_list *ol_next;
44edb34883SAdam H. Leventhal 	char *ol_name;
45edb34883SAdam H. Leventhal 	uintptr_t ol_addr;
46edb34883SAdam H. Leventhal 	Lmid_t ol_lmid;
47edb34883SAdam H. Leventhal } obj_list_t;
48edb34883SAdam H. Leventhal 
49edb34883SAdam H. Leventhal static obj_list_t *list;
50edb34883SAdam H. Leventhal 
51edb34883SAdam H. Leventhal #pragma init(dtrace_daudit_init)
52edb34883SAdam H. Leventhal static void
dtrace_daudit_init(void)53edb34883SAdam H. Leventhal dtrace_daudit_init(void)
54edb34883SAdam H. Leventhal {
55edb34883SAdam H. Leventhal 	dtrace_link_init();
56edb34883SAdam H. Leventhal }
57edb34883SAdam H. Leventhal 
58edb34883SAdam H. Leventhal /*ARGSUSED*/
59edb34883SAdam H. Leventhal uint_t
la_version(uint_t version)60edb34883SAdam H. Leventhal la_version(uint_t version)
61edb34883SAdam H. Leventhal {
62edb34883SAdam H. Leventhal 	return (LAV_CURRENT);
63edb34883SAdam H. Leventhal }
64edb34883SAdam H. Leventhal 
65edb34883SAdam H. Leventhal /*
66edb34883SAdam H. Leventhal  * Record objects into our linked list as they're loaded.
67edb34883SAdam H. Leventhal  */
68edb34883SAdam H. Leventhal /*ARGSUSED*/
69edb34883SAdam H. Leventhal uint_t
la_objopen(Link_map * lmp,Lmid_t lmid,uintptr_t * cookie)70edb34883SAdam H. Leventhal la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie)
71edb34883SAdam H. Leventhal {
72edb34883SAdam H. Leventhal 	obj_list_t *node;
73edb34883SAdam H. Leventhal 
74edb34883SAdam H. Leventhal 	/*
75edb34883SAdam H. Leventhal 	 * If we can't allocate the next node in our list, we'll try to emit a
76edb34883SAdam H. Leventhal 	 * message, but it's possible that might fail as well.
77edb34883SAdam H. Leventhal 	 */
78edb34883SAdam H. Leventhal 	if ((node = malloc(sizeof (obj_list_t))) == NULL) {
79edb34883SAdam H. Leventhal 		dprintf(0, "libdaudit: failed to allocate");
80edb34883SAdam H. Leventhal 		return (0);
81edb34883SAdam H. Leventhal 	}
82edb34883SAdam H. Leventhal 	node->ol_next = list;
83edb34883SAdam H. Leventhal 	node->ol_name = strdup(lmp->l_name);
84edb34883SAdam H. Leventhal 	node->ol_addr = lmp->l_addr;
85edb34883SAdam H. Leventhal 	node->ol_lmid = lmid;
86edb34883SAdam H. Leventhal 	list = node;
87edb34883SAdam H. Leventhal 
88edb34883SAdam H. Leventhal 	return (0);
89edb34883SAdam H. Leventhal }
90edb34883SAdam H. Leventhal 
91edb34883SAdam H. Leventhal /*
92edb34883SAdam H. Leventhal  * Once the link maps have reached a consistent state, process the list of
93edb34883SAdam H. Leventhal  * objects that were loaded. We need to use libproc to search for the
94edb34883SAdam H. Leventhal  * ___SUNW_dof symbol rather than dlsym(3C) since the symbol is not in the
95edb34883SAdam H. Leventhal  * dynamic (run-time) symbol table (though it is, of course, in the symtab).
96edb34883SAdam H. Leventhal  * Once we find it, we ioctl(2) it to the kernel just as we would have from
97edb34883SAdam H. Leventhal  * the .init section if automatic loading were enabled.
98edb34883SAdam H. Leventhal  */
99edb34883SAdam H. Leventhal /*ARGSUSED*/
100edb34883SAdam H. Leventhal void
la_activity(uintptr_t * cookie,uint_t flags)101edb34883SAdam H. Leventhal la_activity(uintptr_t *cookie, uint_t flags)
102edb34883SAdam H. Leventhal {
103edb34883SAdam H. Leventhal 	struct ps_prochandle *P;
104edb34883SAdam H. Leventhal 	int err, ret;
105edb34883SAdam H. Leventhal 	GElf_Sym sym;
106edb34883SAdam H. Leventhal 
107edb34883SAdam H. Leventhal 	if (flags != LA_ACT_CONSISTENT)
108edb34883SAdam H. Leventhal 		return;
109edb34883SAdam H. Leventhal 
110edb34883SAdam H. Leventhal 	while (list != NULL) {
111edb34883SAdam H. Leventhal 		obj_list_t *node = list;
112edb34883SAdam H. Leventhal 		char *name = node->ol_name;
113edb34883SAdam H. Leventhal 
114edb34883SAdam H. Leventhal 		list = node->ol_next;
115edb34883SAdam H. Leventhal 
116edb34883SAdam H. Leventhal 		P = Pgrab(getpid(), PGRAB_RDONLY, &err);
117edb34883SAdam H. Leventhal 		ret = Plookup_by_name(P, name, "___SUNW_dof", &sym);
118edb34883SAdam H. Leventhal 		Prelease(P, 0);
119edb34883SAdam H. Leventhal 
120edb34883SAdam H. Leventhal 		if (ret == 0) {
121edb34883SAdam H. Leventhal 			dtrace_link_dof((void *)(uintptr_t)sym.st_value,
122edb34883SAdam H. Leventhal 			    node->ol_lmid, node->ol_name, node->ol_addr);
123edb34883SAdam H. Leventhal 		}
124edb34883SAdam H. Leventhal 
125edb34883SAdam H. Leventhal 		free(node->ol_name);
126edb34883SAdam H. Leventhal 		free(node);
127edb34883SAdam H. Leventhal 	}
128edb34883SAdam H. Leventhal }
129