[BACK]Return to kern_ksyms.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_ksyms.c, Revision 1.73

1.73    ! joerg       1: /*     $NetBSD: kern_ksyms.c,v 1.72 2014/07/25 08:10:40 dholland Exp $ */
1.38      skrll       2:
1.39      ad          3: /*-
                      4:  * Copyright (c) 2008 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software developed for The NetBSD Foundation
                      8:  * by Andrew Doran.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
1.1       ragge      32: /*
                     33:  * Copyright (c) 2001, 2003 Anders Magnusson (ragge@ludd.luth.se).
                     34:  * All rights reserved.
                     35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
                     44:  * 3. The name of the author may not be used to endorse or promote products
                     45:  *    derived from this software without specific prior written permission
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     48:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     49:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     50:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     51:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     52:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     53:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     54:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     55:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     56:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     57:  */
                     58:
                     59: /*
                     60:  * Code to deal with in-kernel symbol table management + /dev/ksyms.
                     61:  *
                     62:  * For each loaded module the symbol table info is kept track of by a
                     63:  * struct, placed in a circular list. The first entry is the kernel
                     64:  * symbol table.
                     65:  */
                     66:
                     67: /*
                     68:  * TODO:
                     69:  *
1.39      ad         70:  *     Add support for mmap, poll.
1.1       ragge      71:  */
1.11      jdolecek   72:
                     73: #include <sys/cdefs.h>
1.73    ! joerg      74: __KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.72 2014/07/25 08:10:40 dholland Exp $");
1.1       ragge      75:
1.49      pooka      76: #if defined(_KERNEL) && defined(_KERNEL_OPT)
1.1       ragge      77: #include "opt_ddb.h"
1.56      darran     78: #include "opt_dtrace.h"
1.1       ragge      79: #endif
                     80:
1.39      ad         81: #define _KSYMS_PRIVATE
                     82:
1.1       ragge      83: #include <sys/param.h>
                     84: #include <sys/queue.h>
                     85: #include <sys/exec.h>
                     86: #include <sys/systm.h>
                     87: #include <sys/conf.h>
1.39      ad         88: #include <sys/kmem.h>
1.1       ragge      89: #include <sys/proc.h>
1.39      ad         90: #include <sys/atomic.h>
1.1       ragge      91: #include <sys/ksyms.h>
                     92:
                     93: #ifdef DDB
                     94: #include <ddb/db_output.h>
                     95: #endif
                     96:
                     97: #include "ksyms.h"
                     98:
1.56      darran     99: #define KSYMS_MAX_ID   65536
                    100: #ifdef KDTRACE_HOOKS
                    101: static uint32_t ksyms_nmap[KSYMS_MAX_ID];      /* sorted symbol table map */
                    102: #else
                    103: static uint32_t *ksyms_nmap = NULL;
                    104: #endif
                    105:
1.39      ad        106: static int ksyms_maxlen;
                    107: static bool ksyms_isopen;
                    108: static bool ksyms_initted;
1.69      matt      109: static bool ksyms_loaded;
                    110: static kmutex_t ksyms_lock __cacheline_aligned;
1.66      christos  111: static struct ksyms_symtab kernel_symtab;
1.1       ragge     112:
1.39      ad        113: void ksymsattach(int);
1.40      christos  114: static void ksyms_hdr_init(void *);
1.1       ragge     115: static void ksyms_sizes_calc(void);
                    116:
                    117: #ifdef KSYMS_DEBUG
                    118: #define        FOLLOW_CALLS            1
                    119: #define        FOLLOW_MORE_CALLS       2
                    120: #define        FOLLOW_DEVKSYMS         4
                    121: static int ksyms_debug;
                    122: #endif
                    123:
1.3       ragge     124: #define                SYMTAB_FILLER   "|This is the symbol table!"
                    125:
1.73    ! joerg     126: #ifdef COPY_SYMTAB
        !           127: extern char db_symtab[];
        !           128: extern int db_symtabsize;
1.3       ragge     129: #endif
1.1       ragge     130:
1.66      christos  131: /*
                    132:  * used by savecore(8) so non-static
                    133:  */
                    134: struct ksyms_hdr ksyms_hdr;
1.39      ad        135: int ksyms_symsz;
                    136: int ksyms_strsz;
1.67      christos  137: int ksyms_ctfsz;       /* this is not currently used by savecore(8) */
1.39      ad        138: TAILQ_HEAD(, ksyms_symtab) ksyms_symtabs =
                    139:     TAILQ_HEAD_INITIALIZER(ksyms_symtabs);
1.1       ragge     140:
1.33      christos  141: static int
                    142: ksyms_verify(void *symstart, void *strstart)
                    143: {
                    144: #if defined(DIAGNOSTIC) || defined(DEBUG)
                    145:        if (symstart == NULL)
                    146:                printf("ksyms: Symbol table not found\n");
                    147:        if (strstart == NULL)
                    148:                printf("ksyms: String table not found\n");
                    149:        if (symstart == NULL || strstart == NULL)
                    150:                printf("ksyms: Perhaps the kernel is stripped?\n");
                    151: #endif
                    152:        if (symstart == NULL || strstart == NULL)
                    153:                return 0;
                    154:        return 1;
                    155: }
                    156:
1.8       ragge     157: /*
1.43      ad        158:  * Finds a certain symbol name in a certain symbol table.
1.8       ragge     159:  */
1.43      ad        160: static Elf_Sym *
                    161: findsym(const char *name, struct ksyms_symtab *table, int type)
1.8       ragge     162: {
1.43      ad        163:        Elf_Sym *sym, *maxsym;
                    164:        int low, mid, high, nglob;
                    165:        char *str, *cmp;
                    166:
                    167:        sym = table->sd_symstart;
                    168:        str = table->sd_strstart - table->sd_usroffset;
                    169:        nglob = table->sd_nglob;
                    170:        low = 0;
                    171:        high = nglob;
1.8       ragge     172:
1.43      ad        173:        /*
                    174:         * Start with a binary search of all global symbols in this table.
                    175:         * Global symbols must have unique names.
                    176:         */
                    177:        while (low < high) {
                    178:                mid = (low + high) >> 1;
                    179:                cmp = sym[mid].st_name + str;
                    180:                if (cmp[0] < name[0] || strcmp(cmp, name) < 0) {
                    181:                        low = mid + 1;
                    182:                } else {
                    183:                        high = mid;
                    184:                }
1.8       ragge     185:        }
1.43      ad        186:        KASSERT(low == high);
                    187:        if (__predict_true(low < nglob &&
                    188:            strcmp(sym[low].st_name + str, name) == 0)) {
                    189:                KASSERT(ELF_ST_BIND(sym[low].st_info) == STB_GLOBAL);
                    190:                return &sym[low];
1.8       ragge     191:        }
                    192:
1.43      ad        193:        /*
                    194:         * Perform a linear search of local symbols (rare).  Many local
                    195:         * symbols with the same name can exist so are not included in
                    196:         * the binary search.
                    197:         */
                    198:        if (type != KSYMS_EXTERN) {
                    199:                maxsym = sym + table->sd_symsize / sizeof(Elf_Sym);
                    200:                for (sym += nglob; sym < maxsym; sym++) {
                    201:                        if (strcmp(name, sym->st_name + str) == 0) {
                    202:                                return sym;
                    203:                        }
                    204:                }
1.1       ragge     205:        }
                    206:        return NULL;
                    207: }
                    208:
                    209: /*
                    210:  * The "attach" is in reality done in ksyms_init().
                    211:  */
                    212: void
