|
|
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.