[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.31

1.1       ragge       1: /*
                      2:  * Copyright (c) 2001, 2003 Anders Magnusson (ragge@ludd.luth.se).
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: /*
                     29:  * Code to deal with in-kernel symbol table management + /dev/ksyms.
                     30:  *
                     31:  * For each loaded module the symbol table info is kept track of by a
                     32:  * struct, placed in a circular list. The first entry is the kernel
                     33:  * symbol table.
                     34:  */
                     35:
                     36: /*
                     37:  * TODO:
                     38:  *     Change the ugly way of adding new symbols (comes with linker)
                     39:  *     Add kernel locking stuff.
                     40:  *     (Ev) add support for poll.
                     41:  *     (Ev) fix support for mmap.
                     42:  *
                     43:  *     Export ksyms internal logic for use in post-mortem debuggers?
                     44:  *       Need to move struct symtab to ksyms.h for that.
                     45:  */
1.11      jdolecek   46:
                     47: #include <sys/cdefs.h>
1.31    ! jmmv       48: __KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.30 2006/11/01 10:17:58 yamt Exp $");
1.1       ragge      49:
                     50: #ifdef _KERNEL
                     51: #include "opt_ddb.h"
1.3       ragge      52: #include "opt_ddbparam.h"      /* for SYMTAB_SPACE */
1.1       ragge      53: #endif
                     54:
                     55: #include <sys/param.h>
                     56: #include <sys/errno.h>
                     57: #include <sys/queue.h>
                     58: #include <sys/exec.h>
                     59: #include <sys/systm.h>
                     60: #include <sys/conf.h>
                     61: #include <sys/device.h>
                     62: #include <sys/malloc.h>
                     63: #include <sys/proc.h>
                     64:
                     65: #include <machine/elf_machdep.h> /* XXX */
                     66: #define ELFSIZE ARCH_ELFSIZE
                     67:
                     68: #include <sys/exec_elf.h>
                     69: #include <sys/ksyms.h>
                     70:
                     71: #include <lib/libkern/libkern.h>
                     72:
                     73: #ifdef DDB
                     74: #include <ddb/db_output.h>
                     75: #endif
                     76:
                     77: #include "ksyms.h"
                     78:
                     79: static int ksymsinited = 0;
                     80:
                     81: #if NKSYMS
                     82: static void ksyms_hdr_init(caddr_t hdraddr);
                     83: static void ksyms_sizes_calc(void);
                     84: static int ksyms_isopen;
1.5       ragge      85: static int ksyms_maxlen;
1.1       ragge      86: #endif
                     87:
                     88: #ifdef KSYMS_DEBUG
                     89: #define        FOLLOW_CALLS            1
                     90: #define        FOLLOW_MORE_CALLS       2
                     91: #define        FOLLOW_DEVKSYMS         4
                     92: static int ksyms_debug;
                     93: #endif
                     94:
1.3       ragge      95: #ifdef SYMTAB_SPACE
                     96: #define                SYMTAB_FILLER   "|This is the symbol table!"
                     97:
                     98: char           db_symtab[SYMTAB_SPACE] = SYMTAB_FILLER;
                     99: int            db_symtabsize = SYMTAB_SPACE;
                    100: #endif
1.1       ragge     101:
                    102: /*
                    103:  * Store the different symbol tables in a double-linked list.
                    104:  */
                    105: struct symtab {
                    106:        CIRCLEQ_ENTRY(symtab) sd_queue;
1.9       jdolecek  107:        const char *sd_name;    /* Name of this table */
1.1       ragge     108:        Elf_Sym *sd_symstart;   /* Address of symbol table */
                    109:        caddr_t sd_strstart;    /* Adderss of corresponding string table */
1.17      cube      110:        int sd_usroffset;       /* Real address for userspace */
1.1       ragge     111:        int sd_symsize;         /* Size in bytes of symbol table */
                    112:        int sd_strsize;         /* Size of string table */
                    113:        int *sd_symnmoff;       /* Used when calculating the name offset */
                    114: };
                    115:
                    116: static CIRCLEQ_HEAD(, symtab) symtab_queue =
                    117:     CIRCLEQ_HEAD_INITIALIZER(symtab_queue);
                    118:
                    119: static struct symtab kernel_symtab;
                    120:
1.8       ragge     121: #define        USE_PTREE
                    122: #ifdef USE_PTREE
                    123: /*
                    124:  * Patricia-tree-based lookup structure for the in-kernel global symbols.
                    125:  * Based on a design by Mikael Sundstrom, msm@sm.luth.se.
                    126:  */
                    127: struct ptree {
                    128:        int16_t bitno;
                    129:        int16_t lr[2];
                    130: } *symb;
                    131: static int16_t baseidx;
                    132: static int treex = 1;
                    133:
                    134: #define        P_BIT(key, bit) ((key[bit >> 3] >> (bit & 7)) & 1)
                    135: #define        STRING(idx) kernel_symtab.sd_symstart[idx].st_name + \
                    136:                        kernel_symtab.sd_strstart
                    137:
                    138: /*
                    139:  * Walk down the tree until a terminal node is found.
                    140:  */
                    141: static int
1.24      christos  142: symbol_traverse(const char *key)
1.8       ragge     143: {
                    144:        int16_t nb, rbit = baseidx;
                    145:
                    146:        while (rbit > 0) {
                    147:                nb = symb[rbit].bitno;
                    148:                rbit = symb[rbit].lr[P_BIT(key, nb)];
                    149:        }
                    150:        return -rbit;
                    151: }
                    152:
                    153: static int
                    154: ptree_add(char *key, int val)
                    155: {
                    156:        int idx;
1.15      christos  157:        int nix, cix, bit, rbit, sb, lastrbit, svbit = 0, ix;
1.8       ragge     158:        char *m, *k;
                    159:
                    160:        if (baseidx == 0) {
                    161:                baseidx = -val;
                    162:                return 0; /* First element */
                    163:        }
                    164:
                    165:        /* Get string to match against */
                    166:        idx = symbol_traverse(key);
                    167:
                    168:        /* Find first mismatching bit */
                    169:        m = STRING(idx);
                    170:        k = key;
                    171:        if (strcmp(m, k) == 0)
                    172:                return 1;
                    173:
                    174:        for (cix = 0; *m && *k && *m == *k; m++, k++, cix += 8)
                    175:                ;
                    176:        ix = ffs((int)*m ^ (int)*k) - 1;
                    177:        cix += ix;
                    178:
                    179:        /* Create new node */
                    180:        nix = treex++;
                    181:        bit = P_BIT(key, cix);
                    182:        symb[nix].bitno = cix;
                    183:        symb[nix].lr[bit] = -val;
                    184:
                    185:        /* Find where to insert node */
                    186:        rbit = baseidx;
                    187:        lastrbit = 0;
                    188:        for (;;) {
                    189:                if (rbit < 0)
                    190:                        break;
                    191:                sb = symb[rbit].bitno;
                    192:                if (sb > cix)
                    193:                        break;
                    194:                if (sb == cix)
                    195:                        printf("symb[rbit].bitno == cix!!!\n");
                    196:                lastrbit = rbit;
                    197:                svbit = P_BIT(key, sb);
                    198:                rbit = symb[rbit].lr[svbit];
                    199:        }
                    200:
                    201:        /* Do the actual insertion */
                    202:        if (lastrbit == 0) {
                    203:                /* first element */
                    204:                symb[nix].lr[!bit] = baseidx;
                    205:                baseidx = nix;
                    206:        } else {
                    207:                symb[nix].lr[!bit] = rbit;
                    208:                symb[lastrbit].lr[svbit] = nix;
                    209:        }
                    210:        return 0;
                    211: }
                    212:
                    213: static int
1.24      christos  214: ptree_find(const char *key)
1.8       ragge     215: {
                    216:        int idx;
                    217:
                    218:        if (baseidx == 0)
                    219:                return 0;
                    220:        idx = symbol_traverse(key);
                    221:
                    222:        if (strcmp(key, STRING(idx)) == 0)
                    223:                return idx;
                    224:        return 0;
                    225: }
                    226:
                    227: static void
                    228: ptree_gen(char *off, struct symtab *tab)
                    229: {
                    230:        Elf_Sym *sym;
1.16      ragge     231:        int i, nsym;
1.8       ragge     232:
                    233:        if (off != NULL)
                    234:                symb = (struct ptree *)ALIGN(off);
                    235:        else
                    236:                symb = malloc((tab->sd_symsize/sizeof(Elf_Sym)) *
                    237:                    sizeof(struct ptree), M_DEVBUF, M_WAITOK);
                    238:        symb--; /* sym index won't be 0 */
                    239:
                    240:        sym = tab->sd_symstart;
1.16      ragge     241:        if ((nsym = tab->sd_symsize/sizeof(Elf_Sym)) > INT16_MAX) {
                    242:                printf("Too many symbols for tree, skipping %d symbols\n",
                    243:                    nsym-INT16_MAX);
                    244:                nsym = INT16_MAX;
                    245:        }
                    246:        for (i = 1; i < nsym; i++) {
1.8       ragge     247:                if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL)
                    248:                        continue;
                    249:                ptree_add(tab->sd_strstart+sym[i].st_name, i);
                    250:        }
                    251: }
