Annotation of XNU/osfmk/ddb/db_aout.c, revision 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.