|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.