1179193Sjb/*
2179193Sjb * CDDL HEADER START
3179193Sjb *
4179193Sjb * The contents of this file are subject to the terms of the
5179193Sjb * Common Development and Distribution License, Version 1.0 only
6179193Sjb * (the "License").  You may not use this file except in compliance
7179193Sjb * with the License.
8179193Sjb *
9179193Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10179193Sjb * or http://www.opensolaris.org/os/licensing.
11179193Sjb * See the License for the specific language governing permissions
12179193Sjb * and limitations under the License.
13179193Sjb *
14179193Sjb * When distributing Covered Code, include this CDDL HEADER in each
15179193Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16179193Sjb * If applicable, add the following below this CDDL HEADER, with the
17179193Sjb * fields enclosed by brackets "[]" replaced with your own identifying
18179193Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
19179193Sjb *
20179193Sjb * CDDL HEADER END
21179193Sjb */
22179193Sjb/*
23179193Sjb * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24179193Sjb * Use is subject to license terms.
25179193Sjb */
26179193Sjb
27179193Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
28179193Sjb
29179193Sjb#include <sys/sysmacros.h>
30179193Sjb#include <sys/modctl.h>
31179193Sjb#include <sys/debug.h>
32179193Sjb#include <sys/mman.h>
33179193Sjb#include <sys/modctl.h>
34179193Sjb#include <sys/kobj.h>
35179193Sjb#include <ctf_impl.h>
36179193Sjb
37179193Sjbint ctf_leave_compressed = 0;
38179193Sjb
39179193Sjbstatic struct modlmisc modlmisc = {
40179193Sjb	&mod_miscops, "Compact C Type Format routines"
41179193Sjb};
42179193Sjb
43179193Sjbstatic struct modlinkage modlinkage = {
44179193Sjb	MODREV_1, &modlmisc, NULL
45179193Sjb};
46179193Sjb
47179193Sjbint
48179193Sjb_init(void)
49179193Sjb{
50179193Sjb	return (mod_install(&modlinkage));
51179193Sjb}
52179193Sjb
53179193Sjbint
54179193Sjb_info(struct modinfo *mip)
55179193Sjb{
56179193Sjb	return (mod_info(&modlinkage, mip));
57179193Sjb}
58179193Sjb
59179193Sjbint
60179193Sjb_fini(void)
61179193Sjb{
62179193Sjb	return (mod_remove(&modlinkage));
63179193Sjb}
64179193Sjb
65179193Sjb/*ARGSUSED*/
66179193Sjbvoid *
67179193Sjbctf_zopen(int *errp)
68179193Sjb{
69179193Sjb	return ((void *)1); /* zmod is always loaded because we depend on it */
70179193Sjb}
71179193Sjb
72179193Sjb/*ARGSUSED*/
73179193Sjbconst void *
74179193Sjbctf_sect_mmap(ctf_sect_t *sp, int fd)
75179193Sjb{
76179193Sjb	return (MAP_FAILED); /* we don't support this in the kernel */
77179193Sjb}
78179193Sjb
79179193Sjb/*ARGSUSED*/
80179193Sjbvoid
81179193Sjbctf_sect_munmap(const ctf_sect_t *sp)
82179193Sjb{
83179193Sjb	/* we don't support this in the kernel */
84179193Sjb}
85179193Sjb
86179193Sjb/*ARGSUSED*/
87179193Sjbctf_file_t *
88179193Sjbctf_fdopen(int fd, int *errp)
89179193Sjb{
90179193Sjb	return (ctf_set_open_errno(errp, ENOTSUP));
91179193Sjb}
92179193Sjb
93179193Sjb/*ARGSUSED*/
94179193Sjbctf_file_t *
95179193Sjbctf_open(const char *filename, int *errp)
96179193Sjb{
97179193Sjb	return (ctf_set_open_errno(errp, ENOTSUP));
98179193Sjb}
99179193Sjb
100179193Sjb/*ARGSUSED*/
101179193Sjbint
102179193Sjbctf_write(ctf_file_t *fp, int fd)
103179193Sjb{
104179193Sjb	return (ctf_set_errno(fp, ENOTSUP));
105179193Sjb}
106179193Sjb
107179193Sjbint
108179193Sjbctf_version(int version)
109179193Sjb{
110179193Sjb	ASSERT(version > 0 && version <= CTF_VERSION);
111179193Sjb
112179193Sjb	if (version > 0)
113179193Sjb		_libctf_version = MIN(CTF_VERSION, version);
114179193Sjb
115179193Sjb	return (_libctf_version);
116179193Sjb}
117179193Sjb
118179193Sjb/*ARGSUSED*/
119179193Sjbctf_file_t *
120179193Sjbctf_modopen(struct module *mp, int *error)
121179193Sjb{
122179193Sjb	ctf_sect_t ctfsect, symsect, strsect;
123179193Sjb	ctf_file_t *fp = NULL;
124179193Sjb	int err;
125179193Sjb
126179193Sjb	if (error == NULL)
127179193Sjb		error = &err;
128179193Sjb
129179193Sjb	ctfsect.cts_name = ".SUNW_ctf";
130179193Sjb	ctfsect.cts_type = SHT_PROGBITS;
131179193Sjb	ctfsect.cts_flags = SHF_ALLOC;
132179193Sjb	ctfsect.cts_data = mp->ctfdata;
133179193Sjb	ctfsect.cts_size = mp->ctfsize;
134179193Sjb	ctfsect.cts_entsize = 1;
135179193Sjb	ctfsect.cts_offset = 0;
136179193Sjb
137179193Sjb	symsect.cts_name = ".symtab";
138179193Sjb	symsect.cts_type = SHT_SYMTAB;
139179193Sjb	symsect.cts_flags = 0;
140179193Sjb	symsect.cts_data = mp->symtbl;
141179193Sjb	symsect.cts_size = mp->symhdr->sh_size;
142179193Sjb#ifdef _LP64
143179193Sjb	symsect.cts_entsize = sizeof (Elf64_Sym);
144179193Sjb#else
145179193Sjb	symsect.cts_entsize = sizeof (Elf32_Sym);
146179193Sjb#endif
147179193Sjb	symsect.cts_offset = 0;
148179193Sjb
149179193Sjb	strsect.cts_name = ".strtab";
150179193Sjb	strsect.cts_type = SHT_STRTAB;
151179193Sjb	strsect.cts_flags = 0;
152179193Sjb	strsect.cts_data = mp->strings;
153179193Sjb	strsect.cts_size = mp->strhdr->sh_size;
154179193Sjb	strsect.cts_entsize = 1;
155179193Sjb	strsect.cts_offset = 0;
156179193Sjb
157179193Sjb	ASSERT(MUTEX_HELD(&mod_lock));
158179193Sjb
159179193Sjb	if ((fp = ctf_bufopen(&ctfsect, &symsect, &strsect, error)) == NULL)
160179193Sjb		return (NULL);
161179193Sjb
162179193Sjb	if (!ctf_leave_compressed && (caddr_t)fp->ctf_base != mp->ctfdata) {
163179193Sjb		/*
164179193Sjb		 * We must have just uncompressed the CTF data.  To avoid
165179193Sjb		 * others having to pay the (substantial) cost of decompressing
166179193Sjb		 * the data, we're going to substitute the uncompressed version
167179193Sjb		 * for the compressed version.  Note that this implies that the
168179193Sjb		 * first CTF consumer will induce memory impact on the system
169179193Sjb		 * (but in the name of performance of future CTF consumers).
170179193Sjb		 */
171179193Sjb		kobj_set_ctf(mp, (caddr_t)fp->ctf_base, fp->ctf_size);
172179193Sjb		fp->ctf_data.cts_data = fp->ctf_base;
173179193Sjb		fp->ctf_data.cts_size = fp->ctf_size;
174179193Sjb	}
175179193Sjb
176179193Sjb	return (fp);
177179193Sjb}
178