1.30      yamt      213: ksymsattach(int arg)
1.1       ragge     214: {
1.42      ad        215:
1.1       ragge     216: }
                    217:
1.47      martin    218: void
1.51      cegger    219: ksyms_init(void)
1.47      martin    220: {
                    221:
1.73    ! joerg     222: #ifdef COPY_SYMTAB
1.69      matt      223:        if (!ksyms_loaded &&
1.50      jmmv      224:            strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) {
                    225:                ksyms_addsyms_elf(db_symtabsize, db_symtab,
                    226:                    db_symtab + db_symtabsize);
                    227:        }
                    228: #endif
                    229:
1.69      matt      230:        if (!ksyms_initted) {
                    231:                mutex_init(&ksyms_lock, MUTEX_DEFAULT, IPL_NONE);
                    232:                ksyms_initted = true;
                    233:        }
1.47      martin    234: }
                    235:
1.1       ragge     236: /*
1.29      jmmv      237:  * Add a symbol table.
                    238:  * This is intended for use when the symbol table and its corresponding
                    239:  * string table are easily available.  If they are embedded in an ELF
                    240:  * image, use addsymtab_elf() instead.
                    241:  *
                    242:  * name - Symbol's table name.
                    243:  * symstart, symsize - Address and size of the symbol table.
                    244:  * strstart, strsize - Address and size of the string table.
                    245:  * tab - Symbol table to be updated with this information.
                    246:  * newstart - Address to which the symbol table has to be copied during
                    247:  *            shrinking.  If NULL, it is not moved.
1.1       ragge     248:  */
1.43      ad        249: static const char *addsymtab_strstart;
                    250:
                    251: static int
                    252: addsymtab_compar(const void *a, const void *b)
                    253: {
                    254:        const Elf_Sym *sa, *sb;
                    255:
                    256:        sa = a;
                    257:        sb = b;
                    258:
                    259:        /*
                    260:         * Split the symbol table into two, with globals at the start
                    261:         * and locals at the end.
                    262:         */
                    263:        if (ELF_ST_BIND(sa->st_info) != ELF_ST_BIND(sb->st_info)) {
                    264:                if (ELF_ST_BIND(sa->st_info) == STB_GLOBAL) {
                    265:                        return -1;
                    266:                }
                    267:                if (ELF_ST_BIND(sb->st_info) == STB_GLOBAL) {
                    268:                        return 1;
                    269:                }
                    270:        }
                    271:
                    272:        /* Within each band, sort by name. */
                    273:        return strcmp(sa->st_name + addsymtab_strstart,
                    274:            sb->st_name + addsymtab_strstart);
                    275: }
                    276:
1.1       ragge     277: static void
1.39      ad        278: addsymtab(const char *name, void *symstart, size_t symsize,
                    279:          void *strstart, size_t strsize, struct ksyms_symtab *tab,
1.56      darran    280:          void *newstart, void *ctfstart, size_t ctfsize, uint32_t *nmap)
1.1       ragge     281: {
1.46      ad        282:        Elf_Sym *sym, *nsym, ts;
1.43      ad        283:        int i, j, n, nglob;
1.8       ragge     284:        char *str;
1.56      darran    285:        int nsyms = symsize / sizeof(Elf_Sym);
                    286:
1.63      rmind     287:        /* Sanity check for pre-allocated map table used during startup. */
1.56      darran    288:        if ((nmap == ksyms_nmap) && (nsyms >= KSYMS_MAX_ID)) {
1.60      tsutsui   289:                printf("kern_ksyms: ERROR %d > %d, increase KSYMS_MAX_ID\n",
1.56      darran    290:                    nsyms, KSYMS_MAX_ID);
                    291:
1.60      tsutsui   292:                /* truncate for now */
                    293:                nsyms = KSYMS_MAX_ID - 1;
1.56      darran    294:        }
1.1       ragge     295:
1.39      ad        296:        tab->sd_symstart = symstart;
1.29      jmmv      297:        tab->sd_symsize = symsize;
                    298:        tab->sd_strstart = strstart;
                    299:        tab->sd_strsize = strsize;
1.1       ragge     300:        tab->sd_name = name;
1.44      ad        301:        tab->sd_minsym = UINTPTR_MAX;
                    302:        tab->sd_maxsym = 0;
1.39      ad        303:        tab->sd_usroffset = 0;
                    304:        tab->sd_gone = false;
1.56      darran    305:        tab->sd_ctfstart = ctfstart;
                    306:        tab->sd_ctfsize = ctfsize;
                    307:        tab->sd_nmap = nmap;
                    308:        tab->sd_nmapsize = nsyms;
1.8       ragge     309: #ifdef KSYMS_DEBUG
1.61      jakllsch  310:        printf("newstart %p sym %p ksyms_symsz %zu str %p strsz %zu send %p\n",
1.39      ad        311:            newstart, symstart, symsize, strstart, strsize,
                    312:            tab->sd_strstart + tab->sd_strsize);
1.8       ragge     313: #endif
1.1       ragge     314:
1.56      darran    315:        if (nmap) {
                    316:                memset(nmap, 0, nsyms * sizeof(uint32_t));
                    317:        }
                    318:
1.39      ad        319:        /* Pack symbol table by removing all file name references. */
1.8       ragge     320:        sym = tab->sd_symstart;
1.29      jmmv      321:        nsym = (Elf_Sym *)newstart;
1.8       ragge     322:        str = tab->sd_strstart;
1.43      ad        323:        nglob = 0;
1.56      darran    324:        for (i = n = 0; i < nsyms; i++) {
                    325:
                    326:                /* This breaks CTF mapping, so don't do it when
                    327:                 * DTrace is enabled
                    328:                 */
                    329: #ifndef KDTRACE_HOOKS
1.8       ragge     330:                /*
                    331:                 * Remove useless symbols.
                    332:                 * Should actually remove all typeless symbols.
                    333:                 */
1.5       ragge     334:                if (sym[i].st_name == 0)
1.8       ragge     335:                        continue; /* Skip nameless entries */
1.34      ad        336:                if (sym[i].st_shndx == SHN_UNDEF)
                    337:                        continue; /* Skip external references */
1.8       ragge     338:                if (ELF_ST_TYPE(sym[i].st_info) == STT_FILE)
                    339:                        continue; /* Skip filenames */
                    340:                if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE &&
                    341:                    sym[i].st_value == 0 &&
                    342:                    strcmp(str + sym[i].st_name, "*ABS*") == 0)
                    343:                        continue; /* XXX */
                    344:                if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE &&
                    345:                    strcmp(str + sym[i].st_name, "gcc2_compiled.") == 0)
                    346:                        continue; /* XXX */