1.25      thorpej   252: #endif /* USE_PTREE */
1.8       ragge     253:
1.1       ragge     254: /*
                    255:  * Finds a certain symbol name in a certain symbol table.
                    256:  */
                    257: static Elf_Sym *
1.24      christos  258: findsym(const char *name, struct symtab *table)
1.1       ragge     259: {
                    260:        Elf_Sym *start = table->sd_symstart;
                    261:        int i, sz = table->sd_symsize/sizeof(Elf_Sym);
                    262:        char *np;
1.22      cube      263:        caddr_t realstart = table->sd_strstart - table->sd_usroffset;
1.1       ragge     264:
1.8       ragge     265: #ifdef USE_PTREE
                    266:        if (table == &kernel_symtab && (i = ptree_find(name)) != 0)
                    267:                return &start[i];
                    268: #endif
                    269:
1.1       ragge     270:        for (i = 0; i < sz; i++) {
1.17      cube      271:                np = realstart + start[i].st_name;
1.1       ragge     272:                if (name[0] == np[0] && name[1] == np[1] &&
                    273:                    strcmp(name, np) == 0)
                    274:                        return &start[i];
                    275:        }
                    276:        return NULL;
                    277: }
                    278:
                    279: /*
                    280:  * The "attach" is in reality done in ksyms_init().
                    281:  */
                    282: void ksymsattach(int);
                    283: void
1.30      yamt      284: ksymsattach(int arg)
1.1       ragge     285: {
1.8       ragge     286:
                    287: #ifdef USE_PTREE
                    288:        if (baseidx == 0)
                    289:                ptree_gen(0, &kernel_symtab);
                    290: #endif
                    291:
1.1       ragge     292: }
                    293:
                    294: /*
1.29      jmmv      295:  * Add a symbol table.
                    296:  * This is intended for use when the symbol table and its corresponding
                    297:  * string table are easily available.  If they are embedded in an ELF
                    298:  * image, use addsymtab_elf() instead.
                    299:  *
                    300:  * name - Symbol's table name.
                    301:  * symstart, symsize - Address and size of the symbol table.
                    302:  * strstart, strsize - Address and size of the string table.
                    303:  * tab - Symbol table to be updated with this information.
                    304:  * newstart - Address to which the symbol table has to be copied during
                    305:  *            shrinking.  If NULL, it is not moved.
1.1       ragge     306:  */
                    307: static void
1.29      jmmv      308: addsymtab(const char *name,
                    309:     caddr_t symstart, size_t symsize,
                    310:     caddr_t strstart, size_t strsize,
                    311:     struct symtab *tab,
                    312:     caddr_t newstart)
1.1       ragge     313: {
1.8       ragge     314:        caddr_t send;
                    315:        Elf_Sym *sym, *nsym;
1.29      jmmv      316:        int i, n, g;
1.8       ragge     317:        char *str;
1.1       ragge     318:
1.29      jmmv      319:        if (newstart == NULL)
                    320:                newstart = symstart;
                    321:        KASSERT(newstart <= symstart && symstart <= strstart);
                    322:
                    323:        tab->sd_symstart = (Elf_Sym *)symstart;
                    324:        tab->sd_symsize = symsize;
                    325:        tab->sd_strstart = strstart;
                    326:        tab->sd_strsize = strsize;
1.1       ragge     327:        tab->sd_name = name;
1.8       ragge     328:        send = tab->sd_strstart + tab->sd_strsize;
                    329:
                    330: #ifdef KSYMS_DEBUG
1.29      jmmv      331:        printf("newstart %p sym %p symsz %d str %p strsz %d send %p\n",
                    332:            newstart, symstart, symsize, strstart, strsize, send);
1.8       ragge     333: #endif
1.1       ragge     334:
1.8       ragge     335:        /*
                    336:         * Pack symbol table by removing all file name references
                    337:         * and overwrite the elf header.
                    338:         */
                    339:        sym = tab->sd_symstart;
1.29      jmmv      340:        nsym = (Elf_Sym *)newstart;
1.8       ragge     341:        str = tab->sd_strstart;
                    342:        for (g = i = n = 0; i < tab->sd_symsize/sizeof(Elf_Sym); i++) {
                    343:                if (i == 0) {
                    344:                        nsym[n++] = sym[i];
                    345:                        continue;
                    346:                }
                    347:                /*
                    348:                 * Remove useless symbols.
                    349:                 * Should actually remove all typeless symbols.
                    350:                 */
1.5       ragge     351:                if (sym[i].st_name == 0)
1.8       ragge     352:                        continue; /* Skip nameless entries */
                    353:                if (ELF_ST_TYPE(sym[i].st_info) == STT_FILE)
                    354:                        continue; /* Skip filenames */
                    355:                if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE &&
                    356:                    sym[i].st_value == 0 &&
                    357:                    strcmp(str + sym[i].st_name, "*ABS*") == 0)
                    358:                        continue; /* XXX */
                    359:                if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE &&
                    360:                    strcmp(str + sym[i].st_name, "gcc2_compiled.") == 0)
                    361:                        continue; /* XXX */
                    362:
                    363: #ifndef DDB
                    364:                /* Only need global symbols */
                    365:                if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL)
