xref: /freebsd/sys/cddl/contrib/opensolaris/uts/common/ctf/ctf_mod.c (revision 09a53ad8f1318c5daae6cfb19d97f4f6459f0013)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/sysmacros.h>
30 #include <sys/modctl.h>
31 #include <sys/debug.h>
32 #include <sys/mman.h>
33 #include <sys/modctl.h>
34 #include <sys/kobj.h>
35 #include <ctf_impl.h>
36 
37 int ctf_leave_compressed = 0;
38 
39 static struct modlmisc modlmisc = {
40 	&mod_miscops, "Compact C Type Format routines"
41 };
42 
43 static struct modlinkage modlinkage = {
44 	MODREV_1, &modlmisc, NULL
45 };
46 
47 int
48 _init(void)
49 {
50 	return (mod_install(&modlinkage));
51 }
52 
53 int
54 _info(struct modinfo *mip)
55 {
56 	return (mod_info(&modlinkage, mip));
57 }
58 
59 int
60 _fini(void)
61 {
62 	return (mod_remove(&modlinkage));
63 }
64 
65 /*ARGSUSED*/
66 void *
67 ctf_zopen(int *errp)
68 {
69 	return ((void *)1); /* zmod is always loaded because we depend on it */
70 }
71 
72 /*ARGSUSED*/
73 const void *
74 ctf_sect_mmap(ctf_sect_t *sp, int fd)
75 {
76 	return (MAP_FAILED); /* we don't support this in the kernel */
77 }
78 
79 /*ARGSUSED*/
80 void
81 ctf_sect_munmap(const ctf_sect_t *sp)
82 {
83 	/* we don't support this in the kernel */
84 }
85 
86 /*ARGSUSED*/
87 ctf_file_t *
88 ctf_fdopen(int fd, int *errp)
89 {
90 	return (ctf_set_open_errno(errp, ENOTSUP));
91 }
92 
93 /*ARGSUSED*/
94 ctf_file_t *
95 ctf_open(const char *filename, int *errp)
96 {
97 	return (ctf_set_open_errno(errp, ENOTSUP));
98 }
99 
100 /*ARGSUSED*/
101 int
102 ctf_write(ctf_file_t *fp, int fd)
103 {
104 	return (ctf_set_errno(fp, ENOTSUP));
105 }
106 
107 int
108 ctf_version(int version)
109 {
110 	ASSERT(version > 0 && version <= CTF_VERSION);
111 
112 	if (version > 0)
113 		_libctf_version = MIN(CTF_VERSION, version);
114 
115 	return (_libctf_version);
116 }
117 
118 /*ARGSUSED*/
119 ctf_file_t *
120 ctf_modopen(struct module *mp, int *error)
121 {
122 	ctf_sect_t ctfsect, symsect, strsect;
123 	ctf_file_t *fp = NULL;
124 	int err;
125 
126 	if (error == NULL)
127 		error = &err;
128 
129 	ctfsect.cts_name = ".SUNW_ctf";
130 	ctfsect.cts_type = SHT_PROGBITS;
131 	ctfsect.cts_flags = SHF_ALLOC;
132 	ctfsect.cts_data = mp->ctfdata;
133 	ctfsect.cts_size = mp->ctfsize;
134 	ctfsect.cts_entsize = 1;
135 	ctfsect.cts_offset = 0;
136 
137 	symsect.cts_name = ".symtab";
138 	symsect.cts_type = SHT_SYMTAB;
139 	symsect.cts_flags = 0;
140 	symsect.cts_data = mp->symtbl;
141 	symsect.cts_size = mp->symhdr->sh_size;
142 #ifdef _LP64
143 	symsect.cts_entsize = sizeof (Elf64_Sym);
144 #else
145 	symsect.cts_entsize = sizeof (Elf32_Sym);
146 #endif
147 	symsect.cts_offset = 0;
148 
149 	strsect.cts_name = ".strtab";
150 	strsect.cts_type = SHT_STRTAB;
151 	strsect.cts_flags = 0;
152 	strsect.cts_data = mp->strings;
153 	strsect.cts_size = mp->strhdr->sh_size;
154 	strsect.cts_entsize = 1;
155 	strsect.cts_offset = 0;
156 
157 	ASSERT(MUTEX_HELD(&mod_lock));
158 
159 	if ((fp = ctf_bufopen(&ctfsect, &symsect, &strsect, error)) == NULL)
160 		return (NULL);
161 
162 	if (!ctf_leave_compressed && (caddr_t)fp->ctf_base != mp->ctfdata) {
163 		/*
164 		 * We must have just uncompressed the CTF data.  To avoid
165 		 * others having to pay the (substantial) cost of decompressing
166 		 * the data, we're going to substitute the uncompressed version
167 		 * for the compressed version.  Note that this implies that the
168 		 * first CTF consumer will induce memory impact on the system
169 		 * (but in the name of performance of future CTF consumers).
170 		 */
171 		kobj_set_ctf(mp, (caddr_t)fp->ctf_base, fp->ctf_size);
172 		fp->ctf_data.cts_data = fp->ctf_base;
173 		fp->ctf_data.cts_size = fp->ctf_size;
174 	}
175 
176 	return (fp);
177 }
178