1.56      darran    347: #endif
1.8       ragge     348:
                    349:                /* Save symbol. Set it as an absolute offset */
                    350:                nsym[n] = sym[i];
1.56      darran    351:
1.58      darran    352: #ifdef KDTRACE_HOOKS
1.56      darran    353:                if (nmap != NULL) {
1.60      tsutsui   354:                        /*
                    355:                         * Save the size, replace it with the symbol id so
1.56      darran    356:                         * the mapping can be done after the cleanup and sort.
                    357:                         */
                    358:                        nmap[i] = nsym[n].st_size;
1.60      tsutsui   359:                        nsym[n].st_size = i + 1;        /* zero is reserved */
1.56      darran    360:                }
1.58      darran    361: #endif
1.56      darran    362:
1.48      ad        363:                nsym[n].st_shndx = SHBSS;
1.43      ad        364:                j = strlen(nsym[n].st_name + str) + 1;
1.39      ad        365:                if (j > ksyms_maxlen)
                    366:                        ksyms_maxlen = j;
1.43      ad        367:                nglob += (ELF_ST_BIND(nsym[n].st_info) == STB_GLOBAL);
                    368:
                    369:                /* Compute min and max symbols. */
1.62      matt      370:                if (strcmp(str + sym[i].st_name, "*ABS*") != 0
                    371:                    && ELF_ST_TYPE(nsym[n].st_info) != STT_NOTYPE) {
                    372:                        if (nsym[n].st_value < tab->sd_minsym) {
                    373:                                tab->sd_minsym = nsym[n].st_value;
                    374:                        }
                    375:                        if (nsym[n].st_value > tab->sd_maxsym) {
                    376:                                tab->sd_maxsym = nsym[n].st_value;
                    377:                        }
1.43      ad        378:                }
1.8       ragge     379:                n++;
1.43      ad        380:        }
1.8       ragge     381:
1.43      ad        382:        /* Fill the rest of the record, and sort the symbols. */
1.8       ragge     383:        tab->sd_symstart = nsym;
                    384:        tab->sd_symsize = n * sizeof(Elf_Sym);
1.43      ad        385:        tab->sd_nglob = nglob;
                    386:        addsymtab_strstart = str;
1.46      ad        387:        if (kheapsort(nsym, n, sizeof(Elf_Sym), addsymtab_compar, &ts) != 0)
                    388:                panic("addsymtab");
1.43      ad        389:
1.58      darran    390: #ifdef KDTRACE_HOOKS
1.56      darran    391:        /*
                    392:         * Build the mapping from original symbol id to new symbol table.
                    393:         * Deleted symbols will have a zero map, indices will be one based
                    394:         * instead of zero based.
                    395:         * Resulting map is sd_nmap[original_index] = new_index + 1
                    396:         */
                    397:        if (nmap != NULL) {
                    398:                int new;
1.60      tsutsui   399:                for (new = 0; new < n; new++) {
1.56      darran    400:                        uint32_t orig = nsym[new].st_size - 1;
                    401:                        uint32_t size = nmap[orig];
                    402:
                    403:                        nmap[orig] = new + 1;
                    404:
                    405:                        /* restore the size */
                    406:                        nsym[new].st_size = size;
                    407:                }
                    408:        }
1.58      darran    409: #endif
1.56      darran    410:
1.39      ad        411:        /* ksymsread() is unlocked, so membar. */
                    412:        membar_producer();
                    413:        TAILQ_INSERT_TAIL(&ksyms_symtabs, tab, sd_queue);
                    414:        ksyms_sizes_calc();
1.69      matt      415:        ksyms_loaded = true;
1.1       ragge     416: }
                    417:
                    418: /*
1.39      ad        419:  * Setup the kernel symbol table stuff.
1.29      jmmv      420:  */
1.39      ad        421: void
1.47      martin    422: ksyms_addsyms_elf(int symsize, void *start, void *end)
1.29      jmmv      423: {
                    424:        int i, j;
                    425:        Elf_Shdr *shdr;
1.32      christos  426:        char *symstart = NULL, *strstart = NULL;
1.39      ad        427:        size_t strsize = 0;
1.3       ragge     428:        Elf_Ehdr *ehdr;
1.56      darran    429:        char *ctfstart = NULL;
                    430:        size_t ctfsize = 0;
1.3       ragge     431:
                    432:        if (symsize <= 0) {
                    433:                printf("[ Kernel symbol table missing! ]\n");
                    434:                return;
                    435:        }
                    436:
                    437:        /* Sanity check */
                    438:        if (ALIGNED_POINTER(start, long) == 0) {
                    439:                printf("[ Kernel symbol table has bad start address %p ]\n",
                    440:                    start);
                    441:                return;
                    442:        }
                    443:
                    444:        ehdr = (Elf_Ehdr *)start;
1.1       ragge     445:
                    446:        /* check if this is a valid ELF header */
                    447:        /* No reason to verify arch type, the kernel is actually running! */
                    448:        if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
                    449:            ehdr->e_ident[EI_CLASS] != ELFCLASS ||
                    450:            ehdr->e_version > 1) {
1.3       ragge     451:                printf("[ Kernel symbol table invalid! ]\n");
1.1       ragge     452:                return; /* nothing to do */
                    453:        }
                    454:
1.8       ragge     455:        /* Loaded header will be scratched in addsymtab */
                    456:        ksyms_hdr_init(start);
                    457:
1.39      ad        458:        /* Find the symbol table and the corresponding string table. */
                    459:        shdr = (Elf_Shdr *)((uint8_t *)start + ehdr->e_shoff);
                    460:        for (i = 1; i < ehdr->e_shnum; i++) {
                    461:                if (shdr[i].sh_type != SHT_SYMTAB)
                    462:                        continue;
                    463:                if (shdr[i].sh_offset == 0)
                    464:                        continue;
                    465:                symstart = (uint8_t *)start + shdr[i].sh_offset;
                    466:                symsize = shdr[i].sh_size;
                    467:                j = shdr[i].sh_link;
                    468:                if (shdr[j].sh_offset == 0)
                    469:                        continue; /* Can this happen? */
                    470:                strstart = (uint8_t *)start + shdr[j].sh_offset;
                    471:                strsize = shdr[j].sh_size;
                    472:                break;
                    473:        }