1.5       ragge     366:                        continue;
1.8       ragge     367: #endif
                    368:
                    369:                /* Save symbol. Set it as an absolute offset */
                    370:                nsym[n] = sym[i];
                    371:                nsym[n].st_shndx = SHN_ABS;
                    372:                if (ELF_ST_BIND(nsym[n].st_info) == STB_GLOBAL)
                    373:                        g++;
1.6       tron      374: #if NKSYMS
1.29      jmmv      375:                {
                    376:                        int j;
                    377:                        j = strlen(nsym[n].st_name + tab->sd_strstart) + 1;
                    378:                        if (j > ksyms_maxlen)
                    379:                                ksyms_maxlen = j;
                    380:                }
1.6       tron      381: #endif
1.8       ragge     382:                n++;
                    383:
1.5       ragge     384:        }
1.8       ragge     385:        tab->sd_symstart = nsym;
                    386:        tab->sd_symsize = n * sizeof(Elf_Sym);
                    387:
                    388: #ifdef notyet
                    389:        /*
                    390:         * Remove left-over strings.
                    391:         */
                    392:        sym = tab->sd_symstart;
                    393:        str = (caddr_t)tab->sd_symstart + tab->sd_symsize;
                    394:        str[0] = 0;
                    395:        n = 1;
                    396:        for (i = 1; i < tab->sd_symsize/sizeof(Elf_Sym); i++) {
1.10      itojun    397:                strcpy(str + n, tab->sd_strstart + sym[i].st_name);
1.8       ragge     398:                sym[i].st_name = n;
                    399:                n += strlen(str+n) + 1;
                    400:        }
                    401:        tab->sd_strstart = str;
                    402:        tab->sd_strsize = n;
                    403:
                    404: #ifdef KSYMS_DEBUG
                    405:        printf("str %p strsz %d send %p\n", str, n, send);
                    406: #endif
                    407: #endif
1.1       ragge     408:
                    409:        CIRCLEQ_INSERT_HEAD(&symtab_queue, tab, sd_queue);
1.8       ragge     410:
                    411: #ifdef notyet
                    412: #ifdef USE_PTREE
                    413:        /* Try to use the freed space, if possible */
                    414:        if (send - str - n > g * sizeof(struct ptree))
                    415:                ptree_gen(str + n, tab);
                    416: #endif
                    417: #endif
1.1       ragge     418: }
                    419:
                    420: /*
1.29      jmmv      421:  * Add a symbol table named name.
                    422:  * This is intended for use when the kernel loader enters the table.
                    423:  */
                    424: static void
                    425: addsymtab_elf(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
                    426: {
                    427:        int i, j;
                    428:        caddr_t start = (caddr_t)ehdr;
                    429:        Elf_Shdr *shdr;
                    430:        caddr_t symstart = NULL, strstart = NULL;
                    431:        size_t symsize = 0, strsize = 0;
                    432:
                    433:        /* Find the symbol table and the corresponding string table. */
                    434:        shdr = (Elf_Shdr *)(start + ehdr->e_shoff);
                    435:        for (i = 1; i < ehdr->e_shnum; i++) {
                    436:                if (shdr[i].sh_type != SHT_SYMTAB)
                    437:                        continue;
                    438:                if (shdr[i].sh_offset == 0)
                    439:                        continue;
                    440:                symstart = start + shdr[i].sh_offset;
                    441:                symsize = shdr[i].sh_size;
                    442:                j = shdr[i].sh_link;
                    443:                if (shdr[j].sh_offset == 0)
                    444:                        continue; /* Can this happen? */
                    445:                strstart = start + shdr[j].sh_offset;
                    446:                strsize = shdr[j].sh_size;
                    447:                break;
                    448:        }
                    449:
                    450:        KASSERT(symstart != NULL && strstart != NULL);
                    451:
                    452:        addsymtab(name, symstart, symsize, strstart, strsize, tab, start);
                    453: }
                    454:
                    455: /*
1.1       ragge     456:  * Setup the kernel symbol table stuff.
                    457:  */
                    458: void
1.30      yamt      459: ksyms_init(int symsize, void *start, void *end)
1.1       ragge     460: {
1.3       ragge     461:        Elf_Ehdr *ehdr;
                    462:
                    463: #ifdef SYMTAB_SPACE
                    464:        if (symsize <= 0 &&
                    465:            strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) {
                    466:                symsize = db_symtabsize;
                    467:                start = db_symtab;
                    468:                end = db_symtab + db_symtabsize;
                    469:        }
                    470: #endif
                    471:        if (symsize <= 0) {
                    472:                printf("[ Kernel symbol table missing! ]\n");
                    473:                return;
                    474:        }
                    475:
                    476:        /* Sanity check */
                    477:        if (ALIGNED_POINTER(start, long) == 0) {
                    478:                printf("[ Kernel symbol table has bad start address %p ]\n",
                    479:                    start);
                    480:                return;
                    481:        }
                    482:
                    483:        ehdr = (Elf_Ehdr *)start;
1.1       ragge     484:
                    485:        /* check if this is a valid ELF header */
                    486:        /* No reason to verify arch type, the kernel is actually running! */
                    487:        if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
                    488:            ehdr->e_ident[EI_CLASS] != ELFCLASS ||
                    489:            ehdr->e_version > 1) {
1.3       ragge     490: #ifdef notyet /* DDB */
                    491:                if (ddb_init(symsize, start, end))
                    492:                        return; /* old-style symbol table */
                    493: #endif
                    494:                printf("[ Kernel symbol table invalid! ]\n");
1.1       ragge     495:                return; /* nothing to do */
                    496:        }
                    497:
1.8       ragge     498: #if NKSYMS
                    499:        /* Loaded header will be scratched in addsymtab */
                    500:        ksyms_hdr_init(start);
                    501: #endif
                    502:
1.29      jmmv      503:        addsymtab_elf("netbsd", ehdr, &kernel_symtab);
1.8       ragge     504:
1.1       ragge     505: #if NKSYMS
                    506:        ksyms_sizes_calc();
                    507: #endif
1.8       ragge     508:
1.1       ragge     509:        ksymsinited = 1;
1.8       ragge     510:
1.1       ragge     511: #ifdef DEBUG
                    512:        printf("Loaded initial symtab at %p, strtab at %p, # entries %ld\n",
                    513:            kernel_symtab.sd_symstart, kernel_symtab.sd_strstart,
1.2       ragge     514:            (long)kernel_symtab.sd_symsize/sizeof(Elf_Sym));
1.1       ragge     515: #endif
                    516: }
                    517:
                    518: /*
1.29      jmmv      519:  * Setup the kernel symbol table stuff.
                    520:  * Use this when the address of the symbol and string tables are known;
                    521:  * otherwise use ksyms_init with an ELF image.
1.31    ! jmmv      522:  * We need to pass a minimal ELF header which will later be completed by
        !           523:  * ksyms_hdr_init and handed off to userland through /dev/ksyms.  We use
        !           524:  * a caddr_t rather than a pointer to avoid exposing the Elf_Ehdr type.
1.29      jmmv      525:  */
                    526: void
