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 }