1.8       ragge     474:
1.58      darran    475: #ifdef KDTRACE_HOOKS
1.56      darran    476:        /* Find the CTF section */
                    477:        shdr = (Elf_Shdr *)((uint8_t *)start + ehdr->e_shoff);
                    478:        if (ehdr->e_shstrndx != 0) {
1.60      tsutsui   479:                char *shstr = (uint8_t *)start +
                    480:                    shdr[ehdr->e_shstrndx].sh_offset;
1.56      darran    481:                for (i = 1; i < ehdr->e_shnum; i++) {
1.59      darran    482: #ifdef DEBUG
                    483:                        printf("ksyms: checking %s\n", &shstr[shdr[i].sh_name]);
                    484: #endif
1.56      darran    485:                        if (shdr[i].sh_type != SHT_PROGBITS)
                    486:                                continue;
1.60      tsutsui   487:                        if (strncmp(".SUNW_ctf", &shstr[shdr[i].sh_name], 10)
                    488:                            != 0)
1.56      darran    489:                                continue;
                    490:                        ctfstart = (uint8_t *)start + shdr[i].sh_offset;
                    491:                        ctfsize = shdr[i].sh_size;
                    492:                        ksyms_ctfsz = ctfsize;
                    493: #ifdef DEBUG
1.57      christos  494:                        aprint_normal("Found CTF at %p, size 0x%zx\n",
                    495:                            ctfstart, ctfsize);
1.56      darran    496: #endif
                    497:                        break;
                    498:                }
1.59      darran    499: #ifdef DEBUG
                    500:        } else {
                    501:                printf("ksyms: e_shstrndx == 0\n");
                    502: #endif
1.56      darran    503:        }
1.58      darran    504: #endif
1.56      darran    505:
1.39      ad        506:        if (!ksyms_verify(symstart, strstart))
                    507:                return;
1.56      darran    508:
1.39      ad        509:        addsymtab("netbsd", symstart, symsize, strstart, strsize,
1.70      chs       510:            &kernel_symtab, symstart, ctfstart, ctfsize, ksyms_nmap);
1.8       ragge     511:
1.1       ragge     512: #ifdef DEBUG
1.53      hubertf   513:        aprint_normal("Loaded initial symtab at %p, strtab at %p, # entries %ld\n",
1.1       ragge     514:            kernel_symtab.sd_symstart, kernel_symtab.sd_strstart,
1.2       ragge     515:            (long)kernel_symtab.sd_symsize/sizeof(Elf_Sym));
1.1       ragge     516: #endif
                    517: }
                    518:
                    519: /*
1.29      jmmv      520:  * Setup the kernel symbol table stuff.
                    521:  * Use this when the address of the symbol and string tables are known;
                    522:  * otherwise use ksyms_init with an ELF image.
1.31      jmmv      523:  * We need to pass a minimal ELF header which will later be completed by
                    524:  * ksyms_hdr_init and handed off to userland through /dev/ksyms.  We use
1.32      christos  525:  * a void *rather than a pointer to avoid exposing the Elf_Ehdr type.
1.29      jmmv      526:  */
                    527: void
1.47      martin    528: ksyms_addsyms_explicit(void *ehdr, void *symstart, size_t symsize,
1.39      ad        529:                    void *strstart, size_t strsize)
1.29      jmmv      530: {
                    531:
1.33      christos  532:        if (!ksyms_verify(symstart, strstart))
                    533:                return;
1.29      jmmv      534:
1.31      jmmv      535:        ksyms_hdr_init(ehdr);
1.29      jmmv      536:        addsymtab("netbsd", symstart, symsize, strstart, strsize,
1.56      darran    537:            &kernel_symtab, symstart, NULL, 0, ksyms_nmap);
1.29      jmmv      538: }
                    539:
                    540: /*
1.1       ragge     541:  * Get the value associated with a symbol.
1.23      perry     542:  * "mod" is the module name, or null if any module.
1.1       ragge     543:  * "sym" is the symbol name.
                    544:  * "val" is a pointer to the corresponding value, if call succeeded.
                    545:  * Returns 0 if success or ENOENT if no such entry.
1.39      ad        546:  *
                    547:  * Call with ksyms_lock, unless known that the symbol table can't change.
1.1       ragge     548:  */
1.41      christos  549: int
1.40      christos  550: ksyms_getval_unlocked(const char *mod, const char *sym, unsigned long *val,
1.42      ad        551:                      int type)
1.1       ragge     552: {
1.39      ad        553:        struct ksyms_symtab *st;
1.1       ragge     554:        Elf_Sym *es;
                    555:
                    556: #ifdef KSYMS_DEBUG
                    557:        if (ksyms_debug & FOLLOW_CALLS)
1.40      christos  558:                printf("ksyms_getval_unlocked: mod %s sym %s valp %p\n",
                    559:                    mod, sym, val);
1.1       ragge     560: #endif
                    561:
1.39      ad        562:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
1.43      ad        563:                if (__predict_false(st->sd_gone))
1.1       ragge     564:                        continue;
1.43      ad        565:                if (mod != NULL && strcmp(st->sd_name, mod))
1.1       ragge     566:                        continue;
1.43      ad        567:                if ((es = findsym(sym, st, type)) != NULL) {
1.1       ragge     568:                        *val = es->st_value;
1.43      ad        569:                        return 0;
                    570:                }
1.1       ragge     571:        }
                    572:        return ENOENT;
                    573: }
                    574:
1.40      christos  575: int
                    576: ksyms_getval(const char *mod, const char *sym, unsigned long *val, int type)
                    577: {
                    578:        int rc;
                    579:
1.69      matt      580:        if (!ksyms_loaded)
1.43      ad        581:                return ENOENT;
                    582:
1.40      christos  583:        mutex_enter(&ksyms_lock);
                    584:        rc = ksyms_getval_unlocked(mod, sym, val, type);
                    585:        mutex_exit(&ksyms_lock);
                    586:        return rc;
                    587: }
                    588:
