Annotation of XNU/osfmk/ddb/db_aout.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: /*
                     53:  *     Author: David B. Golub, Carnegie Mellon University
                     54:  *     Date:   7/90
                     55:  */
                     56: /*
                     57:  * Symbol table routines for a.out format files.
                     58:  */
                     59: #include <mach/boolean.h>
                     60: #include <mach/std_types.h>
                     61: #include <machine/db_machdep.h>                /* data types */
                     62: #include <string.h>                    /* For strcpy(), strcmp() */
                     63: #include <ddb/db_aout.h>
                     64: #include <ddb/db_output.h>             /* For db_printf() */
                     65: #include <ddb/db_sym.h>
                     66: 
                     67: #ifndef        DB_NO_AOUT
                     68: 
                     69: #include <ddb/nlist.h>                 /* a.out symbol table */
                     70: #include <ddb/stab.h>
                     71: 
                     72: #define private static
                     73: 
                     74: private int aout_db_order_symbols(char *, char *);
                     75: private int aout_db_compare_symbols(char *, char *);
                     76: private boolean_t aout_db_is_filename(char *);
                     77: private boolean_t aout_db_eq_name(struct nlist *, char *, int);
                     78: 
                     79: /*
                     80:  * An a.out symbol table as loaded into the kernel debugger:
                     81:  *
                     82:  * symtab      -> size of symbol entries, in bytes
                     83:  * sp          -> first symbol entry
                     84:  *                ...
                     85:  * ep          -> last symbol entry + 1
                     86:  * strtab      == start of string table
                     87:  *                size of string table in bytes,
                     88:  *                including this word
                     89:  *             -> strings
                     90:  */
                     91: 
                     92: /*
                     93:  * Find pointers to the start and end of the symbol entries,
                     94:  * given a pointer to the start of the symbol table.
                     95:  */
                     96: #define        db_get_aout_symtab(symtab, sp, ep) \
                     97:        (sp = (struct nlist *)(((vm_offset_t *)(symtab)) + 1), \
                     98:         ep = (struct nlist *)((char *)sp + *((int *)(symtab))))
                     99: 
                    100: char *db_sorting_sym_end;
                    101: 
                    102: private int
                    103: aout_db_order_symbols(
                    104:        char    *s1,
                    105:        char    *s2)
                    106: {
                    107:        struct nlist    *sym1 = (struct nlist *) s1;
                    108:        struct nlist    *sym2 = (struct nlist *) s2;
                    109: 
                    110:        if (sym1->n_value != sym2->n_value) 
                    111:                return (sym1->n_value - sym2->n_value);
                    112:        else {
                    113:                return (sym1->n_un.n_name - sym2->n_un.n_name);
                    114:        }
                    115: }
                    116: 
                    117: private int
                    118: aout_db_compare_symbols(
                    119:        char    *sym1,
                    120:        char    *sym2)
                    121: {
                    122:        return (((struct nlist *) sym1)->n_value -
                    123:                ((struct nlist *) sym2)->n_value);
                    124: }
                    125: 
                    126: int db_sorting_limit = 50000;
                    127: 
                    128: boolean_t
                    129: aout_db_sym_init(
                    130:        char *  symtab,         /* pointer to start of symbol table */
                    131:        char *  esymtab,        /* pointer to end of string table,
                    132:                                   for checking - may be rounded up to
                    133:                                   integer boundary */
                    134:        char *  name,
                    135:        char *  task_addr)      /* use for this task only */
                    136: {
                    137:        struct nlist    *sym_start, *sym_end;
                    138:        struct nlist    *sp;
                    139:        char *  strtab;
                    140:        int     strlen;
                    141:        char *          estrtab;
                    142:        unsigned long   minsym = ~0;
                    143:        unsigned long   maxsym = 0;
                    144:        boolean_t       sorted;
                    145:        boolean_t       sorting;
                    146: #ifdef __MACHO__
                    147:        extern boolean_t getsymtab(char *, 
                    148:                vm_offset_t *, int *,
                    149:                vm_offset_t *,  vm_size_t *);
                    150:        int nsyms;
                    151: #endif
                    152: 
                    153: 
                    154: #ifdef __MACHO__
                    155:        if (!getsymtab(symtab, 
                    156:                (vm_offset_t *)&sym_start, &nsyms, 
                    157:                (vm_offset_t *)&strtab, (vm_size_t *)&strlen)) {
                    158:                return(FALSE);
                    159:        }
                    160:        sym_end = sym_start + nsyms;
                    161:        estrtab = strtab + strlen;
                    162: #else
                    163:        db_get_aout_symtab(symtab, sym_start, sym_end);
                    164: 
                    165:        db_sorting_sym_end = (char *)sym_end;
                    166:        strtab = (char *)sym_end;
                    167:        strlen = *(int *)strtab;
                    168:        estrtab = strtab + strlen;
                    169: #endif
                    170: 
                    171: #ifndef __MACHO__
                    172: #define        round_to_size(x) \
                    173:        (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1))
                    174: 
                    175:        if (round_to_size(estrtab) != round_to_size(esymtab))
                    176:            return (FALSE);
                    177: 
                    178: #undef round_to_size
                    179: #endif
                    180: 
                    181:        sorting = ((sym_end - sym_start) < db_sorting_limit);
                    182: 
                    183:        for (sp = sym_start; sp < sym_end; sp++) {
                    184:            register long strx;
                    185:            strx = sp->n_un.n_strx;
                    186:            if (strx != 0) {
                    187:                if (strx > strlen) {
                    188:                    sp->n_un.n_name = 0;
                    189:                    continue;
                    190:                }
                    191:                sp->n_un.n_name = strtab + strx;
                    192:            }
                    193:            if (sp->n_type != N_ABS) {
                    194:                if (sp->n_value > 0 && sp->n_value < minsym)
                    195:                    minsym = sp->n_value;
                    196:                if (sp->n_value > maxsym)
                    197:                    maxsym = sp->n_value;
                    198:            }
                    199:        }
                    200:        if (maxsym < minsym)
                    201:                minsym = maxsym = 0;
                    202: 
                    203:        if (sorting) {
                    204:                db_qsort((char *) sym_start, sym_end - sym_start,
                    205:                         sizeof (struct nlist), aout_db_order_symbols);
                    206:                sorted = TRUE;
                    207:        } else
                    208:                sorted = FALSE;
                    209: 
                    210:        if (db_add_symbol_table(SYMTAB_AOUT,
                    211:                                (char*)sym_start,
                    212:                                (char*)sym_end,
                    213:                                name,
                    214:                                symtab,
                    215:                                task_addr,
                    216:                                minsym,
                    217:                                maxsym,
                    218:                                sorted))
                    219:        {
                    220:            /* Successfully added symbol table */
                    221: 
                    222:            pmap_protect(kernel_pmap,
                    223:                         (vm_offset_t) sym_start, (vm_offset_t) sym_end,
                    224:                         VM_PROT_READ|VM_PROT_WRITE);
                    225:            pmap_protect(kernel_pmap,
                    226:                         (vm_offset_t) strtab, (vm_offset_t) estrtab,
                    227:                         VM_PROT_READ|VM_PROT_WRITE);
                    228:            return TRUE;
                    229:        }
                    230:        return FALSE;
                    231: }
                    232: 
                    233: /*
                    234:  * This KLUDGE offsets the n_values of a copied symbol table
                    235:  */
                    236: void db_clone_offsetXXX(char *, long);
                    237: void
                    238: db_clone_offsetXXX(char * symtab, long offset)
                    239: {
                    240:        register struct nlist   *sym_start, *sym_end, *sp;
                    241: 
                    242:        db_get_aout_symtab((int *)symtab, sym_start, sym_end);
                    243: 
                    244:        for (sp = sym_start; sp < sym_end; sp++)
                    245:                if (sp->n_type != N_ABS)
                    246:                        sp->n_value += offset;
                    247: }
                    248: /* end KLUDGE */
                    249: 
                    250: /*
                    251:  * check file name or not (check xxxx.x pattern)
                    252:  */
                    253: private boolean_t
                    254: aout_db_is_filename(char *name)
                    255: {
                    256:        while (*name) {
                    257:            if (*name == '.') {
                    258:                if (name[1])
                    259:                    return(TRUE);
                    260:            }
                    261:            name++;
                    262:        }
                    263:        return(FALSE);
                    264: }
                    265: 
                    266: /*
                    267:  * special name comparison routine with a name in the symbol table entry
                    268:  */
                    269: private boolean_t
                    270: aout_db_eq_name(
                    271:        struct nlist *sp,
                    272:        char *name,
                    273:        int incomplete)
                    274: {
                    275:        register char *s1, *s2;
                    276: 
                    277:        s1 = sp->n_un.n_name;
                    278:        s2 = name;
                    279: #ifndef __NO_UNDERSCORES__
                    280:        if (*s1 == '_' && *s2 && *s2 != '_')
                    281:            s1++;
                    282: #endif /* __NO_UNDERSCORES__ */
                    283:        while (*s2) {
                    284:            if (*s1++ != *s2++) {
                    285:                /*
                    286:                 * check .c .o file name comparison case
                    287:                 */
                    288:                if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 
                    289:                        && s1[-2] == '.' && s1[-1] == 'o')
                    290:                    return(TRUE);
                    291:                return(FALSE);
                    292:            }
                    293:        }
                    294:        if (incomplete)
                    295:            return(TRUE);
                    296:        /*
                    297:         * do special check for
                    298:         *     xxx:yyy for N_FUN
                    299:         *     xxx.ttt for N_DATA and N_BSS
                    300:         */
                    301:        return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || 
                    302:                (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
                    303: }
                    304: 
                    305: /*
                    306:  * search a symbol table with name and type
                    307:  *     fp(in,out): last found text file name symbol entry
                    308:  */
                    309: private struct nlist *
                    310: aout_db_search_name(
                    311:        struct nlist    *sp,
                    312:        struct nlist    *ep,
                    313:        char            *name,
                    314:        int             type,
                    315:        struct nlist    **fp,
                    316:         int            incomplete)
                    317: {
                    318:        struct nlist    *file_sp = *fp;
                    319:        struct nlist    *found_sp = 0;
                    320: 
                    321:        for ( ; sp < ep; sp++) {
                    322:            if (sp->n_other)
                    323:                sp->n_other = 0;
                    324:            if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
                    325:                *fp = sp;
                    326:            if (type) {
                    327:                if (sp->n_type == type) {
                    328:                    /* dwm_debug: b26 name, mk6 added last param */
                    329:                    if (aout_db_eq_name(sp, name, 0))
                    330:                        return(sp);
                    331:                }
                    332:                if (sp->n_type == N_SO)
                    333:                    *fp = sp;
                    334:                continue;
                    335:            }
                    336:            if (sp->n_type & N_STAB)
                    337:                continue;
                    338:            if (sp->n_un.n_name && aout_db_eq_name(sp, name, incomplete)) {
                    339:                /*
                    340:                 * In case of qaulified search by a file,
                    341:                 * return it immediately with some check.
                    342:                 * Otherwise, search external one
                    343:                 */
                    344:                if (file_sp) {
                    345:                    if ((file_sp == *fp) || (sp->n_type & N_EXT))
                    346:                        return(sp);
                    347:                } else if ((sp->n_type & N_EXT) ||
                    348:                           (incomplete && !aout_db_is_filename(sp->n_un.n_name)))
                    349:                    return(sp);
                    350:                else
                    351:                    found_sp = sp;
                    352:            }
                    353:        }
                    354:        return(found_sp);
                    355: }
                    356: 
                    357: /*
                    358:  * Print sorted possible completions for a symbol.
                    359:  * Use n_other field to mark completion symbols in order
                    360:  *     to speed up sort.
                    361:  */
                    362: int
                    363: aout_db_qualified_print_completion(
                    364:        db_symtab_t     *stab,
                    365:        char            *sym)
                    366: {
                    367:        struct nlist    *sp;
                    368:        struct nlist    *sp1;
                    369:        struct nlist    *ep;
                    370:        struct nlist    *ep1;
                    371:        struct nlist    *fp = 0;
                    372:        int             symlen;
                    373:        int             nsym = 0;
                    374:        struct nlist    *cur;
                    375:        struct nlist    *new;
                    376:        char            *fname;
                    377:        int             func;
                    378:        int             line;
                    379: 
                    380:        sp = aout_db_search_name((struct nlist *)stab->start,
                    381:                              (struct nlist *)stab->end,
                    382:                              sym, 0, &fp, 1);
                    383:        if (sp == (struct nlist *)0)
                    384:            return 0;
                    385: 
                    386:        symlen = strlen(sym);
                    387:        cur = sp;
                    388:        while (cur) {
                    389:            if (strncmp(cur->n_un.n_name, sym, symlen) == 0)
                    390:                 cur->n_other = 1;
                    391:            else
                    392:                 cur->n_other = 2;
                    393:            ep = cur;
                    394:            cur = aout_db_search_name(cur + 1, (struct nlist *)stab->end,
                    395:                                   sym, 0, &fp, 1);
                    396:        }
                    397: 
                    398:        sp1 = sp;
                    399:        for (;;) {
                    400:            new = cur = sp;
                    401:            while (++cur <= ep)
                    402:                if (cur->n_other) {
                    403:                   if (sp1 == sp)
                    404:                        sp1 = cur;
                    405:                   if (strcmp(&cur->n_un.n_name[cur->n_other - 1],
                    406:                              &new->n_un.n_name[new->n_other - 1]) < 0)
                    407:                        new = cur;
                    408:                   else
                    409:                        ep1 = cur;
                    410:                }
                    411: 
                    412:            func = line = 0;
                    413:            if ((new->n_type & N_EXT) == 0) {
                    414:                for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
                    415:                    if (cur->n_type == N_SO ||
                    416:                        (stab->sorted && cur->n_value < new->n_value))
                    417:                        break;
                    418:                    if (line == 0 &&
                    419:                        cur->n_type == N_SLINE &&
                    420:                        cur->n_value == new->n_value)
                    421:                        line = cur->n_desc;
                    422:                    if (func == 0 &&
                    423:                        cur->n_type == N_FUN &&
                    424:                        cur->n_value == new->n_value)
                    425:                        func = 1;
                    426:                }
                    427: 
                    428:                if (cur->n_type == N_SO)
                    429:                    fname = cur->n_un.n_name;
                    430:                else
                    431:                    fname = (char *)0;
                    432: 
                    433:                if (line == 0 || func == 0)
                    434:                    for (cur = new + 1;
                    435:                         cur < (struct nlist *)stab->end; cur++) {
                    436:                        if (cur->n_type == N_SO ||
                    437:                            (stab->sorted && cur->n_value > new->n_value))
                    438:                            break;
                    439:                        if (line == 0 &&
                    440:                            cur->n_type == N_SLINE &&
                    441:                            cur->n_value == new->n_value) {
                    442:                            line = cur->n_desc;
                    443:                            if (func)
                    444:                                break;
                    445:                        }
                    446:                        if (func == 0 &&
                    447:                            cur->n_type == N_FUN &&
                    448:                            cur->n_value == new->n_value) {
                    449:                            func = 1;
                    450:                            if (line)
                    451:                                break;
                    452:                        }
                    453:                }
                    454:            } else {
                    455:                fname = (char *)0;
                    456:                for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
                    457:                    if (cur->n_type == N_SO ||
                    458:                        (stab->sorted && cur->n_value < new->n_value))
                    459:                        break;
                    460:                    if (func == 0 &&
                    461:                        cur->n_type == N_FUN &&
                    462:                        cur->n_value == new->n_value)
                    463:                        func = 1;
                    464:                }
                    465:                if (func == 0)
                    466:                    for (cur = new + 1;
                    467:                         cur < (struct nlist *)stab->end; cur++) {
                    468:                        if (cur->n_type == N_SO ||
                    469:                            (stab->sorted && cur->n_value > new->n_value))
                    470:                            break;
                    471:                        if (cur->n_type == N_FUN &&
                    472:                            cur->n_value == new->n_value) {
                    473:                            func = 1;
                    474:                            break;
                    475:                        }
                    476:                }
                    477:            }
                    478: 
                    479:            db_sym_print_completion(stab, &new->n_un.n_name[new->n_other - 1],
                    480:                                    func, fname, line);
                    481:            nsym++;
                    482:            new->n_other = 0;
                    483: 
                    484:            if (new == sp) {
                    485:                if (sp1 == sp)
                    486:                    break;
                    487:                sp = sp1;
                    488:            } else if (new == sp1)
                    489:                sp1 = sp;
                    490: 
                    491:            if (new == ep)
                    492:                ep = ep1;
                    493:        }
                    494:        return nsym;
                    495: }
                    496: 
                    497: /*
                    498:  * search a (possibly incomplete) symbol with file, func and line qualification
                    499:  */
                    500: private int
                    501: aout_db_qualified_search(
                    502:        db_symtab_t     *stab,
                    503:        char            *file,
                    504:        char            *sym,
                    505:        int             line,
                    506:        db_sym_t        *ret,
                    507:        char            **name,
                    508:        int             *len)
                    509: {
                    510:        register struct nlist *sp = (struct nlist *)stab->start;
                    511:        struct nlist    *ep = (struct nlist *)stab->end;
                    512:        struct nlist    *fp = 0;
                    513:        struct nlist    *found_sp;
                    514:        unsigned long   func_top;
                    515:        boolean_t       in_file;
                    516:        int             nsym = 0;
                    517:        int             i;
                    518:        char            *p;
                    519: 
                    520:        if (file == 0 && sym == 0)
                    521:            return(0);
                    522:        if (file) {
                    523:            if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp, 0)) == 0)
                    524:                return(0);
                    525:        }
                    526:        if (sym) {
                    527:            for (;;) {
                    528:                sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp,
                    529:                                      (ret == (db_sym_t *)0));
                    530:                if (sp == 0)
                    531:                    return(nsym);
                    532:                if (ret)
                    533:                    break;
                    534: 
                    535:                if (strncmp(sp->n_un.n_name, sym, strlen(sym)) == 0)
                    536:                    p = sp->n_un.n_name;
                    537:                else
                    538:                    p = &sp->n_un.n_name[1];
                    539: 
                    540:                if (*name == (char *)0) {
                    541:                    *name = p;
                    542:                    *len = strlen(p);
                    543:                } else {
                    544:                    for (i = 0; i < *len; i++)
                    545:                        if ((*name)[i] != p[i]) {
                    546:                            *len = i;
                    547:                            break;
                    548:                        }
                    549:                }
                    550: 
                    551:                nsym++;
                    552:                sp++;
                    553:            }
                    554:        }
                    555:        if (line > 0) {
                    556:            if (file && !aout_db_eq_name(fp, file, 0))
                    557:                return(0);
                    558:            found_sp = 0;
                    559:            if (sp->n_type == N_FUN) {
                    560:                /*
                    561:                 * qualfied by function name
                    562:                 *     search backward because line number entries
                    563:                 *     for the function are above it in this case.
                    564:                 */
                    565:                func_top = sp->n_value;
                    566:                if (stab->sorted) {
                    567:                    /* symbols with the same value may have been mixed up */
                    568:                    do {
                    569:                        sp++;
                    570:                    } while (sp->n_value == func_top);
                    571:                }
                    572:                for (sp--; sp >= (struct nlist *)stab->start; sp--) {
                    573:                    if (sp->n_type != N_SLINE)
                    574:                        continue;
                    575:                    if (sp->n_value < func_top)
                    576:                        break;
                    577:                    if (sp->n_desc <= line) {
                    578:                        if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
                    579:                            found_sp = sp;
                    580:                        if (sp->n_desc == line)
                    581:                            break;
                    582:                    }
                    583:                }
                    584:                if (sp->n_type != N_SLINE || sp->n_value < func_top)
                    585:                    return(0);
                    586:            } else {
                    587:                /*
                    588:                 * qualified by only file name
                    589:                 *    search forward in this case
                    590:                 */
                    591:                in_file = TRUE;
                    592:                if (stab->sorted) {
                    593:                    /* symbols with the same value may have been mixed up */
                    594:                    func_top = sp->n_value;
                    595:                    do {
                    596:                        sp--;
                    597:                    } while (sp->n_value == func_top);
                    598:                }
                    599:                for (sp++; sp < ep; sp++) {
                    600:                    if (sp->n_type == N_TEXT 
                    601:                        && aout_db_is_filename(sp->n_un.n_name))
                    602:                        break;          /* enter into another file */
                    603:                    if (sp->n_type == N_SOL) {
                    604:                        in_file = aout_db_eq_name(sp, file, 0);
                    605:                        continue;
                    606:                    }
                    607:                    if (!in_file || sp->n_type != N_SLINE)
                    608:                        continue;
                    609:                    if (sp->n_desc <= line) {
                    610:                        if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
                    611:                            found_sp = sp;
                    612:                        if (sp->n_desc == line)
                    613:                            break;
                    614:                    }
                    615:                }
                    616:            }
                    617:            sp = found_sp;
                    618:        }
                    619:        *ret = (db_sym_t) sp;
                    620:        return(1);
                    621: }
                    622: 
                    623: /*
                    624:  * lookup symbol by name
                    625:  */
                    626: db_sym_t
                    627: aout_db_lookup(
                    628:        db_symtab_t     *stab,
                    629:        char *          symstr)
                    630: {
                    631:        return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr));
                    632: }
                    633: 
                    634: /*
                    635:  * lookup (possibly incomplete) symbol by name
                    636:  */
                    637: int
                    638: aout_db_lookup_incomplete(
                    639:        db_symtab_t     *stab,
                    640:        char *          symstr,
                    641:        char **         name,
                    642:        int             *len,
                    643:        int             *toadd)
                    644: {
                    645:        return(db_sym_parse_and_lookup_incomplete(aout_db_qualified_search,
                    646:                                        stab, symstr, name, len, toadd));
                    647: }
                    648: 
                    649: /*
                    650:  * Display possible completion for the symbol
                    651:  */
                    652: int
                    653: aout_db_print_completion(stab, symstr)
                    654:        db_symtab_t     *stab;
                    655:        char *          symstr;
                    656: {
                    657: 
                    658:        return(db_sym_parse_and_print_completion(aout_db_qualified_print_completion,
                    659:                                                 stab, symstr));
                    660: }
                    661: 
                    662: db_sym_t
                    663: aout_db_search_symbol(
                    664:        db_symtab_t     *symtab,
                    665:        db_addr_t       off,
                    666:        db_strategy_t   strategy,
                    667:        db_expr_t       *diffp)         /* in/out */
                    668: {
                    669:        register unsigned long  diff = *diffp;
                    670:        register struct nlist   *symp = 0;
                    671:        struct nlist            *sp, *ep, *cp;
                    672:        boolean_t               first_pass = FALSE;
                    673: 
                    674:        sp = (struct nlist *)symtab->start;
                    675:        ep = (struct nlist *)symtab->end;
                    676: 
                    677:        if (symtab->sorted) {
                    678:            struct nlist target;
                    679: 
                    680:            target.n_value = off;
                    681:            target.n_un.n_name = (char *) 0;
                    682:            target.n_other = (char) 0;
                    683:            db_qsort_limit_search((char *) &target, (char **) &sp, (char **) &ep,
                    684:                                  sizeof (struct nlist), aout_db_compare_symbols);
                    685:            first_pass = TRUE;
                    686:        }
                    687: 
                    688:     try_again:
                    689:        for (cp = ep-1; cp >= sp; cp--) {
                    690:            if (cp->n_un.n_name == 0)
                    691:                continue;
                    692:            if ((cp->n_type & N_STAB) != 0)
                    693:                continue;
                    694:            if (strategy == DB_STGY_XTRN && (cp->n_type & N_EXT) == 0)
                    695:                continue;
                    696:            if (off >= cp->n_value) {
                    697:                if (off - cp->n_value < diff) {
                    698:                    diff = off - cp->n_value;
                    699:                    symp = cp;
                    700:                    if (diff == 0 && (cp->n_type & N_EXT))
                    701:                            break;
                    702:                }
                    703:                else if (off - cp->n_value == diff) {
                    704:                    if (symp == 0)
                    705:                        symp = cp;
                    706:                    else if ((symp->n_type & N_EXT) == 0 &&
                    707:                                (cp->n_type & N_EXT) != 0)
                    708:                        symp = cp;      /* pick the external symbol */
                    709:                }
                    710:            }
                    711:        }
                    712:        if (symp == 0) {
                    713:            if (first_pass) {
                    714:                first_pass = FALSE;
                    715:                sp = (struct nlist *) symtab->start;
                    716:                goto try_again;
                    717:            }
                    718:            *diffp = off;
                    719:        }
                    720:        else {
                    721:            *diffp = diff;
                    722:        }
                    723:        return ((db_sym_t)symp);
                    724: }
                    725: 
                    726: /*
                    727:  * Return the name and value for a symbol.
                    728:  */
                    729: void
                    730: aout_db_symbol_values(
                    731:        db_sym_t        sym,
                    732:        char            **namep,
                    733:        db_expr_t       *valuep)
                    734: {
                    735:        register struct nlist *sp;
                    736: 
                    737:        sp = (struct nlist *)sym;
                    738:        if (namep)
                    739:            *namep = sp->n_un.n_name;
                    740:        if (valuep)
                    741:            *valuep = sp->n_value;
                    742: }
                    743: 
                    744: #define X_DB_MAX_DIFF  8       /* maximum allowable diff at the end of line */
                    745: extern int     db_search_maxoff;       /* maximum acceptable offset */
                    746: 
                    747: /*
                    748:  * search symbol by value
                    749:  */
                    750: db_sym_t
                    751: aout_db_search_by_addr(
                    752:        db_symtab_t     *stab,
                    753:        db_addr_t       addr,
                    754:        char            **file,
                    755:        char            **func,
                    756:        int             *line,
                    757:        db_expr_t       *diff,
                    758:         int             *args)
                    759: {
                    760:        struct nlist    *sp, *cp;
                    761:        register        struct nlist *line_sp, *func_sp, *file_sp, *line_func;
                    762:        unsigned long   func_diff, line_diff;
                    763:        boolean_t       found_line = FALSE;
                    764:        struct          nlist *ep = (struct nlist *)stab->end;
                    765:        boolean_t       first_pass = FALSE;
                    766: 
                    767:        /*
                    768:         * 92-May-16
                    769:         * Added init of these two... not sure if it's correct, but
                    770:         * can't be worse than random values....  -- [email protected]
                    771:         */
                    772:        func_diff = line_diff = /*HUGE*/0x0fffffff;
                    773: 
                    774:        line_sp = func_sp = file_sp = line_func = 0;
                    775:        *file = *func = 0;
                    776:        *line = 0;
                    777:        *args = -1;
                    778: 
                    779:        sp = (struct nlist *)stab->start;
                    780:        if (stab->sorted) {
                    781:                struct nlist target;
                    782: 
                    783:                target.n_value = addr;
                    784:                target.n_un.n_name = (char *) 0;
                    785:                target.n_other = (char) 0;
                    786:                db_qsort_limit_search((char *) &target, (char **) &sp,
                    787:                                      (char **) &ep, sizeof (struct nlist),
                    788:                                      aout_db_compare_symbols);
                    789:                first_pass = TRUE;
                    790:        }
                    791: 
                    792:        for (cp = sp; cp < ep; cp++) {
                    793:            switch(cp->n_type) {
                    794:            case N_SLINE:
                    795:                if (cp->n_value <= addr) {
                    796:                    if (line_sp == 0 || line_diff >= addr - cp->n_value) {
                    797:                        if (line_func)
                    798:                            line_func = 0;
                    799:                        line_sp = cp;
                    800:                        line_diff = addr - cp->n_value;
                    801:                    }
                    802:                }
                    803:                if (cp->n_value >= addr && line_sp)
                    804:                    found_line = TRUE;
                    805:                continue;
                    806:            case N_FUN:
                    807:                if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
                    808:                    && line_func == 0)
                    809:                    line_func = cp;
                    810:                continue;
                    811:            case N_SO:
                    812:                if (cp->n_value > addr)
                    813:                    continue;
                    814:                if (file_sp == 0 || file_sp->n_value <= cp->n_value)
                    815:                    file_sp = cp;
                    816:                continue;
                    817:            case N_TEXT:
                    818:                if (aout_db_is_filename(cp->n_un.n_name)) {
                    819:                    if (cp->n_value > addr)
                    820:                        continue;
                    821:                    if (file_sp == 0 || file_sp->n_value <= cp->n_value)
                    822:                        file_sp = cp;
                    823:                } else if (cp->n_value <= addr &&
                    824:                         (func_sp == 0 || func_diff > addr - cp->n_value)) {
                    825:                    func_sp = cp;
                    826:                    func_diff = addr - cp->n_value;
                    827:                }
                    828:                continue;
                    829:            case N_TEXT|N_EXT:
                    830:                if (cp->n_value <= addr &&
                    831:                         (func_sp == 0 || func_diff >= addr - cp->n_value)) {
                    832:                    func_sp = cp;
                    833:                    func_diff = addr - cp->n_value;
                    834:                    if (func_diff == 0 && file_sp && func_sp && line_sp == 0)
                    835:                        break;
                    836:                }
                    837:            default:
                    838:                if (stab->sorted) {
                    839:                        if ((cp->n_value > addr) &&
                    840:                            (cp->n_value - addr > db_search_maxoff))
                    841:                                break;
                    842:                }
                    843:                continue;
                    844:            }
                    845:            break;
                    846:        }
                    847:        if (first_pass && (!file_sp || !line_sp || !func_sp)) {
                    848:            first_pass = FALSE;
                    849:            cp = sp;
                    850:            sp = (struct nlist *)stab->start;
                    851:            for (; cp >= sp; cp--) {
                    852:                switch(cp->n_type) {
                    853:                case N_SLINE:
                    854:                    if (line_sp)
                    855:                        found_line = TRUE;
                    856:                    continue;
                    857:                case N_FUN:
                    858:                    if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
                    859:                        && line_func == 0)
                    860:                        line_func = cp;
                    861:                    continue;
                    862:                case N_SO:
                    863:                    if (file_sp == 0)
                    864:                        file_sp = cp;
                    865:                    continue;
                    866:                case N_TEXT:
                    867:                    if (aout_db_is_filename(cp->n_un.n_name)) {
                    868:                        if (file_sp == 0)
                    869:                            file_sp = cp;
                    870:                    } else if (func_sp == 0) {
                    871:                        func_sp = cp;
                    872:                        func_diff = addr - cp->n_value;
                    873:                    }
                    874:                    continue;
                    875:                case N_TEXT|N_EXT:
                    876:                    if (func_sp == 0) {
                    877:                        func_sp = cp;
                    878:                        func_diff = addr - cp->n_value;
                    879:                        if (func_diff == 0 && file_sp && func_sp
                    880:                            && line_sp == 0)
                    881:                            break;
                    882:                    }
                    883:                default:
                    884:                    if (line_sp && file_sp &&
                    885:                        addr - cp->n_value > db_search_maxoff)
                    886:                        break;
                    887:                    continue;
                    888:                }
                    889:                break;
                    890:            }
                    891:        }
                    892: #if 0  
                    893: /*
                    894:  * XXX - [email protected]
                    895:  * I don't know if that code is useful to something, but it makes the -gline
                    896:  * option of gcc useless.
                    897:  */
                    898:        if (line_sp) {
                    899:            if (line_func == 0 || func_sp == 0
                    900:                || line_func->n_value != func_sp->n_value)
                    901:                line_sp = 0;
                    902:        }
                    903: #else
                    904:        if (line_sp && !found_line) {
                    905:                line_sp = 0;
                    906:        }
                    907: #endif
                    908:        *diff = 0;
                    909:        if (file_sp) {
                    910:            *diff = addr - file_sp->n_value;
                    911:            *file = file_sp->n_un.n_name;
                    912:        }
                    913:        if (line_sp) {
                    914:            *diff = addr - line_sp->n_value;
                    915:            *line = line_sp->n_desc;
                    916:        }
                    917:        if (func_sp) {
                    918:            *diff = addr - func_sp->n_value;
                    919:            *func = (func_sp->n_un.n_name[0] == '_')?
                    920:                        func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
                    921:            if (line_func && (line_func->n_desc & 0x4000))
                    922:                *args = line_func->n_desc & 0x3ff;
                    923:        }
                    924:        return((db_sym_t) func_sp);
                    925: }
                    926: 
                    927: /*
                    928:  * Find filename and lineno within, given the current pc.
                    929:  */
                    930: boolean_t
                    931: aout_db_line_at_pc(
                    932:        db_symtab_t     *stab,
                    933:        db_sym_t        sym,
                    934:        char            **file,
                    935:        int             *line,
                    936:        db_expr_t       pc)
                    937: {
                    938:        char            *func;
                    939:        db_expr_t       diff;
                    940:        boolean_t       found;
                    941:        int             args;
                    942: 
                    943:        found = (aout_db_search_by_addr(stab, (unsigned)pc, file, &func, line,
                    944:                                     &diff, &args)
                    945:                 != DB_SYM_NULL);
                    946:        return(found && func && *file);
                    947: }
                    948: 
                    949: /*
                    950:  * Initialization routine for a.out files.
                    951:  */
                    952: void
                    953: aout_db_init(void)
                    954: {
                    955: #ifndef __MACHO__
                    956:        extern vm_offset_t      kern_sym_start;
                    957:        extern vm_size_t        kern_sym_size;
                    958: #else
                    959:        extern struct mach_header _mh_execute_header;
                    960: #endif
                    961: 
                    962: #ifndef __MACHO__
                    963:        if (kern_sym_size != 0)
                    964:            aout_db_sym_init((char *) kern_sym_start,
                    965:                          (char *)(kern_sym_start + kern_sym_size),
                    966:                          "mach",
                    967:                          (char *)0);
                    968: #else
                    969:        aout_db_sym_init((char *) &_mh_execute_header,
                    970:                (char *)0, "mach", (char *)0);
                    971: #endif
                    972: }
                    973: 
                    974: #endif /* DB_NO_AOUT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.