1.31    ! jmmv      527: ksyms_init_explicit(caddr_t ehdr, caddr_t symstart, size_t symsize,
1.29      jmmv      528:     caddr_t strstart, size_t strsize)
                    529: {
                    530:
                    531:        KASSERT(symstart != NULL);
                    532:        KASSERT(strstart != NULL);
                    533:        KASSERT(symstart <= strstart);
                    534:
1.31    ! jmmv      535: #if NKSYMS
        !           536:        ksyms_hdr_init(ehdr);
        !           537: #endif
        !           538:
1.29      jmmv      539:        addsymtab("netbsd", symstart, symsize, strstart, strsize,
                    540:            &kernel_symtab, NULL);
                    541:
                    542: #if NKSYMS
                    543:        ksyms_sizes_calc();
                    544: #endif
                    545:
                    546:        ksymsinited = 1;
                    547: }
                    548:
                    549: /*
1.1       ragge     550:  * Get the value associated with a symbol.
1.23      perry     551:  * "mod" is the module name, or null if any module.
1.1       ragge     552:  * "sym" is the symbol name.
                    553:  * "val" is a pointer to the corresponding value, if call succeeded.
                    554:  * Returns 0 if success or ENOENT if no such entry.
                    555:  */
                    556: int
1.24      christos  557: ksyms_getval(const char *mod, const char *sym, unsigned long *val, int type)
1.1       ragge     558: {
                    559:        struct symtab *st;
                    560:        Elf_Sym *es;
                    561:
                    562:        if (ksymsinited == 0)
                    563:                return ENOENT;
                    564:
                    565: #ifdef KSYMS_DEBUG
                    566:        if (ksyms_debug & FOLLOW_CALLS)
                    567:                printf("ksyms_getval: mod %s sym %s valp %p\n", mod, sym, val);
                    568: #endif
                    569:
                    570:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    571:                if (mod && strcmp(st->sd_name, mod))
                    572:                        continue;
1.22      cube      573:                if ((es = findsym(sym, st)) == NULL)
1.1       ragge     574:                        continue;
                    575:
                    576:                /* Skip if bad binding */
                    577:                if (type == KSYMS_EXTERN &&
                    578:                    ELF_ST_BIND(es->st_info) != STB_GLOBAL)
                    579:                        continue;
                    580:
                    581:                if (val)
                    582:                        *val = es->st_value;
                    583:                return 0;
                    584:        }
                    585:        return ENOENT;
                    586: }
                    587:
                    588: /*
                    589:  * Get "mod" and "symbol" associated with an address.
                    590:  * Returns 0 if success or ENOENT if no such entry.
                    591:  */
                    592: int
1.24      christos  593: ksyms_getname(const char **mod, const char **sym, vaddr_t v, int f)
1.1       ragge     594: {
                    595:        struct symtab *st;
                    596:        Elf_Sym *les, *es = NULL;
                    597:        vaddr_t laddr = 0;
1.15      christos  598:        const char *lmod = NULL;
                    599:        char *stable = NULL;
1.1       ragge     600:        int type, i, sz;
                    601:
                    602:        if (ksymsinited == 0)
                    603:                return ENOENT;
                    604:
                    605:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    606:                sz = st->sd_symsize/sizeof(Elf_Sym);
                    607:                for (i = 0; i < sz; i++) {
                    608:                        les = st->sd_symstart + i;
                    609:                        type = ELF_ST_TYPE(les->st_info);
                    610:
                    611:                        if ((f & KSYMS_PROC) && (type != STT_FUNC))
                    612:                                continue;
                    613:
                    614:                        if (type == STT_NOTYPE)
                    615:                                continue;
                    616:
                    617:                        if (((f & KSYMS_ANY) == 0) &&
                    618:                            (type != STT_FUNC) && (type != STT_OBJECT))
                    619:                                continue;
                    620:
                    621:                        if ((les->st_value <= v) && (les->st_value > laddr)) {
                    622:                                laddr = les->st_value;
                    623:                                es = les;
                    624:                                lmod = st->sd_name;
1.17      cube      625:                                stable = st->sd_strstart - st->sd_usroffset;
1.1       ragge     626:                        }
                    627:                }
                    628:        }
                    629:        if (es == NULL)
                    630:                return ENOENT;
                    631:        if ((f & KSYMS_EXACT) && (v != es->st_value))
                    632:                return ENOENT;
                    633:        if (mod)
                    634:                *mod = lmod;
                    635:        if (sym)
                    636:                *sym = stable + es->st_name;
                    637:        return 0;
                    638: }
                    639:
                    640: #if NKSYMS
                    641: static int symsz, strsz;
                    642:
1.22      cube      643: /*
                    644:  * In case we exposing the symbol table to the userland using the pseudo-
                    645:  * device /dev/ksyms, it is easier to provide all the tables as one.
                    646:  * However, it means we have to change all the st_name fields for the
                    647:  * symbols so they match the ELF image that the userland will read
                    648:  * through the device.
                    649:  *
                    650:  * The actual (correct) value of st_name is preserved through a global
                    651:  * offset stored in the symbol table structure.
                    652:  */
                    653:
1.1       ragge     654: static void
                    655: ksyms_sizes_calc(void)
1.23      perry     656: {
                    657:         struct symtab *st;
1.1       ragge     658:        int i;
                    659:
                    660:         symsz = strsz = 0;
                    661:         CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    662:                if (st != &kernel_symtab) {
                    663:                        for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++)
                    664:                                st->sd_symstart[i].st_name =
                    665:                                    strsz + st->sd_symnmoff[i];
1.17      cube      666:                        st->sd_usroffset = strsz;
1.1       ragge     667:                }
                    668:                 symsz += st->sd_symsize;
                    669:                 strsz += st->sd_strsize;