1.56      darran    589: struct ksyms_symtab *
                    590: ksyms_get_mod(const char *mod)
                    591: {
                    592:        struct ksyms_symtab *st;
                    593:
                    594:        mutex_enter(&ksyms_lock);
                    595:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    596:                if (__predict_false(st->sd_gone))
                    597:                        continue;
                    598:                if (mod != NULL && strcmp(st->sd_name, mod))
                    599:                        continue;
                    600:                break;
                    601:        }
                    602:        mutex_exit(&ksyms_lock);
                    603:
                    604:        return st;
                    605: }
                    606:
                    607:
                    608: /*
                    609:  * ksyms_mod_foreach()
                    610:  *
                    611:  * Iterate over the symbol table of the specified module, calling the callback
                    612:  * handler for each symbol. Stop iterating if the handler return is non-zero.
                    613:  *
                    614:  */
                    615:
                    616: int
                    617: ksyms_mod_foreach(const char *mod, ksyms_callback_t callback, void *opaque)
                    618: {
                    619:        struct ksyms_symtab *st;
                    620:        Elf_Sym *sym, *maxsym;
                    621:        char *str;
                    622:        int symindx;
                    623:
1.69      matt      624:        if (!ksyms_loaded)
1.56      darran    625:                return ENOENT;
                    626:
                    627:        mutex_enter(&ksyms_lock);
                    628:
                    629:        /* find the module */
                    630:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    631:                if (__predict_false(st->sd_gone))
                    632:                        continue;
                    633:                if (mod != NULL && strcmp(st->sd_name, mod))
                    634:                        continue;
                    635:
                    636:                sym = st->sd_symstart;
                    637:                str = st->sd_strstart - st->sd_usroffset;
                    638:
                    639:                /* now iterate through the symbols */
                    640:                maxsym = sym + st->sd_symsize / sizeof(Elf_Sym);
1.60      tsutsui   641:                for (symindx = 0; sym < maxsym; sym++, symindx++) {
1.56      darran    642:                        if (callback(str + sym->st_name, symindx,
1.60      tsutsui   643:                            (void *)sym->st_value,
                    644:                            sym->st_size,
                    645:                            sym->st_info,
                    646:                            opaque) != 0) {
1.56      darran    647:                                break;
                    648:                        }
                    649:                }
                    650:        }
                    651:        mutex_exit(&ksyms_lock);
                    652:
                    653:        return 0;
                    654: }
                    655:
1.1       ragge     656: /*
                    657:  * Get "mod" and "symbol" associated with an address.
                    658:  * Returns 0 if success or ENOENT if no such entry.
1.39      ad        659:  *
                    660:  * Call with ksyms_lock, unless known that the symbol table can't change.
1.1       ragge     661:  */
                    662: int
1.24      christos  663: ksyms_getname(const char **mod, const char **sym, vaddr_t v, int f)
1.1       ragge     664: {
1.39      ad        665:        struct ksyms_symtab *st;
1.1       ragge     666:        Elf_Sym *les, *es = NULL;
                    667:        vaddr_t laddr = 0;
1.15      christos  668:        const char *lmod = NULL;
                    669:        char *stable = NULL;
1.1       ragge     670:        int type, i, sz;
                    671:
1.69      matt      672:        if (!ksyms_loaded)
1.1       ragge     673:                return ENOENT;
                    674:
1.39      ad        675:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    676:                if (st->sd_gone)
                    677:                        continue;
1.44      ad        678:                if (v < st->sd_minsym || v > st->sd_maxsym)
1.35      matt      679:                        continue;
1.1       ragge     680:                sz = st->sd_symsize/sizeof(Elf_Sym);
                    681:                for (i = 0; i < sz; i++) {
                    682:                        les = st->sd_symstart + i;
                    683:                        type = ELF_ST_TYPE(les->st_info);
                    684:
                    685:                        if ((f & KSYMS_PROC) && (type != STT_FUNC))
                    686:                                continue;
                    687:
                    688:                        if (type == STT_NOTYPE)
                    689:                                continue;
                    690:
                    691:                        if (((f & KSYMS_ANY) == 0) &&
                    692:                            (type != STT_FUNC) && (type != STT_OBJECT))
                    693:                                continue;
                    694:
                    695:                        if ((les->st_value <= v) && (les->st_value > laddr)) {
                    696:                                laddr = les->st_value;
                    697:                                es = les;
                    698:                                lmod = st->sd_name;
1.17      cube      699:                                stable = st->sd_strstart - st->sd_usroffset;
1.1       ragge     700:                        }
                    701:                }
                    702:        }
                    703:        if (es == NULL)
                    704:                return ENOENT;
                    705:        if ((f & KSYMS_EXACT) && (v != es->st_value))
                    706:                return ENOENT;
                    707:        if (mod)
                    708:                *mod = lmod;
                    709:        if (sym)
                    710:                *sym = stable + es->st_name;
                    711:        return 0;
                    712: }
                    713:
1.22      cube      714: /*
1.39      ad        715:  * Add a symbol table from a loadable module.
                    716:  */
                    717: void
                    718: ksyms_modload(const char *name, void *symstart, vsize_t symsize,
                    719:              char *strstart, vsize_t strsize)
1.17      cube      720: {
1.39      ad        721:        struct ksyms_symtab *st;
                    722:
                    723:        st = kmem_zalloc(sizeof(*st), KM_SLEEP);
                    724:        mutex_enter(&ksyms_lock);
1.56      darran    725:        addsymtab(name, symstart, symsize, strstart, strsize, st, symstart,
1.60      tsutsui   726:            NULL, 0, NULL);
1.39      ad        727:        mutex_exit(&ksyms_lock);
                    728: }
1.17      cube      729:
1.39      ad        730: /*
                    731:  * Remove a symbol table from a loadable module.
                    732:  */
                    733: void
                    734: ksyms_modunload(const char *name)
                    735: {
                    736:        struct ksyms_symtab *st;
1.17      cube      737:
1.39      ad        738:        mutex_enter(&ksyms_lock);
                    739:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    740:                if (st->sd_gone)
                    741:                        continue;
                    742:                if (strcmp(name, st->sd_name) != 0)
                    743:                        continue;
                    744:                st->sd_gone = true;
                    745:                if (!ksyms_isopen) {
                    746:                        TAILQ_REMOVE(&ksyms_symtabs, st, sd_queue);
                    747:                        ksyms_sizes_calc();
                    748:                        kmem_free(st, sizeof(*st));
                    749:                }
                    750:                break;
                    751:        }
                    752:        mutex_exit(&ksyms_lock);
                    753:        KASSERT(st != NULL);
1.17      cube      754: }
                    755:
