[BACK]Return to db_elf.c CVS log [TXT][DIR] Up to [local] / sys / ddb

Annotation of sys/ddb/db_elf.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: db_elf.c,v 1.7 2006/03/13 06:23:20 jsg Exp $  */
                      2: /*     $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $        */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1997 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                     10:  * NASA Ames Research Center.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the NetBSD
                     23:  *     Foundation, Inc. and its contributors.
                     24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     25:  *    contributors may be used to endorse or promote products derived
                     26:  *    from this software without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     38:  * POSSIBILITY OF SUCH DAMAGE.
                     39:  */
                     40:
                     41: #include <sys/types.h>
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/exec.h>
                     46:
                     47: #include <machine/db_machdep.h>
                     48:
                     49: #include <ddb/db_sym.h>
                     50: #include <ddb/db_output.h>
                     51: #include <ddb/db_extern.h>
                     52:
                     53: #ifdef DB_ELF_SYMBOLS
                     54:
                     55: #ifndef DB_ELFSIZE
                     56: #error Must define DB_ELFSIZE!
                     57: #endif
                     58:
                     59: #define        ELFSIZE         DB_ELFSIZE
                     60:
                     61: #include <sys/exec_elf.h>
                     62:
                     63: static char *db_elf_find_strtab(db_symtab_t *);
                     64:
                     65: #define        STAB_TO_SYMSTART(stab)  ((Elf_Sym *)((stab)->start))
                     66: #define        STAB_TO_SYMEND(stab)    ((Elf_Sym *)((stab)->end))
                     67: #define        STAB_TO_EHDR(stab)      ((Elf_Ehdr *)((stab)->private))
                     68: #define        STAB_TO_SHDR(stab, e)   ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
                     69:
                     70: boolean_t      db_elf_sym_init(int, void *, void *, const char *);
                     71: db_sym_t       db_elf_lookup(db_symtab_t *, char *);
                     72: db_sym_t       db_elf_search_symbol(db_symtab_t *, db_addr_t,
                     73:                    db_strategy_t, db_expr_t *);
                     74: void           db_elf_symbol_values(db_symtab_t *, db_sym_t,
                     75:                    char **, db_expr_t *);
                     76: boolean_t      db_elf_line_at_pc(db_symtab_t *, db_sym_t,
                     77:                    char **, int *, db_expr_t);
                     78: boolean_t      db_elf_sym_numargs(db_symtab_t *, db_sym_t, int *,
                     79:                    char **);
                     80: void           db_elf_forall(db_symtab_t *,
                     81:                    db_forall_func_t db_forall_func, void *);
                     82:
                     83: db_symformat_t db_symformat_elf = {
                     84:        "ELF",
                     85:        db_elf_sym_init,
                     86:        db_elf_lookup,
                     87:        db_elf_search_symbol,
                     88:        db_elf_symbol_values,
                     89:        db_elf_line_at_pc,
                     90:        db_elf_sym_numargs,
                     91:        db_elf_forall
                     92: };
                     93:
                     94: /*
                     95:  * Find the symbol table and strings; tell ddb about them.
                     96:  *
                     97:  * symsize:    size of symbol table
                     98:  * symtab:     pointer to start of symbol table
                     99:  * esymtab:    pointer to end of string table, for checking - rounded up to
                    100:  *                 integer boundry
                    101:  */
                    102: boolean_t
                    103: db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name)
                    104: {
                    105:        Elf_Ehdr *elf;
                    106:        Elf_Shdr *shp;
                    107:        Elf_Sym *symp, *symtab_start, *symtab_end;
                    108:        char *shstrtab, *strtab_start, *strtab_end;
                    109:        int i;
                    110:        char *errstr = "";
                    111:
                    112:        if (ALIGNED_POINTER(symtab, long) == 0) {
                    113:                printf("[ %s symbol table has bad start address %p ]\n",
                    114:                    name, symtab);
                    115:                return (FALSE);
                    116:        }
                    117:
                    118:        symtab_start = symtab_end = NULL;
                    119:        strtab_start = strtab_end = NULL;
                    120:
                    121:        /*
                    122:         * The format of the symbols loaded by the boot program is:
                    123:         *
                    124:         *      Elf exec header
                    125:         *      first section header
                    126:         *      . . .
                    127:         *      . . .
                    128:         *      last section header
                    129:         *      first symbol or string table section
                    130:         *      . . .
                    131:         *      . . .
                    132:         *      last symbol or string table section
                    133:         */
                    134:
                    135:        /*
                    136:         * Validate the Elf header.
                    137:         */
                    138:        elf = (Elf_Ehdr *)symtab;
                    139:        if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
                    140:            elf->e_ident[EI_CLASS] != ELFCLASS) {
                    141:                errstr = "bad magic";
                    142:                goto badheader;
                    143:        }
                    144:
                    145:        if (elf->e_machine != ELF_TARG_MACH) {
                    146:                errstr = "bad e_machine";
                    147:                goto badheader;
                    148:        }
                    149:
                    150:        /*
                    151:         * Find the section header string table (.shstrtab), and look up
                    152:         * the symbol table (.symtab) and string table (.strtab) via their
                    153:         * names in shstrtab, rather than by table type.
                    154:         * This works in the presence of multiple string tables, such as
                    155:         * stabs data found when booting bsd.gdb.
                    156:         */
                    157:        shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
                    158:        shstrtab = (char *)symtab + shp[elf->e_shstrndx].sh_offset;
                    159:        for (i = 0; i < elf->e_shnum; i++) {
                    160:                if (shp[i].sh_type == SHT_SYMTAB) {
                    161:                        int j;
                    162:
                    163:                        if (shp[i].sh_offset == 0)
                    164:                                continue;
                    165:                        symtab_start = (Elf_Sym *)((char *)symtab +
                    166:                            shp[i].sh_offset);
                    167:                        symtab_end = (Elf_Sym *)((char *)symtab +
                    168:                            shp[i].sh_offset + shp[i].sh_size);
                    169:                        j = shp[i].sh_link;
                    170:                        if (shp[j].sh_offset == 0)
                    171:                                continue;
                    172:                        strtab_start = (char *)symtab + shp[j].sh_offset;
                    173:                        strtab_end = (char *)symtab + shp[j].sh_offset +
                    174:                            shp[j].sh_size;
                    175:                        break;
                    176:                }
                    177:
                    178:                /*
                    179:                 * This is the old way of doing things.
                    180:                 * XXX - verify that it's not needed.
                    181:                 */
                    182:                if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) {
                    183:                        strtab_start = (char *)symtab + shp[i].sh_offset;
                    184:                        strtab_end = (char *)symtab + shp[i].sh_offset +
                    185:                            shp[i].sh_size;
                    186:                } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) {
                    187:                        symtab_start = (Elf_Sym *)((char *)symtab +
                    188:                            shp[i].sh_offset);
                    189:                        symtab_end = (Elf_Sym *)((char *)symtab +
                    190:                            shp[i].sh_offset + shp[i].sh_size);
                    191:                }
                    192:        }
                    193:
                    194:        /*
                    195:         * Now, sanity check the symbols against the string table.
                    196:         */
                    197:        if (symtab_start == NULL || strtab_start == NULL ||
                    198:            ALIGNED_POINTER(symtab_start, long) == 0 ||
                    199:            ALIGNED_POINTER(strtab_start, long) == 0) {
                    200:                errstr = "symtab unaligned";
                    201:                goto badheader;
                    202:        }
                    203:        for (symp = symtab_start; symp < symtab_end; symp++)
                    204:                if (symp->st_name + strtab_start > strtab_end) {
                    205:                        errstr = "symtab corrupted";
                    206:                        goto badheader;
                    207:                }
                    208:
                    209:        /*
                    210:         * Link the symbol table into the debugger.
                    211:         */
                    212:        if (db_add_symbol_table((char *)symtab_start,
                    213:            (char *)symtab_end, name, (char *)symtab) != -1) {
                    214:                printf("[ using %lu bytes of %s ELF symbol table ]\n",
                    215:                    (u_long)roundup(((char *)esymtab - (char *)symtab),
                    216:                                    sizeof(u_long)), name);
                    217:                return (TRUE);
                    218:        }
                    219:
                    220:        return (FALSE);
                    221:
                    222:  badheader:
                    223:        printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr);
                    224:        return (FALSE);
                    225: }
                    226:
                    227: /*
                    228:  * Internal helper function - return a pointer to the string table
                    229:  * for the current symbol table.
                    230:  */
                    231: static char *
                    232: db_elf_find_strtab(db_symtab_t *stab)
                    233: {
                    234:        Elf_Ehdr *elf = STAB_TO_EHDR(stab);
                    235:        Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
                    236:        char *shstrtab;
                    237:        int i;
                    238:
                    239:        shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset;
                    240:        for (i = 0; i < elf->e_shnum; i++) {
                    241:                if (shp[i].sh_type == SHT_SYMTAB)
                    242:                        return ((char *)elf + shp[shp[i].sh_link].sh_offset);
                    243:                if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0)
                    244:                        return ((char *)elf + shp[i].sh_offset);
                    245:        }
                    246:
                    247:        return (NULL);
                    248: }
                    249:
                    250: /*
                    251:  * Lookup the symbol with the given name.
                    252:  */
                    253: db_sym_t
                    254: db_elf_lookup(db_symtab_t *stab, char *symstr)
                    255: {
                    256:        Elf_Sym *symp, *symtab_start, *symtab_end;
                    257:        char *strtab;
                    258:
                    259:        symtab_start = STAB_TO_SYMSTART(stab);
                    260:        symtab_end = STAB_TO_SYMEND(stab);
                    261:
                    262:        strtab = db_elf_find_strtab(stab);
                    263:        if (strtab == NULL)
                    264:                return ((db_sym_t)0);
                    265:
                    266:        for (symp = symtab_start; symp < symtab_end; symp++) {
                    267:                if (symp->st_name != 0 &&
                    268:                    db_eqname(strtab + symp->st_name, symstr, 0))
                    269:                        return ((db_sym_t)symp);
                    270:        }
                    271:
                    272:        return ((db_sym_t)0);
                    273: }
                    274:
                    275: /*
                    276:  * Search for the symbol with the given address (matching within the
                    277:  * provided threshold).
                    278:  */
                    279: db_sym_t
                    280: db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
                    281:     db_expr_t *diffp)
                    282: {
                    283:        Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
                    284:        db_expr_t diff = *diffp;
                    285:
                    286:        symtab_start = STAB_TO_SYMSTART(symtab);
                    287:        symtab_end = STAB_TO_SYMEND(symtab);
                    288:
                    289:        rsymp = NULL;
                    290:
                    291:        for (symp = symtab_start; symp < symtab_end; symp++) {
                    292:                if (symp->st_name == 0)
                    293:                        continue;
                    294: #if 0
                    295:                /* This prevents me from seeing anythin in locore.s -- eeh */
                    296:                if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
                    297:                    ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
                    298:                        continue;
                    299: #endif
                    300:
                    301:                if (off >= symp->st_value) {
                    302:                        if ((off - symp->st_value) < diff) {
                    303:                                diff = off - symp->st_value;
                    304:                                rsymp = symp;
                    305:                                if (diff == 0) {
                    306:                                        if (strategy == DB_STGY_PROC &&
                    307:                                            ELFDEFNNAME(ST_TYPE)(symp->st_info)
                    308:                                              == STT_FUNC &&
                    309:                                            ELFDEFNNAME(ST_BIND)(symp->st_info)
                    310:                                              != STB_LOCAL)
                    311:                                                break;
                    312:                                        if (strategy == DB_STGY_ANY &&
                    313:                                            ELFDEFNNAME(ST_BIND)(symp->st_info)
                    314:                                              != STB_LOCAL)
                    315:                                                break;
                    316:                                }
                    317:                        } else if ((off - symp->st_value) == diff) {
                    318:                                if (rsymp == NULL)
                    319:                                        rsymp = symp;
                    320:                                else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
                    321:                                      == STB_LOCAL &&
                    322:                                    ELFDEFNNAME(ST_BIND)(symp->st_info)
                    323:                                      != STB_LOCAL) {
                    324:                                        /* pick the external symbol */
                    325:                                        rsymp = symp;
                    326:                                }
                    327:                        }
                    328:                }
                    329:        }
                    330:
                    331:        if (rsymp == NULL)
                    332:                *diffp = off;
                    333:        else
                    334:                *diffp = diff;
                    335:
                    336:        return ((db_sym_t)rsymp);
                    337: }
                    338:
                    339: /*
                    340:  * Return the name and value for a symbol.
                    341:  */
                    342: void
                    343: db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, char **namep,
                    344:     db_expr_t *valuep)
                    345: {
                    346:        Elf_Sym *symp = (Elf_Sym *)sym;
                    347:        char *strtab;
                    348:
                    349:        if (namep) {
                    350:                strtab = db_elf_find_strtab(symtab);
                    351:                if (strtab == NULL)
                    352:                        *namep = NULL;
                    353:                else
                    354:                        *namep = strtab + symp->st_name;
                    355:        }
                    356:
                    357:        if (valuep)
                    358:                *valuep = symp->st_value;
                    359: }
                    360:
                    361: /*
                    362:  * Return the file and line number of the current program counter
                    363:  * if we can find the appropriate debugging symbol.
                    364:  */
                    365: boolean_t
                    366: db_elf_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename,
                    367:     int *linenum, db_expr_t off)
                    368: {
                    369:
                    370:        /*
                    371:         * XXX We don't support this (yet).
                    372:         */
                    373:        return (FALSE);
                    374: }
                    375:
                    376: /*
                    377:  * Returns the number of arguments to a function and their
                    378:  * names if we can find the appropriate debugging symbol.
                    379:  */
                    380: boolean_t
                    381: db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
                    382:     char **argnamep)
                    383: {
                    384:
                    385:        /*
                    386:         * XXX We don't support this (yet).
                    387:         */
                    388:        return (FALSE);
                    389: }
                    390:
                    391: void
                    392: db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
                    393: {
                    394:        char *strtab;
                    395:        static char suffix[2];
                    396:        Elf_Sym *symp, *symtab_start, *symtab_end;
                    397:
                    398:        symtab_start = STAB_TO_SYMSTART(stab);
                    399:        symtab_end = STAB_TO_SYMEND(stab);
                    400:
                    401:        strtab = db_elf_find_strtab(stab);
                    402:        if (strtab == NULL)
                    403:                return;
                    404:
                    405:        for (symp = symtab_start; symp < symtab_end; symp++)
                    406:                if (symp->st_name != 0) {
                    407:                        suffix[1] = '\0';
                    408:                        switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
                    409:                        case STT_OBJECT:
                    410:                                suffix[0] = '+';
                    411:                                break;
                    412:                        case STT_FUNC:
                    413:                                suffix[0] = '*';
                    414:                                break;
                    415:                        case STT_SECTION:
                    416:                                suffix[0] = '&';
                    417:                                break;
                    418:                        case STT_FILE:
                    419:                                suffix[0] = '/';
                    420:                                break;
                    421:                        default:
                    422:                                suffix[0] = '\0';
                    423:                        }
                    424:                        (*db_forall_func)(stab, (db_sym_t)symp,
                    425:                            strtab + symp->st_name, suffix, 0, arg);
                    426:                }
                    427:        return;
                    428: }
                    429: #endif /* DB_ELF_SYMBOLS */

CVSweb