1.17      cube      670:         }
1.1       ragge     671: }
1.25      thorpej   672: #endif /* NKSYMS */
1.1       ragge     673:
                    674: /*
1.20      matt      675:  * Temporary work structure for dynamic loaded symbol tables.
1.1       ragge     676:  * Will go away when in-kernel linker is in place.
                    677:  */
1.20      matt      678:
                    679: struct syminfo {
                    680:        size_t cursyms;
                    681:        size_t curnamep;
                    682:        size_t maxsyms;
                    683:        size_t maxnamep;
                    684:        Elf_Sym *syms;
                    685:        int *symnmoff;
                    686:        char *symnames;
                    687: };
1.23      perry     688:
1.1       ragge     689:
                    690: /*
                    691:  * Add a symbol to the temporary save area for symbols.
                    692:  * This routine will go away when the in-kernel linker is in place.
                    693:  */
                    694: static void
1.20      matt      695: addsym(struct syminfo *info, const Elf_Sym *sym, const char *name,
                    696:        const char *mod)
1.1       ragge     697: {
1.20      matt      698:        int len, mlen;
1.1       ragge     699:
                    700: #ifdef KSYMS_DEBUG
                    701:        if (ksyms_debug & FOLLOW_MORE_CALLS)
                    702:                printf("addsym: name %s val %lx\n", name, (long)sym->st_value);
                    703: #endif
1.20      matt      704:        len = strlen(name) + 1;
                    705:        if (mod)
                    706:                mlen = 1 + strlen(mod);
                    707:        else
                    708:                mlen = 0;
1.23      perry     709:        if (info->cursyms == info->maxsyms ||
1.20      matt      710:            (len + mlen + info->curnamep) > info->maxnamep) {
1.19      matt      711:                printf("addsym: too many symbols, skipping '%s'\n", name);
1.1       ragge     712:                return;
                    713:        }
1.20      matt      714:        strlcpy(&info->symnames[info->curnamep], name,
                    715:            info->maxnamep - info->curnamep);
                    716:        if (mlen) {
                    717:                info->symnames[info->curnamep + len - 1] = '.';
                    718:                strlcpy(&info->symnames[info->curnamep + len], mod,
                    719:                    info->maxnamep - (info->curnamep + len));
                    720:                len += mlen;
                    721:        }
                    722:        info->syms[info->cursyms] = *sym;
                    723:        info->syms[info->cursyms].st_name = info->curnamep;
                    724:        info->symnmoff[info->cursyms] = info->curnamep;
                    725:        info->curnamep += len;
1.7       ragge     726: #if NKSYMS
1.5       ragge     727:        if (len > ksyms_maxlen)
                    728:                ksyms_maxlen = len;
1.6       tron      729: #endif
1.20      matt      730:        info->cursyms++;
1.1       ragge     731: }
                    732: /*
                    733:  * Adds a symbol table.
                    734:  * "name" is the module name, "start" and "size" is where the symbol table
                    735:  * is located, and "type" is in which binary format the symbol table is.
                    736:  * New memory for keeping the symbol table is allocated in this function.
                    737:  * Returns 0 if success and EEXIST if the module name is in use.
                    738:  */
1.21      matt      739: static int
                    740: specialsym(const char *symname)
                    741: {
                    742:        return  !strcmp(symname, "_bss_start") ||
                    743:                !strcmp(symname, "__bss_start") ||
                    744:                !strcmp(symname, "_bss_end__") ||
                    745:                !strcmp(symname, "__bss_end__") ||
                    746:                !strcmp(symname, "_edata") ||
                    747:                !strcmp(symname, "_end") ||
                    748:                !strcmp(symname, "__end") ||
                    749:                !strcmp(symname, "__end__") ||
                    750:                !strncmp(symname, "__start_link_set_", 17) ||
                    751:                !strncmp(symname, "__stop_link_set_", 16);
                    752: }
                    753:
1.1       ragge     754: int
1.9       jdolecek  755: ksyms_addsymtab(const char *mod, void *symstart, vsize_t symsize,
1.30      yamt      756:     char *strstart, vsize_t strsize)
1.1       ragge     757: {
                    758:        Elf_Sym *sym = symstart;
                    759:        struct symtab *st;
1.14      ragge     760:        unsigned long rval;
1.1       ragge     761:        int i;
1.20      matt      762:        char *name;
                    763:        struct syminfo info;
1.1       ragge     764:
                    765: #ifdef KSYMS_DEBUG
                    766:        if (ksyms_debug & FOLLOW_CALLS)
                    767:                printf("ksyms_addsymtab: mod %s symsize %lx strsize %lx\n",
                    768:                    mod, symsize, strsize);
                    769: #endif
                    770:
                    771: #if NKSYMS
                    772:        /*
                    773:         * Do not try to add a symbol table while someone is reading
                    774:         * from /dev/ksyms.
                    775:         */
                    776:        while (ksyms_isopen != 0)
                    777:                tsleep(&ksyms_isopen, PWAIT, "ksyms", 0);
                    778: #endif
                    779:
                    780:        /* Check if this symtab already loaded */
                    781:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    782:                if (strcmp(mod, st->sd_name) == 0)
                    783:                        return EEXIST;
                    784:        }
                    785:
                    786:        /*
                    787:         * XXX - Only add a symbol if it do not exist already.
                    788:         * This is because of a flaw in the current LKM implementation,
1.20      matt      789:         * these loops will be removed once the in-kernel linker is in place.
1.1       ragge     790:         */
1.20      matt      791:        memset(&info, 0, sizeof(info));
1.1       ragge     792:        for (i = 0; i < symsize/sizeof(Elf_Sym); i++) {
1.20      matt      793:                char * const symname = strstart + sym[i].st_name;
1.1       ragge     794:                if (sym[i].st_name == 0)
                    795:                        continue; /* Just ignore */
                    796:
                    797:                /* check validity of the symbol */
                    798:                /* XXX - save local symbols if DDB */
                    799:                if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL)
                    800:                        continue;
1.23      perry     801:
1.1       ragge     802:                /* Check if the symbol exists */
1.22      cube      803:                if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) {
1.1       ragge     804:                        /* Check (and complain) about differing values */
                    805:                        if (sym[i].st_value != rval) {
1.21      matt      806:                                if (specialsym(symname)) {
1.20      matt      807:                                        info.maxsyms++;
                    808:                                        info.maxnamep += strlen(symname) + 1 +
                    809:                                            strlen(mod) + 1;
                    810:                                } else {
                    811:                                        printf("%s: symbol '%s' redeclared with"
                    812:                                            " different value (%lx != %lx)\n",
                    813:                                            mod, symname,
                    814:                                            rval, (long)sym[i].st_value);
                    815:                                }
                    816:                        }
                    817:                } else {
                    818:                        /*
                    819:                         * Count this symbol
                    820:                         */
                    821:                        info.maxsyms++;
                    822:                        info.maxnamep += strlen(symname) + 1;
                    823:                }
                    824:        }
                    825:
                    826:        /*
                    827:         * Now that we know the sizes, malloc the structures.
                    828:         */
                    829:        info.syms = malloc(sizeof(Elf_Sym)*info.maxsyms, M_DEVBUF, M_WAITOK);
                    830:        info.symnames = malloc(info.maxnamep, M_DEVBUF, M_WAITOK);
                    831:        info.symnmoff = malloc(sizeof(int)*info.maxsyms, M_DEVBUF, M_WAITOK);
                    832:
                    833:        /*
                    834:         * Now that we have the symbols, actually fill in the structures.
                    835:         */
                    836:        for (i = 0; i < symsize/sizeof(Elf_Sym); i++) {
                    837:                char * const symname = strstart + sym[i].st_name;
                    838:                if (sym[i].st_name == 0)
                    839:                        continue; /* Just ignore */
                    840:
                    841:                /* check validity of the symbol */
                    842:                /* XXX - save local symbols if DDB */
                    843:                if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL)
                    844:                        continue;