1.1       ragge     756: #ifdef DDB
                    757: /*
                    758:  * Keep sifting stuff here, to avoid export of ksyms internals.
1.39      ad        759:  *
                    760:  * Systems is expected to be quiescent, so no locking done.
1.1       ragge     761:  */
                    762: int
                    763: ksyms_sift(char *mod, char *sym, int mode)
                    764: {
1.39      ad        765:        struct ksyms_symtab *st;
1.1       ragge     766:        char *sb;
                    767:        int i, sz;
                    768:
1.69      matt      769:        if (!ksyms_loaded)
1.1       ragge     770:                return ENOENT;
                    771:
1.39      ad        772:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    773:                if (st->sd_gone)
                    774:                        continue;
1.1       ragge     775:                if (mod && strcmp(mod, st->sd_name))
                    776:                        continue;
1.39      ad        777:                sb = st->sd_strstart - st->sd_usroffset;
1.1       ragge     778:
                    779:                sz = st->sd_symsize/sizeof(Elf_Sym);
                    780:                for (i = 0; i < sz; i++) {
                    781:                        Elf_Sym *les = st->sd_symstart + i;
                    782:                        char c;
                    783:
1.39      ad        784:                        if (strstr(sb + les->st_name, sym) == NULL)
1.1       ragge     785:                                continue;
                    786:
                    787:                        if (mode == 'F') {
                    788:                                switch (ELF_ST_TYPE(les->st_info)) {
                    789:                                case STT_OBJECT:
                    790:                                        c = '+';
                    791:                                        break;
                    792:                                case STT_FUNC:
                    793:                                        c = '*';
                    794:                                        break;
                    795:                                case STT_SECTION:
                    796:                                        c = '&';
                    797:                                        break;
                    798:                                case STT_FILE:
                    799:                                        c = '/';
                    800:                                        break;
                    801:                                default:
                    802:                                        c = ' ';
                    803:                                        break;
                    804:                                }
1.39      ad        805:                                db_printf("%s%c ", sb + les->st_name, c);
1.1       ragge     806:                        } else
1.39      ad        807:                                db_printf("%s ", sb + les->st_name);
1.1       ragge     808:                }
                    809:        }
                    810:        return ENOENT;
                    811: }
1.25      thorpej   812: #endif /* DDB */
1.1       ragge     813:
                    814: /*
1.39      ad        815:  * In case we exposing the symbol table to the userland using the pseudo-
                    816:  * device /dev/ksyms, it is easier to provide all the tables as one.
                    817:  * However, it means we have to change all the st_name fields for the
                    818:  * symbols so they match the ELF image that the userland will read
                    819:  * through the device.
                    820:  *
                    821:  * The actual (correct) value of st_name is preserved through a global
                    822:  * offset stored in the symbol table structure.
                    823:  *
                    824:  * Call with ksyms_lock held.
1.1       ragge     825:  */
1.39      ad        826: static void
                    827: ksyms_sizes_calc(void)
                    828: {
                    829:         struct ksyms_symtab *st;
                    830:        int i, delta;
1.1       ragge     831:
1.39      ad        832:         ksyms_symsz = ksyms_strsz = 0;
                    833:         TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                    834:                delta = ksyms_strsz - st->sd_usroffset;
                    835:                if (delta != 0) {
                    836:                        for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++)
                    837:                                st->sd_symstart[i].st_name += delta;
                    838:                        st->sd_usroffset = ksyms_strsz;
                    839:                }
                    840:                 ksyms_symsz += st->sd_symsize;
                    841:                 ksyms_strsz += st->sd_strsize;
                    842:         }
                    843: }
