Annotation of researchv9/jerq/sgs/ld/alloc.c, revision 1.1

1.1     ! root        1: static char ID[] = "@(#) alloc.c: 1.7 5/27/83";
        !             2: #include "system.h"
        !             3: 
        !             4: #include <stdio.h>
        !             5: #include "structs.h"
        !             6: #include "extrns.h"
        !             7: #include "list.h"
        !             8: #include "params.h"
        !             9: #include "sgsmacros.h"
        !            10: #include "ldmacros.h"
        !            11: 
        !            12: #if TRVEC
        !            13: #include "sdpsrc/hd/define2.h"
        !            14: #include "tv.h"
        !            15: #include "ldtv.h"
        !            16: #endif
        !            17: 
        !            18: #define L15    0xfL
        !            19: /*eject*/
        !            20: alloc()
        !            21: {
        !            22: 
        !            23: /*
        !            24:  * Perform the allocation of the output sections into the configured
        !            25:  * memory
        !            26:  */
        !            27: 
        !            28:        bldmemlist();   /* build initial address space from memlist     */
        !            29: 
        !            30: #if USEREGIONS
        !            31:        bldreglist();   /* collate regions into available space         */
        !            32: #endif
        !            33: 
        !            34:        alc_bonds();    /* allocate bonded output sections              */
        !            35: 
        !            36: #if DEBUG
        !            37:        if( dflag > 1 ) {
        !            38:                fprintf(stderr, "\n\nalc_bonds");
        !            39:                dump_mem();
        !            40:                }
        !            41: #endif
        !            42: 
        !            43:        alc_owners();   /* allocate out sects assigned to owners        */
        !            44:        alc_attowns();  /* allocate out sects assigned to attributes    */
        !            45: 
        !            46: #if DEBUG
        !            47:        if( dflag > 1 ) {
        !            48:                fprintf(stderr, "\n\nalc_own, alc_att");
        !            49:                dump_mem();
        !            50:                }
        !            51: #endif
        !            52: 
        !            53: #if IANDD && USEREGIONS
        !            54:        if( iflag  &&  ( ! tvflag ) )
        !            55:                alc_iandd();    /* separate I and D */
        !            56: #endif
        !            57: 
        !            58:        alc_the_rest();         /* allocate everything as yet unallocated       */
        !            59: 
        !            60: #if DEBUG
        !            61:        if( dflag > 1 ) {
        !            62:                fprintf(stderr, "\n\nalc_iandd, alc_rest");
        !            63:                dump_mem();
        !            64:                }
        !            65: #endif
        !            66: 
        !            67: #if USEREGIONS
        !            68:        if (tvflag && (reglist.head == NULL))
        !            69:                bld_regions();
        !            70: #endif
        !            71: 
        !            72:        audit_groups();
        !            73: 
        !            74:        audit_regions();
        !            75: 
        !            76: #if DEBUG
        !            77:        if( dflag > 1 ) {
        !            78:                fprintf(stderr, "\nbld_reg, audit_grp, audit_reg");
        !            79:                dump_mem();
        !            80:                }
        !            81: #endif
        !            82: 
        !            83:        if (aflag)
        !            84:                set_spec_syms();   /* generate special symbols for absolute load */
        !            85: 
        !            86: }
        !            87: /*eject*/
        !            88: bldmemlist()
        !            89: {
        !            90: 
        !            91:        register MEMTYPE *mp;
        !            92:        register ANODE *ap;
        !            93: 
        !            94: /*
        !            95:  * Build the initial address space from the memlist
        !            96:  */
        !            97: 
        !            98:        for( mp = (MEMTYPE *) memlist.head; mp != NULL; mp = mp->mtnext ) {
        !            99:                ap = newnode();
        !           100:                ap->adpaddr = mp->mtorig;
        !           101:                ap->adsize  = mp->mtlength;
        !           102:                ap->admemp  = mp;
        !           103:                mp->mtaddrhd=mp->mtaddrtl = ap;
        !           104:                listadd(l_ADR, &avlist, ap);
        !           105:                }
        !           106: 
        !           107: #if DEBUG
        !           108:        if( dflag )
        !           109:                dump_mem();
        !           110: #endif
        !           111: 
        !           112: }
        !           113: /*eject*/
        !           114: alc_bonds()
        !           115: {
        !           116: 
        !           117: /*
        !           118:  * Process the bond.list, allocating all output sections which have
        !           119:  * been bonded to specific addresses
        !           120:  */
        !           121: 
        !           122:        ACTITEM *aip,           /* ptr to bonded section */
        !           123:                *nextaip;       /* ptr to next item on bond.list */
        !           124:        ANODE   *sap,           /* ptr to memory node containing bond address */
        !           125:                *eap, *newap, *splitnode();
        !           126:        OUTSECT *osp,           /* ptr to output section description for the bonded section */
        !           127:                *bsp;
        !           128:        ADDRESS lastaddr, have, need;
        !           129: 
        !           130:        for( aip = (ACTITEM *) bondlist.head; aip != NULL; aip = nextaip ) {
        !           131:                nextaip = aip->bond.ainext;
        !           132:                osp = aip->bond.aioutsec;
        !           133:                /*
        !           134:                 * DSECT sections are bonded at the requested address,
        !           135:                 * but are not allocated any memory
        !           136:                 */
        !           137:                if( osp->oshdr.s_flags & STYP_DSECT) {
        !           138:                        osp->oshdr.s_paddr = osp->oshdr.s_vaddr = aip->bond.aiadrbnd;
        !           139:                        listadd(l_DS, &dsectlst, osp);
        !           140:                        free(aip);
        !           141:                        continue;
        !           142:                        }
        !           143:                /*
        !           144:                 * For the current bonded section, find out in which of
        !           145:                 * the space nodes the bond address is located
        !           146:                 */
        !           147:                for( sap = (ANODE *) avlist.head; sap != NULL; sap = sap->adnext ) {
        !           148:                        if( sap->adpaddr+(ADDRESS)sap->adsize > aip->bond.aiadrbnd)
        !           149:                                break;
        !           150:                        }
        !           151: 
        !           152:                if(sap == NULL) {
        !           153:                        lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           154:                                "bond address %.2lx for %.8s is outside all configured memory",
        !           155:                                aip->bond.aiadrbnd, (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name);
        !           156:                        free(aip);
        !           157:                        continue;
        !           158:                        }
        !           159:                /*
        !           160:                 * If an space node exists for the bond address, sap
        !           161:                 * points to it
        !           162:                 */
        !           163:                if( sap->adpaddr > aip->bond.aiadrbnd ) {
        !           164:                        lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           165:                                "bond address %.2lx for %.8s is not in configured memory",
        !           166:                                aip->bond.aiadrbnd, (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name);
        !           167:                        free(aip);
        !           168:                        continue;
        !           169:                        }
        !           170:                /*
        !           171:                 * Make sure the space node is of type ADAVAIL (i.e, that
        !           172:                 * it is unallocated memory
        !           173:                 */
        !           174:                if(sap->adtype != ADAVAIL) {
        !           175:                        bsp=sap->adscnptr;
        !           176:                        lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           177:                                "bond address %.2lx for %.8s overlays previously allocated section %.8s at %.2lx",
        !           178:                                aip->bond.aiadrbnd, (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name,
        !           179:                                bsp->oshdr.s_name, sap->adpaddr);
        !           180:                        free(aip);
        !           181:                        continue;
        !           182:                        }
        !           183:                /*
        !           184:                 * If the bond address is not the start of an AVAIL
        !           185:                 * node, split the AVAIL node into two nodes. The
        !           186:                 * first will be AVAIL, the second SECT
        !           187:                 */
        !           188:                if( sap->adpaddr < aip->bond.aiadrbnd ) {
        !           189:                        newap = splitnode(sap,aip->bond.aiadrbnd);
        !           190:                        sap = newap;
        !           191:                        }
        !           192:                /*
        !           193:                 * Make sure the entire bonded section will fit into memory
        !           194:                 *      1. The bonded section must fit into configured memory
        !           195:                 *      2. Each space node into which the section falls
        !           196:                 *              must be of type AVAIL
        !           197:                 *      3. Each space node must be contiguous
        !           198:                 */
        !           199:                have = sap->adpaddr + sap->adsize;
        !           200:                /*
        !           201:                 * special processing for special people:
        !           202:                 *      if one needs to allocate more memory
        !           203:                 *      than is explicitly demanded, do
        !           204:                 *      so here [ in special.c ]
        !           205:                 */
        !           206: 
        !           207:                need = sap->adpaddr + osp->oshdr.s_size;
        !           208:                adjneed(&need, osp, sap);
        !           209:                eap = sap;
        !           210:                lastaddr = sap->adpaddr;
        !           211:                while ( have < need ) {
        !           212:                        lastaddr += eap->adsize;
        !           213:                        eap = eap->adnext;
        !           214:                        if(eap == NULL) {
        !           215:                                lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           216:                                        "%.8s, bonded at %.2lx, won't fit into configured memory",
        !           217:                                         (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name, aip->bond.aiadrbnd);
        !           218:                                free(aip);
        !           219:                                break;
        !           220:                                }
        !           221:                        if(eap->adtype != ADAVAIL) {
        !           222:                                bsp = eap->adscnptr;
        !           223:                                lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           224:                                        "%.8s at %.2lx overlays previously allocated section %.8s at %.2lx",
        !           225:                                         (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name, aip->bond.aiadrbnd,
        !           226:                                         bsp->oshdr.s_name, eap->adpaddr);
        !           227:                                eap = NULL;
        !           228:                                free(aip);
        !           229:                                break;
        !           230:                                }
        !           231:                        if(eap->adpaddr != lastaddr) {
        !           232:                                lderror(1, aip->bond.aiinlnno, aip->bond.aiinflnm,
        !           233:                                        "%.8s enters unconfigured memory at %.2lx",
        !           234:                                         (*(osp->oshdr.s_name) == '\0') ? "GROUP" : osp->oshdr.s_name, lastaddr);
        !           235:                                eap = NULL;
        !           236:                                free(aip);
        !           237:                                break;
        !           238:                                }
        !           239:                        have += eap->adsize;
        !           240:                        }
        !           241:                if( eap == NULL )
        !           242:                        continue;
        !           243:                /*
        !           244:                 * If the bonded section does not end at the end of the
        !           245:                 * space node, split the space node up. The first will
        !           246:                 * be SECT, the second AVAIL
        !           247:                 */
        !           248:                if ( have > need )
        !           249:                        newap = splitnode(eap, need);
        !           250:                /*
        !           251:                 * Reserve and set the output section ptrs
        !           252:                 * in the address subspace
        !           253:                 */
        !           254:                do_alloc(sap,eap,osp);
        !           255: 
        !           256:                free(aip);
        !           257:                }
        !           258: }
        !           259: /*eject*/
        !           260: alc_owners()
        !           261: {
        !           262: 
        !           263: /*
        !           264:  * Allocate the output sections which have been given explicit
        !           265:  * owners.  The owner of a section can be either a memory area, or a
        !           266:  * region
        !           267:  */
        !           268: 
        !           269:        ACTITEM *aip,           /* ptr to section having an owner */
        !           270:                *nextaip;       /* ptr to next item on ownlist    */
        !           271:        MEMTYPE *mp;            /* ptr to a memory area item      */
        !           272: #if USEREGIONS
        !           273:        REGION *rp;             /* ptr to a region item           */
        !           274: #endif
        !           275:        ANODE *ap1, *ap2;
        !           276:        short failure;
        !           277: 
        !           278:        for( aip = (ACTITEM *) ownlist.head; aip != NULL; aip = nextaip ) {
        !           279:                nextaip = aip->dfownr.ainext;
        !           280:                /*
        !           281:                 * It is meaningless to have owners for a DSECT
        !           282:                 * since they are not allocated
        !           283:                 */
        !           284:                if( aip->dfownr.aioutsec->oshdr.s_flags & STYP_DSECT) {
        !           285:                        lderror(1, aip->dfownr.aiinlnno, aip->dfownr.aiinflnm,
        !           286:                            "DSECT %.8s can't be given an owner",
        !           287:                            aip->dfownr.aioutsec->oshdr.s_name);
        !           288:                        free(aip);
        !           289:                        continue;
        !           290:                        }
        !           291: 
        !           292:                /*
        !           293:                 * Look in memlist for the owner's name
        !           294:                 */
        !           295:                failure = 1;
        !           296:                for( mp = (MEMTYPE *) memlist.head; mp != NULL; mp = mp->mtnext ) {
        !           297:                        if( equal(aip->dfownr.ainamown,mp->mtname,8)  &&
        !           298:                            (can_alloc(mp->mtaddrhd,mp->mtaddrtl,aip->dfownr.aioutsec,
        !           299:                                 &ap1,&ap2)) ) {
        !           300:                                /*
        !           301:                                 * Found where to put the output section
        !           302:                                 */
        !           303:                                do_alloc(ap1,ap2,aip->dfownr.aioutsec);
        !           304:                                failure = 0;
        !           305:                                break;
        !           306:                                }
        !           307:                        }
        !           308: #if USEREGIONS
        !           309:                /*
        !           310:                 * If the name was not found in the memlist, (failure still
        !           311:                 * 1), then try the reglist
        !           312:                 */
        !           313:                if( ! failure ) {
        !           314:                        free(aip);
        !           315:                        continue;
        !           316:                        }
        !           317: 
        !           318:                for( rp = (REGION *) reglist.head; rp != NULL; rp = rp->rgnext ) {
        !           319:                        if( equal(aip->dfownr.ainamown,rp->rgname,8) &&
        !           320:                            (can_alloc(rp->rgaddrhd,rp->rgaddrtl,aip->dfownr.aioutsec,
        !           321:                                 &ap1,&ap2)) ) {
        !           322:                                /*
        !           323:                                 * Output section goes in this region
        !           324:                                 *  between ap1 and ap2
        !           325:                                 */
        !           326:                                do_alloc(ap1,ap2,aip->dfownr.aioutsec);
        !           327:                                failure = 0;
        !           328:                                break;
        !           329:                                }
        !           330:                        }
        !           331: #endif
        !           332: 
        !           333: 
        !           334:                /*
        !           335:                 * If failed in to find where to put the output section,
        !           336:                 * issue an error message
        !           337:                 */
        !           338:                if(failure)
        !           339:                        lderror(1, aip->dfownr.aiinlnno, aip->dfownr.aiinflnm,
        !           340:                                "can't allocate section %.8s into owner %.8s",
        !           341:                                aip->dfownr.aioutsec->oshdr.s_name,aip->dfownr.ainamown);
        !           342: 
        !           343:                free(aip);
        !           344:                }
        !           345: 
        !           346: }
        !           347: /*eject*/
        !           348: alc_attowns()
        !           349: {
        !           350: 
        !           351: /*
        !           352:  * Allocate the output sections assigned to any memory type
        !           353:  * with a given attribute
        !           354:  */
        !           355: 
        !           356:        ACTITEM *aip,           /* ptr to section tied to an attribute */
        !           357:                *nextaip;       /* ptr to next item on atownlst  */
        !           358:        MEMTYPE *mp;            /* ptr to an item on the memlist */
        !           359:        ANODE   *ap1, *ap2;
        !           360:        short   failure;
        !           361: 
        !           362:        for( aip = (ACTITEM *) atownlst.head; aip != NULL; aip = nextaip ) {
        !           363:                nextaip = aip->ownatr.ainext;
        !           364:                /*
        !           365:                 * It is meaningless to associate a DSECT with an
        !           366:                 * attribute, since they are not allocated any memory
        !           367:                 */
        !           368:                if( aip->ownatr.aioutsec->oshdr.s_flags & STYP_DSECT) {
        !           369:                        lderror(1, aip->ownatr.aiinlnno, aip->ownatr.aiinflnm,
        !           370:                            "DSECT %.8s can't be linked to an attribute",
        !           371:                            aip->ownatr.aioutsec->oshdr.s_name);
        !           372:                        free(aip);
        !           373:                        continue;
        !           374:                        }
        !           375: 
        !           376:                /*
        !           377:                 * Look for a memory area with the specified attribute
        !           378:                 */
        !           379:                failure = 1;
        !           380:                for( mp = (MEMTYPE *) memlist.head; mp != NULL; mp = mp->mtnext ) {
        !           381:                        if( (aip->ownatr.aiownatt == mp->mtattr) &&
        !           382:                            (can_alloc(mp->mtaddrhd,mp->mtaddrtl,
        !           383:                                     aip->ownatr.aioutsec,&ap1,&ap2)) ) {
        !           384:                                do_alloc(ap1,ap2,aip->ownatr.aioutsec);
        !           385:                                failure = 0;
        !           386:                                break;
        !           387:                                }
        !           388:                        }
        !           389: 
        !           390:                if(failure)
        !           391:                        lderror(1,0,NULL, "can't allocate %.8s with attr %x",
        !           392:                              aip->ownatr.aioutsec->oshdr.s_name,aip->ownatr.aiownatt);
        !           393: 
        !           394:                free(aip);
        !           395:                }
        !           396: }
        !           397: /*eject*/
        !           398: alc_the_rest()
        !           399: {
        !           400: 
        !           401: /*
        !           402:  * Allocate every output section that is not as yet allocated
        !           403:  */
        !           404: 
        !           405:        ANODE **anlp;           /* ptr to (sorted) avail node list      */
        !           406:        OUTSECT **usp;          /* ptr to (sorted) unalloc outsect list */
        !           407: 
        !           408:        ANODE *ap;              /* ptr to element from anlp     */
        !           409:        short numanods,         /* number of avail nodes        */
        !           410:              nanl;             /* working index into anlp      */
        !           411:        OUTSECT *osp;           /* ptr to element from usp      */
        !           412:        short numuaos,          /* number of unalloc outsects   */
        !           413:              nuaos;            /* working index into usp       */
        !           414:        int cmp_uos(),          /* qsort sorting routine        */
        !           415:            cmp_anl();          /* qsort sorting routine        */
        !           416: 
        !           417: /*
        !           418:  * Build a list of unallocated output sections
        !           419:  */
        !           420: 
        !           421:        numuaos = 0;
        !           422:        for( osp = (OUTSECT *) outsclst.head; osp != NULL; osp = osp->osnext )
        !           423:                if( (osp->oshdr.s_paddr == -1L)  &&  (! (osp->oshdr.s_flags & STYP_DSECT)) )
        !           424:                        numuaos++;
        !           425:        if(numuaos == 0)
        !           426:                return;         /* nothing left to allocate */
        !           427: 
        !           428:        usp = (OUTSECT **) myalloc(sizeof(OUTSECT *) * (numuaos + 1));
        !           429:        nuaos = 0;
        !           430:        for( osp = (OUTSECT *) outsclst.head; osp != NULL; osp = osp->osnext )
        !           431:                if(osp->oshdr.s_paddr == -1L) {
        !           432:                        /*
        !           433:                         * Allocate DSECTs so as to start at zero
        !           434:                         */
        !           435:                        if( osp->oshdr.s_flags & STYP_DSECT) {
        !           436:                                osp->oshdr.s_paddr = 0L;
        !           437:                                listadd(l_DS,&dsectlst,osp);
        !           438:                                }
        !           439:                        else
        !           440:                                usp[nuaos++] = osp;
        !           441:                        }
        !           442: 
        !           443: #if USEREGIONS
        !           444: /*
        !           445:  * Sort only if more than 3 output sections.  This exempts the
        !           446:  *       basic load, containing only .text, .data, and .bss sections.
        !           447:  *       They will usually be in the usual order.
        !           448:  *
        !           449:  * NOTE:  Sort only if REGIONS directives were supplied
        !           450:  */
        !           451: 
        !           452:        if( (numuaos > 3)  &&  (reglist.head != NULL) )
        !           453:                qsort(usp, numuaos, sizeof(osp), cmp_uos);
        !           454: #endif
        !           455:        usp[nuaos] = NULL;
        !           456: 
        !           457: /*
        !           458:  * Build the list of avail space nodes
        !           459:  *
        !           460:  * The size of the list used to hold the AVAIL pointers must be big
        !           461:  * enough to allow for possible fragmentation of an existing AVAIL
        !           462:  * node during allocation:
        !           463:  *
        !           464:  *     1 AVAIL node -> 1 AVAIL node (due to ALIGNment)
        !           465:  *                     1 ADSECT node (assigned to the OUTSECT)
        !           466:  *                     1 AVAIL node (remainder of original AVAIL node)
        !           467:  *     
        !           468:  */
        !           469: 
        !           470:        numanods = 0;
        !           471:        for( ap = (ANODE *) avlist.head; ap != NULL; ap = ap->adnext )
        !           472:                if( (ap->adtype == ADAVAIL)  &&  ((reglist.head == NULL) || (ap->adregp != NULL)) )
        !           473:                        numanods++;
        !           474: 
        !           475:        anlp = (ANODE **) myalloc( sizeof(ANODE *) * (numanods + 1)  +
        !           476:                                   sizeof(OUTSECT *) * (numuaos) );
        !           477:        
        !           478:        nanl = 0;
        !           479:        for( ap = (ANODE *) avlist.head; ap != NULL; ap = ap->adnext )
        !           480:                if( (ap->adtype==ADAVAIL)  &&  ((reglist.head == NULL) || (ap->adregp != NULL)) )
        !           481:                        anlp[nanl++] = ap;
        !           482: 
        !           483: #if USEREGIONS
        !           484: /*
        !           485:  * Sort the avail space node list, on space size, from low to high
        !           486:  */
        !           487: 
        !           488:        qsort(anlp,numanods,sizeof(ap),cmp_anl);
        !           489: #endif
        !           490:        anlp[nanl] = NULL;      /* terminating entry    */
        !           491: 
        !           492:        alc_lists(usp, anlp, nanl);
        !           493: 
        !           494:        free(usp);
        !           495:        free(anlp);
        !           496: }
        !           497: /*eject*/
        !           498: audit_groups()
        !           499: {
        !           500:        OUTSECT *grpp, *osp, *prevp, *p;
        !           501:        ANODE *ap;
        !           502:        ADDRESS addr;
        !           503: 
        !           504:        prevp = NULL;
        !           505:        grpp = (OUTSECT *) outsclst.head;
        !           506:        while (grpp) {
        !           507:                if( grpp->oshdr.s_flags & STYP_GROUP) {
        !           508:                        addr = grpp->oshdr.s_paddr;
        !           509:                        if( (ap=findsanode(grpp)) == NULL )
        !           510:                                lderror(2,0,NULL, "internal error: audit_groups, findsanode failure");
        !           511:                        ((OUTSECT *) grpp->osinclhd)->osblock = grpp->osblock;
        !           512:                        for( osp = (OUTSECT *) grpp->osinclhd; osp != NULL; osp = osp->osnext ) 
        !           513:                                if (osp->oshdr.s_flags & STYP_DSECT) {
        !           514:                                        osp->oshdr.s_paddr = addr;
        !           515:                                        listadd( l_DS, &dsectlst, osp );
        !           516:                                } else {
        !           517:                                        if ( !(ap->adscnptr->oshdr.s_flags & STYP_GROUP))
        !           518:                                                ap = splitnode( ap, addr );
        !           519:                                        ap->adscnptr = osp;
        !           520:                                        if( ap->adpaddr != addr )
        !           521:                                                lderror(2,0,NULL, "internal error: audit_groups, address mismatch");
        !           522:                                        osp->oshdr.s_paddr = addr;
        !           523:                                        addr += osp->oshdr.s_size;
        !           524:                                }
        !           525:                        if( prevp )
        !           526:                                prevp->osnext = (OUTSECT *) grpp->osinclhd;
        !           527:                        else
        !           528:                                outsclst.head = (char *) grpp->osinclhd;
        !           529:                        prevp = (OUTSECT *) grpp->osincltl;
        !           530:                        prevp->osnext = grpp->osnext;
        !           531:                        p = grpp;
        !           532:                        grpp = grpp->osnext;
        !           533:                        if( grpp == NULL )
        !           534:                                outsclst.tail = (char *) prevp;
        !           535:                        free(p);
        !           536:                        }
        !           537:                else {
        !           538:                        prevp = grpp;
        !           539:                        grpp = grpp->osnext;
        !           540:                        }
        !           541:                }
        !           542: 
        !           543: #if DEBUG
        !           544:        if( dflag )
        !           545:                dmp_outsects();
        !           546: #endif
        !           547: }
        !           548: /*eject*/
        !           549: audit_regions()
        !           550: {
        !           551: 
        !           552: /*
        !           553:  * 1. Compute the virtual addresses of each output section
        !           554:  *     The logic used by ld results in physical addresses being computed
        !           555:  *     prior to virtual addresses
        !           556:  *
        !           557:  * 2. Perform a consistency check, to make sure sufficient regions 
        !           558:  *     have been defined, where regions are necessary
        !           559:  */
        !           560: 
        !           561:        register ANODE *ap;
        !           562:        register OUTSECT *osp;
        !           563: #if USEREGIONS
        !           564:        register REGION *rp;
        !           565: 
        !           566:        if( reglist.head == NULL ) {
        !           567:                lderror(1,0,NULL, "internal error: audit_regions detected no regions built");
        !           568:                return;
        !           569:                }
        !           570: #endif
        !           571: 
        !           572:        for( ap = (ANODE *) avlist.head; ap != NULL; ap = ap->adnext ) {
        !           573:                if( ap->adtype == ADSECT) {
        !           574: #if USEREGIONS
        !           575:                        rp = ap->adregp;
        !           576:                        osp = ap->adscnptr;
        !           577:                        if( ap->adpaddr == osp->oshdr.s_paddr )
        !           578:                                if( rp != NULL)
        !           579:                                        osp->oshdr.s_vaddr = rp->rgvaddr + ap->adpaddr - rp->rgorig;
        !           580:                                else
        !           581:                                        osp->oshdr.s_vaddr = osp->oshdr.s_paddr;
        !           582:                        /*
        !           583:                         * Make sure every output section goes into some
        !           584:                         * region
        !           585:                         */
        !           586:                        if( ! ap->adregp )
        !           587:                                lderror(1,0,NULL,"output section %.8s not allocated into a region",
        !           588:                                        osp->oshdr.s_name);
        !           589: #else
        !           590:                        osp = ap->adscnptr;
        !           591:                        if( ap->adpaddr == osp->oshdr.s_paddr )
        !           592:                                osp->oshdr.s_vaddr = osp->oshdr.s_paddr;
        !           593: #endif
        !           594:                        }
        !           595:                }
        !           596: 
        !           597:        return;
        !           598: 
        !           599: }
        !           600: /*eject*/
        !           601: ANODE *
        !           602: findsanode(osp)
        !           603: OUTSECT        *osp;
        !           604: {
        !           605:        
        !           606: /*
        !           607:  * Run down the avlist and look for a particular
        !           608:  * section pointer.  Return the pointer to the
        !           609:  * ANODE containing it, or return NULL.
        !           610:  */
        !           611: 
        !           612:        register ANODE  *ap;
        !           613: 
        !           614:        for( ap = (ANODE *) avlist.head; ap != NULL; ap = ap->adnext )
        !           615:                if( ap->adscnptr == osp )
        !           616:                        break;
        !           617: 
        !           618:        return ( ap );
        !           619: }
        !           620: /*eject*/
        !           621: alc_lists(usl,anl,nanl)
        !           622: OUTSECT *usl[];                /* sorted list of output sections */
        !           623: ANODE *anl[];          /* sorted list of available space */
        !           624: short nanl;            /* next free entry in the anl list*/
        !           625: {
        !           626:        OUTSECT *usp;
        !           627:        ANODE   *ap1, *ap2, *ap3;
        !           628:        short   ani,            /* index into sorted ANODEs     */
        !           629:                usi,            /* index into sorted OUTSECTs   */
        !           630:                new_node;       /* flag if ANODE was split up   */
        !           631:        int cmp_anl();          /* qsort sorting routine        */
        !           632: 
        !           633: /*
        !           634:  * For each unallocated output section:
        !           635:  *     1. Find the first free AVAIL node which can contain it
        !           636:  *     2. Allocate the OUTSECT node to the AVAIL node
        !           637:  *
        !           638:  * The list of unallocated output sections is sorted DECREASING,
        !           639:  * by section size.
        !           640:  *
        !           641:  * The list of available space is sorted INCREASING, on the size of
        !           642:  * the space
        !           643:  */
        !           644: 
        !           645:        for( usi = 0; usl[usi]; usi++ ) {
        !           646: 
        !           647:                usp = usl[usi];
        !           648: 
        !           649:                for( ani = 0; anl[ani]; ani++ )
        !           650:                        if( anl[ani]->adsize >=
        !           651:                            (alignment(usp->osalign, anl[ani]->adpaddr)
        !           652:                            + usp->oshdr.s_size) )
        !           653:                                break;
        !           654: 
        !           655:                if(anl[ani] == NULL) {
        !           656:                        lderror(1,0,NULL, "can't allocate output section %.8s, of size %10.1lx",
        !           657:                                usp->oshdr.s_name, usp->oshdr.s_size);
        !           658:                        continue;
        !           659:                        }
        !           660: 
        !           661:                new_node = (anl[ani]->adsize != usp->oshdr.s_size);
        !           662:                ap3 = anl[ani]->adnext;
        !           663:                if( ! can_alloc(anl[ani], anl[ani], usp, &ap1, &ap2)) {
        !           664:                                lderror(2,0,NULL, "internal error: in allocate lists, list confusion (%d %d)",
        !           665:                                        usi, ani);
        !           666:                                dump_mem();
        !           667:                                }
        !           668:                do_alloc(ap1, ap2, usp);
        !           669: 
        !           670:                if(new_node) {
        !           671:                        /*
        !           672:                         * If the node at anl[ani] was fragmented, then
        !           673:                         * update the anl list.  The current
        !           674:                         * AVAIL node could have generated either one 
        !           675:                         * or two smaller AVAIL nodes
        !           676:                         */
        !           677:                        if( ap1 == anl[ani] )
        !           678:                                anl[ani] = ap1->adnext;
        !           679:                        else
        !           680: #if USEREGIONS
        !           681:                                if( ap2->adnext != ap3 ) {
        !           682:                                        anl[nanl++] = ap2->adnext;
        !           683:                                        anl[nanl] = NULL;
        !           684:                                        }
        !           685:                        qsort(anl, nanl, sizeof(ap1), cmp_anl);
        !           686: #else
        !           687:                                if( ap2->adnext != ap3 ) {
        !           688:                                        for( new_node = nanl; new_node > ani; new_node-- )
        !           689:                                                anl[new_node] = anl[new_node-1];
        !           690:                                        anl[ani+1] = ap2->adnext;
        !           691:                                        anl[++nanl] = NULL;
        !           692:                                        }
        !           693: #endif
        !           694:                        }
        !           695:                else {
        !           696:                        /*
        !           697:                         * The node at anl[ani] was competely used,
        !           698:                         * so remove it from the list and move all
        !           699:                         * the other entries up one space
        !           700:                         */
        !           701:                        for( nanl--; anl[ani]; ani++ )
        !           702:                                anl[ani] = anl[ani+1];
        !           703:                        }
        !           704:                }
        !           705: 
        !           706:        return(nanl);   /* new length of available space list   */
        !           707: }
        !           708: /*eject*/
        !           709: can_alloc(sap,eap,scp,pap1,pap2)
        !           710: ANODE *sap, *eap;
        !           711: OUTSECT *scp;
        !           712: ANODE **pap1, **pap2;
        !           713: {
        !           714: 
        !           715: /*
        !           716:  * Determine if the output section pointed to by scp can fit
        !           717:  * somewhere between sap and eap.
        !           718:  *
        !           719:  * If it can, pap1 and pap2 are given the subrange start and end,
        !           720:  * and 1 is returned. Otherwise 0 is returned
        !           721:  */
        !           722: 
        !           723:        ADDRESS disp,           /* alignment */
        !           724:                have,           /* last address allocated */
        !           725:                need;           /* final needed allocation */
        !           726:        register ANODE *ap1, *ap2;      /* working pointers     */
        !           727:        ANODE *splitnode(),
        !           728:                *newnode();
        !           729:        short   success;
        !           730: 
        !           731:        success = 0;
        !           732:        ap2=sap;
        !           733:        while(!success) {
        !           734:                ap1 = ap2;
        !           735:                while(! (ap1->adtype == ADAVAIL && (ap1->adregp != NULL || reglist.head == NULL)) )
        !           736:                        if( ap1 == eap )
        !           737:                                return(0);
        !           738:                        else
        !           739:                                ap1=ap1->adnext;
        !           740:                disp=alignment(scp->osalign,ap1->adpaddr);
        !           741:                have = ap1->adsize + ap1->adpaddr;
        !           742:                need = ap1->adpaddr + disp + scp->oshdr.s_size;
        !           743:                ap2 = ap1;
        !           744:                while ( need > have ) {
        !           745:                        if(ap2 == eap)
        !           746:                                return(0);
        !           747:                        ap2 = ap2->adnext;
        !           748:                        
        !           749:                        if(ap2->adtype != ADAVAIL)
        !           750:                                break;
        !           751: 
        !           752:                        if(ap2->adprev->adpaddr+ap2->adprev->adsize != ap2->adpaddr)
        !           753:                                break;
        !           754: 
        !           755:                        if(ap2->adregp==NULL && reglist.head != NULL )
        !           756:                                break;
        !           757:                        have += ap2->adsize;
        !           758:                        }
        !           759:                if ( have >= need )
        !           760:                        success = 1;
        !           761:                }
        !           762: 
        !           763: /*
        !           764:  * To reach this point, success must have been achieved
        !           765:  */
        !           766: 
        !           767:        if ( disp != 0L ) {
        !           768:                /*
        !           769:                 * Split the node because of alignment
        !           770:                 */
        !           771:                ANODE *newap;
        !           772:                newap = splitnode(ap1,ap1->adpaddr+disp);
        !           773:                if(ap1 == ap2)
        !           774:                        ap2 = newap;
        !           775:                ap1 = newap;
        !           776:                }
        !           777:        if ( have > need ) {
        !           778:                /*
        !           779:                 * If ending in the middle of a node, split the node
        !           780:                 */
        !           781:                ANODE *newap;
        !           782:                newap = splitnode(ap2,need);
        !           783:                }
        !           784: 
        !           785:        *pap1 = ap1;    /* output parameters */
        !           786:        *pap2 = ap2;
        !           787: 
        !           788:        return(1);
        !           789: }
        !           790: /*eject*/
        !           791: ANODE *
        !           792: splitnode(ap,addr)
        !           793: ANODE *ap;
        !           794: ADDRESS addr;
        !           795: {
        !           796:        register ANODE *newap;
        !           797:        ANODE *newnode();
        !           798: 
        !           799:        newap = newnode();
        !           800: 
        !           801:        copynode(newap,ap);
        !           802: 
        !           803:        if( ap->adnext != NULL )
        !           804:                ap->adnext->adprev = newap;
        !           805:        newap->adprev = ap;
        !           806:        ap->adnext = newap;
        !           807: 
        !           808:        ap->adsize = addr - ap->adpaddr;
        !           809:        newap->adsize -= ap->adsize;
        !           810:        newap->adpaddr = addr;
        !           811: 
        !           812:        if( (ANODE *) avlist.tail == ap )
        !           813:                avlist.tail = (char *) newap;
        !           814: 
        !           815:        if( ap->admemp->mtaddrtl == ap )
        !           816:                ap->admemp->mtaddrtl = newap;
        !           817:        if( (ap->adregp != NULL)  &&  (ap->adregp->rgaddrtl == ap) )
        !           818:                ap->adregp->rgaddrtl = newap;
        !           819: 
        !           820:        return(newap);
        !           821: }
        !           822: /*eject*/
        !           823: do_alloc(ap1,ap2,scp)
        !           824: ANODE *ap1, *ap2;
        !           825: OUTSECT *scp;
        !           826: {
        !           827:        register ANODE *ap;
        !           828: 
        !           829:        for( ap = ap1; ap != ap2->adnext; ap = ap->adnext ) {
        !           830:                ap->adtype = ADSECT;
        !           831:                ap->adscnptr = scp;
        !           832:                }
        !           833: 
        !           834:        scp->oshdr.s_paddr = ap1->adpaddr;
        !           835: }
        !           836: /*eject*/
        !           837: ANODE *
        !           838: findnode(adr,flg)
        !           839: ADDRESS adr;
        !           840: int flg;
        !           841: {
        !           842: 
        !           843: /*
        !           844:  * "flg" is used if the adr falls between two nodes.
        !           845:  *     flg == 1: return next node,
        !           846:  *     flg == 0: return prev node.
        !           847:  */
        !           848: 
        !           849:        register ANODE *ap;
        !           850: 
        !           851:        for( ap = (ANODE *) avlist.head; ap != NULL; ap = ap->adnext ) {
        !           852: 
        !           853:                if(ap->adpaddr > adr)
        !           854:                        /*
        !           855:                         * adr is between nodes
        !           856:                         */
        !           857:                        if( flg )
        !           858:                                return(ap);
        !           859:                        else
        !           860:                                return(ap->adprev);
        !           861: 
        !           862:                if( ap->adpaddr+ap->adsize > adr )
        !           863:                        /*
        !           864:                         * adr is within a node
        !           865:                         */
        !           866:                        return(ap);
        !           867: 
        !           868:                }
        !           869: 
        !           870:        /*
        !           871:         * adr is outside all configured memory
        !           872:         */
        !           873: 
        !           874:        return((ANODE *) -1);
        !           875: }
        !           876: /*eject*/
        !           877: cmp_anl(p1,p2)
        !           878: ANODE **p1, **p2;
        !           879: {
        !           880: 
        !           881: /*
        !           882:  * Compare two ANODEs, returning:
        !           883:  *
        !           884:  *     -1      when p1 <  p2
        !           885:  *      0      when p1 == p2
        !           886:  *     +1      when p1 >  p2
        !           887:  *
        !           888:  * The adsize field is used for the comparison
        !           889:  */
        !           890: 
        !           891:        if( (*p1)->adsize <  (*p2)->adsize ) return(-1);
        !           892: 
        !           893:        if( (*p1)->adsize == (*p2)->adsize ) return(0);
        !           894: 
        !           895:        return(1);
        !           896: }
        !           897: 
        !           898: 
        !           899: 
        !           900: 
        !           901: 
        !           902: cmp_uos(p1,p2)
        !           903: OUTSECT **p1, **p2;
        !           904: {
        !           905: 
        !           906: /*
        !           907:  * Compare two OUTSECT nodes, returning:
        !           908:  *
        !           909:  *     +1      when p1 <  p2
        !           910:  *      0      when p1 == p2
        !           911:  *     -1      when p1 >  p2
        !           912:  *
        !           913:  * The oshdr.s_size field is used for the comparison
        !           914:  */
        !           915: 
        !           916:        if( (*p1)->oshdr.s_size < (*p2)->oshdr.s_size ) return(1);
        !           917: 
        !           918:        if( (*p1)->oshdr.s_size == (*p2)->oshdr.s_size ) return(0);
        !           919: 
        !           920:        return(-1);
        !           921: }
        !           922: /*eject*/
        !           923: ANODE *
        !           924: newnode()
        !           925: {
        !           926: 
        !           927: /*
        !           928:  * Return a blanked out node
        !           929:  */
        !           930: 
        !           931:        register ANODE *ap;
        !           932: 
        !           933:        ap = (ANODE *) myalloc(sizeof(ANODE));
        !           934: 
        !           935:        ap->adtype = ADAVAIL;
        !           936: 
        !           937:        return(ap);
        !           938: }
        !           939: 
        !           940: 
        !           941: 
        !           942: 
        !           943: 
        !           944: copynode(new,old)
        !           945: ANODE *new, *old;
        !           946: {
        !           947:        new->adnext = old->adnext;
        !           948:        new->adprev = old->adprev;
        !           949:        new->adpaddr = old->adpaddr;
        !           950:        new->adsize = old->adsize;
        !           951:        new->admemp = old->admemp;
        !           952:        new->adregp = old->adregp;
        !           953:        new->adscnptr = old->adscnptr;
        !           954:        new->adtype = old->adtype;
        !           955: }
        !           956: /*eject*/
        !           957: long
        !           958: alignment(align,paddr)
        !           959: ADDRESS align ;        /* this will be a power or two */
        !           960: ADDRESS paddr;
        !           961: {
        !           962:        register ADDRESS l;
        !           963: 
        !           964:        if ( align <= 1 )
        !           965:                return(0);
        !           966: 
        !           967:        l = (paddr + (align - 1)) & ~(align - 1);
        !           968: 
        !           969:        return(l - paddr);
        !           970: }
        !           971: /*eject*/
        !           972: creatsym(name,value)
        !           973: char *name;
        !           974: long value;
        !           975: {
        !           976: 
        !           977: /*
        !           978:  * Generate a special ld-define symbol. The name of the symbol is
        !           979:  * pointed to by 'name', and its value is given by 'value'
        !           980:  *
        !           981:  * Such a symbol is defined to have a basic symbol type of T_NULL
        !           982:  */
        !           983: 
        !           984:        register SYMTAB *p;
        !           985:        SYMENT q;
        !           986: 
        !           987: /*
        !           988:  * Special symbols are generated only under the "-a" flag
        !           989:  */
        !           990: 
        !           991:        if( ! aflag )
        !           992:                return;
        !           993: 
        !           994:        if( (p = (SYMTAB *) findsym(name)) == NULL ) {
        !           995:                /*
        !           996:                 * Case 1: This is the first time the special symbol
        !           997:                 *              has been encountered
        !           998:                 */
        !           999:                zero(&q, SYMESZ);
        !          1000: #if FLEXNAMES
        !          1001:                if (strlen(name) > 8) {
        !          1002:                        q.n_zeroes = 0L;
        !          1003:                        q.n_nptr = name;
        !          1004:                        }
        !          1005:                else
        !          1006: #endif
        !          1007:                        copy(q.n_name, name, 8);
        !          1008:                q.n_sclass = C_EXT;
        !          1009:                q.n_scnum = -1;         /* for absolute symbol */
        !          1010:                q.n_value = value;
        !          1011:                q.n_type = T_NULL;
        !          1012:                p = makesym(&q, NULL);
        !          1013:                }
        !          1014:        else if( p->sment.n_scnum == 0 ) {
        !          1015:                /*
        !          1016:                 * Case 2: The special symbol has been previously
        !          1017:                 *              referenced but not defined
        !          1018:                 */
        !          1019:                p->sment.n_sclass = C_EXT;
        !          1020:                p->sment.n_scnum = -1;
        !          1021:                p->sment.n_value = value;
        !          1022:                p->sment.n_type = T_NULL;
        !          1023:                }
        !          1024: 
        !          1025:        if( p->sment.n_scnum == -1 )
        !          1026:                p->smnewval = p->sment.n_value;
        !          1027: 
        !          1028:        PUTSYM(p, 1);
        !          1029: }

unix.superglobalmegacorp.com

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