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 #include <sys/sysmacros.h>
  28 #include <sys/modctl.h>
  29 #include <sys/debug.h>
  30 #include <sys/mman.h>
  31 #include <sys/modctl.h>
  32 #include <sys/kobj.h>
  33 #include <ctf_impl.h>
  34 
  35 int ctf_leave_compressed = 0;
  36 
  37 static struct modlmisc modlmisc = {
  38         &mod_miscops, "Compact C Type Format routines"
  39 };
  40 
  41 static struct modlinkage modlinkage = {
  42         MODREV_1, { &modlmisc, NULL }
  43 };
  44 
  45 int
  46 _init(void)
  47 {
  48         return (mod_install(&modlinkage));
  49 }
  50 
  51 int
  52 _info(struct modinfo *mip)
  53 {
  54         return (mod_info(&modlinkage, mip));
  55 }
  56 
  57 int
  58 _fini(void)
  59 {
  60         return (mod_remove(&modlinkage));
  61 }
  62 
  63 /*ARGSUSED*/
  64 void *
  65 ctf_zopen(int *errp)
  66 {
  67         return ((void *)1); /* zmod is always loaded because we depend on it */
  68 }
  69 
  70 /*ARGSUSED*/
  71 const void *
  72 ctf_sect_mmap(ctf_sect_t *sp, int fd)
  73 {
  74         return (MAP_FAILED); /* we don't support this in the kernel */
  75 }
  76 
  77 /*ARGSUSED*/
  78 void
  79 ctf_sect_munmap(const ctf_sect_t *sp)
  80 {
  81         /* we don't support this in the kernel */
  82 }
  83 
  84 /*ARGSUSED*/
  85 ctf_file_t *
  86 ctf_fdopen(int fd, int *errp)
  87 {
  88         return (ctf_set_open_errno(errp, ENOTSUP));
  89 }
  90 
  91 /*ARGSUSED*/
  92 ctf_file_t *
  93 ctf_open(const char *filename, int *errp)
  94 {
  95         return (ctf_set_open_errno(errp, ENOTSUP));
  96 }
  97 
  98 /*ARGSUSED*/
  99 int
 100 ctf_write(ctf_file_t *fp, int fd)
 101 {
 102         return (ctf_set_errno(fp, ENOTSUP));
 103 }
 104 
 105 int
 106 ctf_version(int version)
 107 {
 108         ASSERT(version > 0 && version <= CTF_VERSION);
 109 
 110         if (version > 0)
 111                 _libctf_version = MIN(CTF_VERSION, version);
 112 
 113         return (_libctf_version);
 114 }
 115 
 116 /*ARGSUSED*/
 117 ctf_file_t *
 118 ctf_modopen(struct module *mp, int *error)
 119 {
 120         ctf_sect_t ctfsect, symsect, strsect;
 121         ctf_file_t *fp = NULL;
 122         int err;
 123 
 124         if (error == NULL)
 125                 error = &err;
 126 
 127         ctfsect.cts_name = ".SUNW_ctf";
 128         ctfsect.cts_type = SHT_PROGBITS;
 129         ctfsect.cts_flags = SHF_ALLOC;
 130         ctfsect.cts_data = mp->ctfdata;
 131         ctfsect.cts_size = mp->ctfsize;
 132         ctfsect.cts_entsize = 1;
 133         ctfsect.cts_offset = 0;
 134 
 135         symsect.cts_name = ".symtab";
 136         symsect.cts_type = SHT_SYMTAB;
 137         symsect.cts_flags = 0;
 138         symsect.cts_data = mp->symtbl;
 139         symsect.cts_size = mp->symhdr->sh_size;
 140 #ifdef _LP64
 141         symsect.cts_entsize = sizeof (Elf64_Sym);
 142 #else
 143         symsect.cts_entsize = sizeof (Elf32_Sym);
 144 #endif
 145         symsect.cts_offset = 0;
 146 
 147         strsect.cts_name = ".strtab";
 148         strsect.cts_type = SHT_STRTAB;
 149         strsect.cts_flags = 0;
 150         strsect.cts_data = mp->strings;
 151         strsect.cts_size = mp->strhdr->sh_size;
 152         strsect.cts_entsize = 1;
 153         strsect.cts_offset = 0;
 154 
 155         ASSERT(MUTEX_HELD(&mod_lock));
 156 
 157         if ((fp = ctf_bufopen(&ctfsect, &symsect, &strsect, error)) == NULL)
 158                 return (NULL);
 159 
 160         if (!ctf_leave_compressed && (caddr_t)fp->ctf_base != mp->ctfdata) {
 161                 /*
 162                  * We must have just uncompressed the CTF data.  To avoid
 163                  * others having to pay the (substantial) cost of decompressing
 164                  * the data, we're going to substitute the uncompressed version
 165                  * for the compressed version.  Note that this implies that the
 166                  * first CTF consumer will induce memory impact on the system
 167                  * (but in the name of performance of future CTF consumers).
 168                  */
 169                 kobj_set_ctf(mp, (caddr_t)fp->ctf_base, fp->ctf_size);
 170                 fp->ctf_data.cts_data = fp->ctf_base;
 171                 fp->ctf_data.cts_size = fp->ctf_size;
 172         }
 173 
 174         return (fp);
 175 }