1.1       ragge     844:
1.25      thorpej   845: static void
1.32      christos  846: ksyms_hdr_init(void *hdraddr)
1.1       ragge     847: {
                    848:
                    849:        /* Copy the loaded elf exec header */
                    850:        memcpy(&ksyms_hdr.kh_ehdr, hdraddr, sizeof(Elf_Ehdr));
                    851:
                    852:        /* Set correct program/section header sizes, offsets and numbers */
                    853:        ksyms_hdr.kh_ehdr.e_phoff = offsetof(struct ksyms_hdr, kh_phdr[0]);
                    854:        ksyms_hdr.kh_ehdr.e_phentsize = sizeof(Elf_Phdr);
                    855:        ksyms_hdr.kh_ehdr.e_phnum = NPRGHDR;
                    856:        ksyms_hdr.kh_ehdr.e_shoff = offsetof(struct ksyms_hdr, kh_shdr[0]);
                    857:        ksyms_hdr.kh_ehdr.e_shentsize = sizeof(Elf_Shdr);
                    858:        ksyms_hdr.kh_ehdr.e_shnum = NSECHDR;
1.48      ad        859:        ksyms_hdr.kh_ehdr.e_shstrndx = SHSTRTAB;
1.1       ragge     860:
1.48      ad        861:        /* Text/data - fake */
1.39      ad        862:        ksyms_hdr.kh_phdr[0].p_type = PT_LOAD;
                    863:        ksyms_hdr.kh_phdr[0].p_memsz = (unsigned long)-1L;
1.48      ad        864:        ksyms_hdr.kh_phdr[0].p_flags = PF_R | PF_X | PF_W;
1.39      ad        865:
                    866:        /* First section is null */
1.1       ragge     867:
                    868:        /* Second section header; ".symtab" */
                    869:        ksyms_hdr.kh_shdr[SYMTAB].sh_name = 1; /* Section 3 offset */
                    870:        ksyms_hdr.kh_shdr[SYMTAB].sh_type = SHT_SYMTAB;
                    871:        ksyms_hdr.kh_shdr[SYMTAB].sh_offset = sizeof(struct ksyms_hdr);
                    872: /*     ksyms_hdr.kh_shdr[SYMTAB].sh_size = filled in at open */
                    873:        ksyms_hdr.kh_shdr[SYMTAB].sh_link = 2; /* Corresponding strtab */
                    874:        ksyms_hdr.kh_shdr[SYMTAB].sh_addralign = sizeof(long);
                    875:        ksyms_hdr.kh_shdr[SYMTAB].sh_entsize = sizeof(Elf_Sym);
                    876:
                    877:        /* Third section header; ".strtab" */
                    878:        ksyms_hdr.kh_shdr[STRTAB].sh_name = 9; /* Section 3 offset */
                    879:        ksyms_hdr.kh_shdr[STRTAB].sh_type = SHT_STRTAB;
                    880: /*     ksyms_hdr.kh_shdr[STRTAB].sh_offset = filled in at open */
                    881: /*     ksyms_hdr.kh_shdr[STRTAB].sh_size = filled in at open */
                    882:        ksyms_hdr.kh_shdr[STRTAB].sh_addralign = sizeof(char);
                    883:
                    884:        /* Fourth section, ".shstrtab" */
                    885:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_name = 17; /* This section name offset */
                    886:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_type = SHT_STRTAB;
                    887:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_offset =
                    888:            offsetof(struct ksyms_hdr, kh_strtab);
                    889:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_size = SHSTRSIZ;
                    890:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_addralign = sizeof(char);
                    891:
1.48      ad        892:        /* Fifth section, ".bss". All symbols reside here. */
                    893:        ksyms_hdr.kh_shdr[SHBSS].sh_name = 27; /* This section name offset */
1.55      darran    894:        ksyms_hdr.kh_shdr[SHBSS].sh_type = SHT_NOBITS;
1.48      ad        895:        ksyms_hdr.kh_shdr[SHBSS].sh_offset = 0;
                    896:        ksyms_hdr.kh_shdr[SHBSS].sh_size = (unsigned long)-1L;
                    897:        ksyms_hdr.kh_shdr[SHBSS].sh_addralign = PAGE_SIZE;
                    898:        ksyms_hdr.kh_shdr[SHBSS].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
                    899:
1.56      darran    900:        /* Sixth section header; ".SUNW_ctf" */
                    901:        ksyms_hdr.kh_shdr[SHCTF].sh_name = 32; /* Section 6 offset */
                    902:        ksyms_hdr.kh_shdr[SHCTF].sh_type = SHT_PROGBITS;
                    903: /*     ksyms_hdr.kh_shdr[SHCTF].sh_offset = filled in at open */
                    904: /*     ksyms_hdr.kh_shdr[SHCTF].sh_size = filled in at open */
                    905:        ksyms_hdr.kh_shdr[SHCTF].sh_link = SYMTAB; /* Corresponding symtab */
                    906:        ksyms_hdr.kh_shdr[SHCTF].sh_addralign = sizeof(char);
                    907:
1.1       ragge     908:        /* Set section names */
1.10      itojun    909:        strlcpy(&ksyms_hdr.kh_strtab[1], ".symtab",
                    910:            sizeof(ksyms_hdr.kh_strtab) - 1);
                    911:        strlcpy(&ksyms_hdr.kh_strtab[9], ".strtab",
                    912:            sizeof(ksyms_hdr.kh_strtab) - 9);
                    913:        strlcpy(&ksyms_hdr.kh_strtab[17], ".shstrtab",
                    914:            sizeof(ksyms_hdr.kh_strtab) - 17);
1.48      ad        915:        strlcpy(&ksyms_hdr.kh_strtab[27], ".bss",
                    916:            sizeof(ksyms_hdr.kh_strtab) - 27);
1.56      darran    917:        strlcpy(&ksyms_hdr.kh_strtab[32], ".SUNW_ctf",
                    918:            sizeof(ksyms_hdr.kh_strtab) - 32);
1.39      ad        919: }
1.1       ragge     920:
1.25      thorpej   921: static int
1.30      yamt      922: ksymsopen(dev_t dev, int oflags, int devtype, struct lwp *l)
1.1       ragge     923: {
                    924:
1.69      matt      925:        if (minor(dev) != 0 || !ksyms_loaded)
1.18      cube      926:                return ENXIO;
1.1       ragge     927:
1.39      ad        928:        /*
                    929:         * Create a "snapshot" of the kernel symbol table.  Setting
                    930:         * ksyms_isopen will prevent symbol tables from being freed.
                    931:         */
                    932:        mutex_enter(&ksyms_lock);
                    933:        ksyms_hdr.kh_shdr[SYMTAB].sh_size = ksyms_symsz;
                    934:        ksyms_hdr.kh_shdr[SYMTAB].sh_info = ksyms_symsz / sizeof(Elf_Sym);
1.55      darran    935:        ksyms_hdr.kh_shdr[STRTAB].sh_offset = ksyms_symsz +
1.1       ragge     936:            ksyms_hdr.kh_shdr[SYMTAB].sh_offset;
1.39      ad        937:        ksyms_hdr.kh_shdr[STRTAB].sh_size = ksyms_strsz;
1.56      darran    938:        ksyms_hdr.kh_shdr[SHCTF].sh_offset = ksyms_strsz +
                    939:            ksyms_hdr.kh_shdr[STRTAB].sh_offset;
                    940:        ksyms_hdr.kh_shdr[SHCTF].sh_size = ksyms_ctfsz;
1.39      ad        941:        ksyms_isopen = true;
                    942:        mutex_exit(&ksyms_lock);
1.1       ragge     943:
                    944:        return 0;
                    945: }
                    946:
1.25      thorpej   947: static int
1.30      yamt      948: ksymsclose(dev_t dev, int oflags, int devtype, struct lwp *l)
1.1       ragge     949: {
1.39      ad        950:        struct ksyms_symtab *st, *next;
                    951:        bool resize;
1.1       ragge     952:
1.39      ad        953:        /* Discard refernces to symbol tables. */
                    954:        mutex_enter(&ksyms_lock);
                    955:        ksyms_isopen = false;
                    956:        resize = false;
                    957:        for (st = TAILQ_FIRST(&ksyms_symtabs); st != NULL; st = next) {
                    958:                next = TAILQ_NEXT(st, sd_queue);
                    959:                if (st->sd_gone) {
                    960:                        TAILQ_REMOVE(&ksyms_symtabs, st, sd_queue);
                    961:                        kmem_free(st, sizeof(*st));
                    962:                        resize = true;
                    963:                }
                    964:        }
                    965:        if (resize)
                    966:                ksyms_sizes_calc();
                    967:        mutex_exit(&ksyms_lock);
1.1       ragge     968:
                    969:        return 0;
                    970: }
                    971:
1.25      thorpej   972: static int
1.30      yamt      973: ksymsread(dev_t dev, struct uio *uio, int ioflag)
1.1       ragge     974: {
1.58      darran    975:        struct ksyms_symtab *st;
1.1       ragge     976:        size_t filepos, inpos, off;
1.39      ad        977:        int error;
1.1       ragge     978:
                    979:        /*
1.39      ad        980:         * First: Copy out the ELF header.   XXX Lose if ksymsopen()
                    981:         * occurs during read of the header.
1.1       ragge     982:         */
1.39      ad        983:        off = uio->uio_offset;
                    984:        if (off < sizeof(struct ksyms_hdr)) {
                    985:                error = uiomove((char *)&ksyms_hdr + off,
                    986:                    sizeof(struct ksyms_hdr) - off, uio);
                    987:                if (error != 0)
                    988:                        return error;
                    989:        }
1.1       ragge     990:
                    991:        /*
                    992:         * Copy out the symbol table.
                    993:         */
1.39      ad        994:        filepos = sizeof(struct ksyms_hdr);
                    995:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
1.1       ragge     996:                if (uio->uio_resid == 0)
                    997:                        return 0;
                    998:                if (uio->uio_offset <= st->sd_symsize + filepos) {
                    999:                        inpos = uio->uio_offset - filepos;
1.39      ad       1000:                        error = uiomove((char *)st->sd_symstart + inpos,
1.1       ragge    1001:                           st->sd_symsize - inpos, uio);
1.39      ad       1002:                        if (error != 0)
                   1003:                                return error;
1.1       ragge    1004:                }
                   1005:                filepos += st->sd_symsize;
                   1006:        }
                   1007:
                   1008:        /*
                   1009:         * Copy out the string table
                   1010:         */