1.23      perry     845:
1.20      matt      846:                /* Check if the symbol exists */
1.22      cube      847:                if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) {
1.21      matt      848:                        if ((sym[i].st_value != rval) && specialsym(symname)) {
1.20      matt      849:                                addsym(&info, &sym[i], symname, mod);
1.1       ragge     850:                        }
                    851:                } else
                    852:                        /* Ok, save this symbol */
1.20      matt      853:                        addsym(&info, &sym[i], symname, NULL);
1.1       ragge     854:        }
1.5       ragge     855:
1.1       ragge     856:        st = malloc(sizeof(struct symtab), M_DEVBUF, M_WAITOK);
1.10      itojun    857:        i = strlen(mod) + 1;
                    858:        name = malloc(i, M_DEVBUF, M_WAITOK);
                    859:        strlcpy(name, mod, i);
1.9       jdolecek  860:        st->sd_name = name;
1.20      matt      861:        st->sd_symnmoff = info.symnmoff;
                    862:        st->sd_symstart = info.syms;
                    863:        st->sd_symsize = sizeof(Elf_Sym)*info.maxsyms;
                    864:        st->sd_strstart = info.symnames;
                    865:        st->sd_strsize = info.maxnamep;
1.1       ragge     866:
                    867:        /* Make them absolute references */
                    868:        sym = st->sd_symstart;
                    869:        for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++)
                    870:                sym[i].st_shndx = SHN_ABS;
                    871:
                    872:        CIRCLEQ_INSERT_TAIL(&symtab_queue, st, sd_queue);
                    873: #if NKSYMS
                    874:        ksyms_sizes_calc();
                    875: #endif
                    876:        return 0;
                    877: }
                    878:
                    879: /*
                    880:  * Remove a symbol table specified by name.
                    881:  * Returns 0 if success, EBUSY if device open and ENOENT if no such name.
                    882:  */
                    883: int
1.9       jdolecek  884: ksyms_delsymtab(const char *mod)
1.1       ragge     885: {
                    886:        struct symtab *st;
                    887:        int found = 0;
                    888:
                    889: #if NKSYMS
                    890:        /*
                    891:         * Do not try to delete a symbol table while someone is reading
                    892:         * from /dev/ksyms.
                    893:         */
                    894:        while (ksyms_isopen != 0)
                    895:                tsleep(&ksyms_isopen, PWAIT, "ksyms", 0);
                    896: #endif
                    897:
                    898:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    899:                if (strcmp(mod, st->sd_name) == 0) {
                    900:                        found = 1;
                    901:                        break;
                    902:                }
                    903:        }
                    904:        if (found == 0)
                    905:                return ENOENT;
                    906:        CIRCLEQ_REMOVE(&symtab_queue, st, sd_queue);
                    907:        free(st->sd_symstart, M_DEVBUF);
                    908:        free(st->sd_strstart, M_DEVBUF);
                    909:        free(st->sd_symnmoff, M_DEVBUF);
1.24      christos  910:        /* XXXUNCONST LINTED - const castaway */
                    911:        free(__UNCONST(st->sd_name), M_DEVBUF);
1.1       ragge     912:        free(st, M_DEVBUF);
                    913: #if NKSYMS
                    914:        ksyms_sizes_calc();
                    915: #endif
                    916:        return 0;
                    917: }
                    918:
1.17      cube      919: int
                    920: ksyms_rensymtab(const char *old, const char *new)
                    921: {
                    922:        struct symtab *st, *oldst = NULL;
                    923:        char *newstr;
                    924:
                    925:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    926:                if (strcmp(old, st->sd_name) == 0)
                    927:                        oldst = st;
                    928:                if (strcmp(new, st->sd_name) == 0)
                    929:                        return (EEXIST);
                    930:        }
                    931:        if (oldst == NULL)
                    932:                return (ENOENT);
                    933:
                    934:        newstr = malloc(strlen(new)+1, M_DEVBUF, M_WAITOK);
                    935:        if (!newstr)
                    936:                return (ENOMEM);
                    937:        strcpy(newstr, new);
1.24      christos  938:        /*XXXUNCONST*/
                    939:        free(__UNCONST(oldst->sd_name), M_DEVBUF);
1.17      cube      940:        oldst->sd_name = newstr;
                    941:
                    942:        return (0);
                    943: }
                    944:
1.1       ragge     945: #ifdef DDB
                    946: /*
                    947:  * Keep sifting stuff here, to avoid export of ksyms internals.
                    948:  */
                    949: int
                    950: ksyms_sift(char *mod, char *sym, int mode)
                    951: {
                    952:        struct symtab *st;
                    953:        char *sb;
                    954:        int i, sz;
                    955:
                    956:        if (ksymsinited == 0)
                    957:                return ENOENT;
                    958:
                    959:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                    960:                if (mod && strcmp(mod, st->sd_name))
                    961:                        continue;
                    962:                sb = st->sd_strstart;
                    963:
                    964:                sz = st->sd_symsize/sizeof(Elf_Sym);
                    965:                for (i = 0; i < sz; i++) {
                    966:                        Elf_Sym *les = st->sd_symstart + i;
                    967:                        char c;
                    968:
1.17      cube      969:                        if (strstr(sb + les->st_name - st->sd_usroffset, sym)
                    970:                            == NULL)
1.1       ragge     971:                                continue;
                    972:
                    973:                        if (mode == 'F') {
                    974:                                switch (ELF_ST_TYPE(les->st_info)) {
                    975:                                case STT_OBJECT:
                    976:                                        c = '+';
                    977:                                        break;
                    978:                                case STT_FUNC:
                    979:                                        c = '*';
                    980:                                        break;
                    981:                                case STT_SECTION:
                    982:                                        c = '&';
                    983:                                        break;
                    984:                                case STT_FILE:
                    985:                                        c = '/';
                    986:                                        break;
                    987:                                default:
                    988:                                        c = ' ';
                    989:                                        break;
                    990:                                }
1.17      cube      991:                                db_printf("%s%c ", sb + les->st_name -
                    992:                                    st->sd_usroffset, c);
1.1       ragge     993:                        } else
1.17      cube      994:                                db_printf("%s ", sb + les->st_name -
                    995:                                    st->sd_usroffset);
1.1       ragge     996:                }
                    997:        }
                    998:        return ENOENT;
                    999: }
