Annotation of researchv9/jerq/sgs/ld/alloc.c, revision 1.1.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.