1.39      ad       1011:        KASSERT(filepos == sizeof(struct ksyms_hdr) +
1.55      darran   1012:            ksyms_hdr.kh_shdr[SYMTAB].sh_size);
1.39      ad       1013:        TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
1.1       ragge    1014:                if (uio->uio_resid == 0)
                   1015:                        return 0;
                   1016:                if (uio->uio_offset <= st->sd_strsize + filepos) {
                   1017:                        inpos = uio->uio_offset - filepos;
1.39      ad       1018:                        error = uiomove((char *)st->sd_strstart + inpos,
1.1       ragge    1019:                           st->sd_strsize - inpos, uio);
1.39      ad       1020:                        if (error != 0)
                   1021:                                return error;
1.1       ragge    1022:                }
                   1023:                filepos += st->sd_strsize;
                   1024:        }
1.39      ad       1025:
1.56      darran   1026:        /*
                   1027:         * Copy out the CTF table.
                   1028:         */
1.68      chs      1029:        st = TAILQ_FIRST(&ksyms_symtabs);
                   1030:        if (st->sd_ctfstart != NULL) {
1.56      darran   1031:                if (uio->uio_resid == 0)
                   1032:                        return 0;
1.68      chs      1033:                if (uio->uio_offset <= st->sd_ctfsize + filepos) {
1.56      darran   1034:                        inpos = uio->uio_offset - filepos;
1.68      chs      1035:                        error = uiomove((char *)st->sd_ctfstart + inpos,
                   1036:                            st->sd_ctfsize - inpos, uio);
1.56      darran   1037:                        if (error != 0)
                   1038:                                return error;
                   1039:                }
1.68      chs      1040:                filepos += st->sd_ctfsize;
1.56      darran   1041:        }
                   1042:
1.1       ragge    1043:        return 0;
                   1044: }
                   1045:
1.25      thorpej  1046: static int
1.30      yamt     1047: ksymswrite(dev_t dev, struct uio *uio, int ioflag)
1.1       ragge    1048: {
1.30      yamt     1049:
1.1       ragge    1050:        return EROFS;
                   1051: }
                   1052:
1.25      thorpej  1053: static int
1.32      christos 1054: ksymsioctl(dev_t dev, u_long cmd, void *data, int fflag, struct lwp *l)
1.1       ragge    1055: {
                   1056:        struct ksyms_gsymbol *kg = (struct ksyms_gsymbol *)data;
1.39      ad       1057:        struct ksyms_symtab *st;
                   1058:        Elf_Sym *sym = NULL, copy;
1.1       ragge    1059:        unsigned long val;
                   1060:        int error = 0;
1.15      christos 1061:        char *str = NULL;
1.39      ad       1062:        int len;
                   1063:
                   1064:        /* Read ksyms_maxlen only once while not holding the lock. */
                   1065:        len = ksyms_maxlen;
1.5       ragge    1066:
1.39      ad       1067:        if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) {
                   1068:                str = kmem_alloc(len, KM_SLEEP);
                   1069:                if ((error = copyinstr(kg->kg_name, str, len, NULL)) != 0) {
                   1070:                        kmem_free(str, len);
                   1071:                        return error;
                   1072:                }
                   1073:        }
1.1       ragge    1074:
                   1075:        switch (cmd) {
                   1076:        case KIOCGVALUE:
                   1077:                /*
                   1078:                 * Use the in-kernel symbol lookup code for fast
                   1079:                 * retreival of a value.
                   1080:                 */
1.39      ad       1081:                error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN);
                   1082:                if (error == 0)
                   1083:                        error = copyout(&val, kg->kg_value, sizeof(long));
                   1084:                kmem_free(str, len);
1.1       ragge    1085:                break;
                   1086:
                   1087:        case KIOCGSYMBOL:
                   1088:                /*
                   1089:                 * Use the in-kernel symbol lookup code for fast
                   1090:                 * retreival of a symbol.
                   1091:                 */
1.39      ad       1092:                mutex_enter(&ksyms_lock);
                   1093:                TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
                   1094:                        if (st->sd_gone)
                   1095:                                continue;
1.43      ad       1096:                        if ((sym = findsym(str, st, KSYMS_ANY)) == NULL)
1.1       ragge    1097:                                continue;
1.36      christos 1098: #ifdef notdef
1.1       ragge    1099:                        /* Skip if bad binding */
                   1100:                        if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) {
                   1101:                                sym = NULL;
                   1102:                                continue;
                   1103:                        }
1.36      christos 1104: #endif
1.1       ragge    1105:                        break;
                   1106:                }
1.39      ad       1107:                if (sym != NULL) {
                   1108:                        memcpy(&copy, sym, sizeof(copy));
                   1109:                        mutex_exit(&ksyms_lock);
                   1110:                        error = copyout(&copy, kg->kg_sym, sizeof(Elf_Sym));
                   1111:                } else {
                   1112:                        mutex_exit(&ksyms_lock);
1.1       ragge    1113:                        error = ENOENT;
1.39      ad       1114:                }
                   1115:                kmem_free(str, len);
1.1       ragge    1116:                break;
                   1117:
                   1118:        case KIOCGSIZE:
                   1119:                /*
                   1120:                 * Get total size of symbol table.
                   1121:                 */
1.39      ad       1122:                mutex_enter(&ksyms_lock);
                   1123:                *(int *)data = ksyms_strsz + ksyms_symsz +
                   1124:                    sizeof(struct ksyms_hdr);
                   1125:                mutex_exit(&ksyms_lock);
1.1       ragge    1126:                break;
                   1127:
                   1128:        default:
                   1129:                error = ENOTTY;
                   1130:                break;
                   1131:        }
1.5       ragge    1132:
                   1133:        return error;
1.1       ragge    1134: }
1.25      thorpej  1135:
                   1136: const struct cdevsw ksyms_cdevsw = {
1.71      dholland 1137:        .d_open = ksymsopen,
                   1138:        .d_close = ksymsclose,
                   1139:        .d_read = ksymsread,
                   1140:        .d_write = ksymswrite,
                   1141:        .d_ioctl = ksymsioctl,
                   1142:        .d_stop = nullstop,
                   1143:        .d_tty = notty,
                   1144:        .d_poll = nopoll,
                   1145:        .d_mmap = nommap,
                   1146:        .d_kqfilter = nullkqfilter,
1.72      dholland 1147:        .d_discard = nodiscard,
1.71      dholland 1148:        .d_flag = D_OTHER | D_MPSAFE
1.25      thorpej  1149: };

CVSweb <webmaster@jp.NetBSD.org>