Home | History | Annotate | Download | only in ctf
      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