1.25      thorpej  1000: #endif /* DDB */
1.1       ragge    1001:
                   1002: #if NKSYMS
                   1003: /*
                   1004:  * Static allocated ELF header.
                   1005:  * Basic info is filled in at attach, sizes at open.
                   1006:  */
                   1007: #define        SYMTAB          1
                   1008: #define        STRTAB          2
                   1009: #define        SHSTRTAB        3
                   1010: #define NSECHDR                4
                   1011:
                   1012: #define        NPRGHDR         2
                   1013: #define        SHSTRSIZ        28
                   1014:
                   1015: static struct ksyms_hdr {
                   1016:        Elf_Ehdr        kh_ehdr;
                   1017:        Elf_Phdr        kh_phdr[NPRGHDR];
                   1018:        Elf_Shdr        kh_shdr[NSECHDR];
                   1019:        char            kh_strtab[SHSTRSIZ];
                   1020: } ksyms_hdr;
                   1021:
                   1022:
1.25      thorpej  1023: static void
1.1       ragge    1024: ksyms_hdr_init(caddr_t hdraddr)
                   1025: {
                   1026:
                   1027:        /* Copy the loaded elf exec header */
                   1028:        memcpy(&ksyms_hdr.kh_ehdr, hdraddr, sizeof(Elf_Ehdr));
                   1029:
                   1030:        /* Set correct program/section header sizes, offsets and numbers */
                   1031:        ksyms_hdr.kh_ehdr.e_phoff = offsetof(struct ksyms_hdr, kh_phdr[0]);
                   1032:        ksyms_hdr.kh_ehdr.e_phentsize = sizeof(Elf_Phdr);
                   1033:        ksyms_hdr.kh_ehdr.e_phnum = NPRGHDR;
                   1034:        ksyms_hdr.kh_ehdr.e_shoff = offsetof(struct ksyms_hdr, kh_shdr[0]);
                   1035:        ksyms_hdr.kh_ehdr.e_shentsize = sizeof(Elf_Shdr);
                   1036:        ksyms_hdr.kh_ehdr.e_shnum = NSECHDR;
                   1037:        ksyms_hdr.kh_ehdr.e_shstrndx = NSECHDR - 1; /* Last section */
                   1038:
                   1039:        /*
                   1040:         * Keep program headers zeroed (unused).
                   1041:         * The section headers are hand-crafted.
                   1042:         * First section is section zero.
                   1043:         */
                   1044:
                   1045:        /* Second section header; ".symtab" */
                   1046:        ksyms_hdr.kh_shdr[SYMTAB].sh_name = 1; /* Section 3 offset */
                   1047:        ksyms_hdr.kh_shdr[SYMTAB].sh_type = SHT_SYMTAB;
                   1048:        ksyms_hdr.kh_shdr[SYMTAB].sh_offset = sizeof(struct ksyms_hdr);
                   1049: /*     ksyms_hdr.kh_shdr[SYMTAB].sh_size = filled in at open */
                   1050:        ksyms_hdr.kh_shdr[SYMTAB].sh_link = 2; /* Corresponding strtab */
                   1051:        ksyms_hdr.kh_shdr[SYMTAB].sh_info = 0; /* XXX */
                   1052:        ksyms_hdr.kh_shdr[SYMTAB].sh_addralign = sizeof(long);
                   1053:        ksyms_hdr.kh_shdr[SYMTAB].sh_entsize = sizeof(Elf_Sym);
                   1054:
                   1055:        /* Third section header; ".strtab" */
                   1056:        ksyms_hdr.kh_shdr[STRTAB].sh_name = 9; /* Section 3 offset */
                   1057:        ksyms_hdr.kh_shdr[STRTAB].sh_type = SHT_STRTAB;
                   1058: /*     ksyms_hdr.kh_shdr[STRTAB].sh_offset = filled in at open */
                   1059: /*     ksyms_hdr.kh_shdr[STRTAB].sh_size = filled in at open */
                   1060: /*     ksyms_hdr.kh_shdr[STRTAB].sh_link = kept zero */
                   1061:        ksyms_hdr.kh_shdr[STRTAB].sh_info = 0;
                   1062:        ksyms_hdr.kh_shdr[STRTAB].sh_addralign = sizeof(char);
                   1063:        ksyms_hdr.kh_shdr[STRTAB].sh_entsize = 0;
                   1064:
                   1065:        /* Fourth section, ".shstrtab" */
                   1066:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_name = 17; /* This section name offset */
                   1067:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_type = SHT_STRTAB;
                   1068:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_offset =
                   1069:            offsetof(struct ksyms_hdr, kh_strtab);
                   1070:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_size = SHSTRSIZ;
                   1071:        ksyms_hdr.kh_shdr[SHSTRTAB].sh_addralign = sizeof(char);
                   1072:
                   1073:        /* Set section names */
1.10      itojun   1074:        strlcpy(&ksyms_hdr.kh_strtab[1], ".symtab",
                   1075:            sizeof(ksyms_hdr.kh_strtab) - 1);
                   1076:        strlcpy(&ksyms_hdr.kh_strtab[9], ".strtab",
                   1077:            sizeof(ksyms_hdr.kh_strtab) - 9);
                   1078:        strlcpy(&ksyms_hdr.kh_strtab[17], ".shstrtab",
                   1079:            sizeof(ksyms_hdr.kh_strtab) - 17);
1.1       ragge    1080: };
                   1081:
1.25      thorpej  1082: static int
1.30      yamt     1083: ksymsopen(dev_t dev, int oflags, int devtype, struct lwp *l)
1.1       ragge    1084: {
                   1085:
                   1086:        if (minor(dev))
                   1087:                return ENXIO;
1.18      cube     1088:        if (ksymsinited == 0)
                   1089:                return ENXIO;
1.1       ragge    1090:
                   1091:        ksyms_hdr.kh_shdr[SYMTAB].sh_size = symsz;
                   1092:        ksyms_hdr.kh_shdr[STRTAB].sh_offset = symsz +
                   1093:            ksyms_hdr.kh_shdr[SYMTAB].sh_offset;
                   1094:        ksyms_hdr.kh_shdr[STRTAB].sh_size = strsz;
                   1095:        ksyms_isopen = 1;
                   1096:
                   1097: #ifdef KSYMS_DEBUG
                   1098:        if (ksyms_debug & FOLLOW_DEVKSYMS)
                   1099:                printf("ksymsopen: symsz 0x%x strsz 0x%x\n", symsz, strsz);
                   1100: #endif
                   1101:
                   1102:        return 0;
                   1103: }
                   1104:
1.25      thorpej  1105: static int
1.30      yamt     1106: ksymsclose(dev_t dev, int oflags, int devtype, struct lwp *l)
1.1       ragge    1107: {
                   1108:
                   1109: #ifdef KSYMS_DEBUG
                   1110:        if (ksyms_debug & FOLLOW_DEVKSYMS)
                   1111:                printf("ksymsclose\n");
                   1112: #endif
                   1113:
                   1114:        ksyms_isopen = 0;
                   1115:        wakeup(&ksyms_isopen);
                   1116:        return 0;
                   1117: }
                   1118:
                   1119: #define        HDRSIZ  sizeof(struct ksyms_hdr)
                   1120:
1.25      thorpej  1121: static int
1.30      yamt     1122: ksymsread(dev_t dev, struct uio *uio, int ioflag)
1.1       ragge    1123: {
                   1124:        struct symtab *st;
                   1125:        size_t filepos, inpos, off;
                   1126:
                   1127: #ifdef KSYMS_DEBUG
                   1128:        if (ksyms_debug & FOLLOW_DEVKSYMS)
1.26      riz      1129:                printf("ksymsread: offset 0x%llx resid 0x%zx\n",
1.1       ragge    1130:                    (long long)uio->uio_offset, uio->uio_resid);
                   1131: #endif
                   1132:
                   1133:        off = uio->uio_offset;
                   1134:        if (off >= (strsz + symsz + HDRSIZ))
                   1135:                return 0; /* End of symtab */
                   1136:        /*
                   1137:         * First: Copy out the ELF header.
                   1138:         */
                   1139:        if (off < HDRSIZ)
                   1140:                uiomove((char *)&ksyms_hdr + off, HDRSIZ - off, uio);
                   1141:
                   1142:        /*
                   1143:         * Copy out the symbol table.
                   1144:         */
                   1145:        filepos = HDRSIZ;
                   1146:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                   1147:                if (uio->uio_resid == 0)
                   1148:                        return 0;
                   1149:                if (uio->uio_offset <= st->sd_symsize + filepos) {
                   1150:                        inpos = uio->uio_offset - filepos;
                   1151:                        uiomove((char *)st->sd_symstart + inpos,
                   1152:                           st->sd_symsize - inpos, uio);
                   1153:                }
                   1154:                filepos += st->sd_symsize;
                   1155:        }
                   1156:
                   1157:        if (filepos != HDRSIZ + symsz)
                   1158:                panic("ksymsread: unsunc");
                   1159:
                   1160:        /*
                   1161:         * Copy out the string table
                   1162:         */
                   1163:        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                   1164:                if (uio->uio_resid == 0)
                   1165:                        return 0;
                   1166:                if (uio->uio_offset <= st->sd_strsize + filepos) {
                   1167:                        inpos = uio->uio_offset - filepos;
                   1168:                        uiomove((char *)st->sd_strstart + inpos,
                   1169:                           st->sd_strsize - inpos, uio);
                   1170:                }
                   1171:                filepos += st->sd_strsize;
                   1172:        }
                   1173:        return 0;
                   1174: }
                   1175:
1.25      thorpej  1176: static int
1.30      yamt     1177: ksymswrite(dev_t dev, struct uio *uio, int ioflag)
1.1       ragge    1178: {
1.30      yamt     1179:
1.1       ragge    1180:        return EROFS;
                   1181: }
                   1182:
1.25      thorpej  1183: static int
1.30      yamt     1184: ksymsioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct lwp *l)
1.1       ragge    1185: {
                   1186:        struct ksyms_gsymbol *kg = (struct ksyms_gsymbol *)data;
                   1187:        struct symtab *st;
1.15      christos 1188:        Elf_Sym *sym = NULL;
1.1       ragge    1189:        unsigned long val;
                   1190:        int error = 0;
1.15      christos 1191:        char *str = NULL;
1.5       ragge    1192:
                   1193:        if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL)
                   1194:                str = malloc(ksyms_maxlen, M_DEVBUF, M_WAITOK);
1.1       ragge    1195:
                   1196:        switch (cmd) {
                   1197:        case KIOCGVALUE:
                   1198:                /*
                   1199:                 * Use the in-kernel symbol lookup code for fast
                   1200:                 * retreival of a value.
                   1201:                 */
1.5       ragge    1202:                if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL)))
1.1       ragge    1203:                        break;
1.22      cube     1204:                if ((error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN)))
1.1       ragge    1205:                        break;
                   1206:                error = copyout(&val, kg->kg_value, sizeof(long));
                   1207:                break;
                   1208:
                   1209:        case KIOCGSYMBOL:
                   1210:                /*
                   1211:                 * Use the in-kernel symbol lookup code for fast
                   1212:                 * retreival of a symbol.
                   1213:                 */
1.5       ragge    1214:                if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL)))
1.1       ragge    1215:                        break;
                   1216:                CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
1.22      cube     1217:                        if ((sym = findsym(str, st)) == NULL) /* from userland */
1.1       ragge    1218:                                continue;
                   1219:
                   1220:                        /* Skip if bad binding */
                   1221:                        if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) {
                   1222:                                sym = NULL;
                   1223:                                continue;
                   1224:                        }
                   1225:                        break;
                   1226:                }
1.22      cube     1227:                /*
                   1228:                 * XXX which value of sym->st_name should be returned?  The real
                   1229:                 * one, or the one that matches what reading /dev/ksyms get?
                   1230:                 *
                   1231:                 * Currently, we're returning the /dev/ksyms one.
                   1232:                 */
1.1       ragge    1233:                if (sym != NULL)
                   1234:                        error = copyout(sym, kg->kg_sym, sizeof(Elf_Sym));
                   1235:                else
                   1236:                        error = ENOENT;
                   1237:                break;
                   1238:
                   1239:        case KIOCGSIZE:
                   1240:                /*
                   1241:                 * Get total size of symbol table.
                   1242:                 */
                   1243:                *(int *)data = strsz + symsz + HDRSIZ;
                   1244:                break;
                   1245:
                   1246:        default:
                   1247:                error = ENOTTY;
                   1248:                break;
                   1249:        }
1.5       ragge    1250:
                   1251:        if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL)
                   1252:                free(str, M_DEVBUF);
                   1253:
                   1254:        return error;
1.1       ragge    1255: }
1.25      thorpej  1256:
                   1257: const struct cdevsw ksyms_cdevsw = {
                   1258:        ksymsopen, ksymsclose, ksymsread, ksymswrite, ksymsioctl,
                   1259:            nullstop, notty, nopoll, nommap, nullkqfilter, DV_DULL
                   1260: };
                   1261: #endif /* NKSYMS */

CVSweb <webmaster@jp.NetBSD.org>