|
|
1.1 root 1: static char ID[] = "@(#) ld2.c: 1.16 12/1/83";
2: #include "system.h"
3:
4: #include <stdio.h>
5: #include "reloc.h"
6: #include "linenum.h"
7: #include "structs.h"
8: #include "y.tab.h"
9:
10: #if TRVEC
11: #include "tv.h"
12: #include "ldtv.h"
13: #endif
14:
15: #include "extrns.h"
16: #include "list.h"
17: #include "params.h"
18: #include "sgsmacros.h"
19: #include "patch.h"
20:
21:
22: #define BASIC_TYPES (STYP_TEXT | STYP_DATA | STYP_BSS)
23: #define K8 0x2000L
24: static ITEMID dotacid;
25: static OUTSECT *dotosptr;
26: /*eject*/
27: pboslist()
28: {
29:
30: /*
31: * Process the BLDOUTSC List
32: */
33:
34: register OUTSECT *osptr;
35: register INSECT *insptr;
36: register INFILE *inflptr;
37: #if !ONEPROC
38: ACTITEM a;
39: #endif
40: OUTSECT *dfn_scn_grp();
41: long check_sect();
42:
43:
44: /*
45: * Process the list of output sections. Output sections can be
46: * defined in two places:
47: *
48: * 1. PASS 1: user-supplied; bldcnt will be > 0, and the bldoutsc
49: * list head will be NULL
50: * 2. PASS 2: default-generation; bldcnt will be 0, and the
51: * bldoutsc list will describe the output
52: * sections
53: *
54: * These two uses are mutually exclusive
55: */
56:
57: #if DEBUG
58: if( dflag > 2 )
59: fprintf( stderr, "\nBLDOSCN data structures:" );
60: #endif
61: #if !ONEPROC
62: while( bldcnt-- ) {
63:
64: fread( &a, 1, sizeof(ACTITEM), trnfdes );
65: a.dfnscn.aiinflnm = (char *) ((int) a.dfnscn.aiinflnm + (int) strbase);
66:
67: osptr = dfn_scn_grp(&a, 0);
68: copy(osptr->oshdr.s_name, a.dfnscn.ainame, 8);
69: #if TRVEC
70: /*
71: * User can define attributes of TV in two ways:
72: * (1) using TV { } directive
73: * (2) using SECTIONS { .tv : {} } directive
74: * so force them to agree
75: */
76: if ( equal(a.dfnscn.ainame, _TV, 8) ) { /* defining .tv */
77: if ( tvspec.tvbndadr == -1L )
78: tvspec.tvbndadr = a.dfnscn.aibndadr;
79: else
80: a.dfnscn.aibndadr = tvspec.tvbndadr;
81: }
82: #endif
83: if( a.dfnscn.aitype == AIDFNSCN )
84: numoutsc++;
85:
86: osptr->oshdr.s_paddr = -1L;
87: listadd(l_OS, &outsclst, osptr);
88: }
89: #endif
90:
91: /*
92: * We now know everything there is to know about the
93: * transfer vector:
94: * At the end of ploadfil(), we knew how big it
95: * had to be.
96: * Here we know whether it was defined by ld or
97: * whether it is defined by .tv input sections
98: * together with a .tv SECTION directive
99: * Go check everything and complete tvspec definition.
100: */
101:
102: #if TRVEC
103: if ( tvflag )
104: tvupdat(); /* update definition of tv */
105: #endif
106:
107: if( bldoutsc.head ) {
108: register ACTITEM *aptr, *a2ptr;
109:
110: aptr = (ACTITEM *) bldoutsc.head;
111: while( aptr ) {
112:
113: osptr = dfn_scn_grp(aptr, 1);
114:
115: copy(osptr->oshdr.s_name, aptr->dfnscn.ainame, 8);
116: if( aptr->dfnscn.aitype == AIDFNSCN )
117: numoutsc++;
118:
119: osptr->oshdr.s_paddr = -1L;
120: listadd(l_OS, &outsclst, osptr);
121:
122: a2ptr = aptr;
123: aptr = aptr->dfnscn.ainext;
124: free( (char *) a2ptr);
125: }
126: }
127:
128: /*
129: * Make sure all input sections are allocated
130: * into some output section.
131: */
132:
133: for( inflptr = (INFILE *) infilist.head; inflptr; inflptr = inflptr->flnext ) {
134: for( insptr = inflptr->flishead; insptr; insptr=insptr->isnext ) {
135: if (insptr->isoutsec <= 0) {
136: if ((osptr = fndoutsec(insptr->ishdr.s_name)) != NULL)
137: inscadd(insptr,osptr);
138: else {
139: osptr = (OUTSECT *) myalloc(sizeof(OUTSECT));
140: numoutsc++;
141: copy(osptr->oshdr.s_name, insptr->ishdr.s_name, 8);
142: osptr->osfill = globfill;
143: osptr->oshdr.s_paddr = -1l;
144: listadd(l_OS,&outsclst,osptr);
145: inscadd(insptr,osptr);
146: }
147: }
148: }
149: }
150:
151: /*
152: * for each output section, check the flags, and for a group,
153: * check the size.
154: */
155:
156: for( osptr = (OUTSECT *) outsclst.head; osptr; osptr = osptr->osnext )
157: {
158: #if PAGING
159: ACTITEM *aptr;
160: ADDRESS textbegin, textsize;
161: textbegin = hflag + FILHSZ + SCNHSZ * numoutsc + memorg;
162: #endif
163: if (osptr->oshdr.s_flags & STYP_GROUP) {
164: OUTSECT *op;
165: for( op = ((OUTSECT *) osptr->osinclhd); op; op = op->osnext ) {
166: #if PAGING
167: if (bond_t_d && !Nflag && equal(op->oshdr.s_name,_DATA,8)) {
168: osptr->osalign = 0L;
169: aptr = (ACTITEM *) myalloc(sizeof(ACTITEM));
170: aptr->bond.aitype = AIBOND;
171: aptr->bond.aiinflnm = "*default.bond.file*";
172: aptr->bond.aiinlnno = 3;
173: aptr->bond.aioutsec = osptr;
174: aptr->bond.aiadrbnd = ((textsize + textbegin) / BOUNDARY + 1)
175: * BOUNDARY + (textsize + textbegin) % K8;
176: listadd(l_AI,&bondlist,aptr);
177: }
178: #endif
179: osptr->oshdr.s_size += check_sect( op );
180: }
181: if (osptr->oshdr.s_size > MAXSCNSIZE)
182: lderror(1,0,NULL, "GROUP containing section %.8s is too big",
183: osptr->osinclhd->ishdr.s_name);
184: } else {
185: #if PAGING
186: if (bond_t_d && !Nflag && equal(osptr->oshdr.s_name,_TEXT,8)) {
187: textsize = osptr->oshdr.s_size;
188: aptr = (ACTITEM *) myalloc(sizeof(ACTITEM));
189: aptr->bond.aitype = AIBOND;
190: aptr->bond.aiinflnm = "*default.bond.file*";
191: aptr->bond.aiinlnno = 2;
192: aptr->bond.aioutsec = osptr;
193: aptr->bond.aiadrbnd = textbegin;
194: listadd(l_AI,&bondlist,aptr);
195: }
196: #endif
197: check_sect( osptr );
198: }
199: }
200:
201: /*
202: * If .tv is user-defined, we now know the true size of
203: * the section ( the sum of the sizes of the input
204: * sections) which we didn't know before. Now call the
205: * the final update routine to insure .tv symtab entry
206: * is correct
207: */
208:
209: #if TRVEC
210: if ( tvflag )
211: tvupdt2(); /* final update of tvrange and tvlength */
212: #endif
213:
214: #if DEBUG
215: if (dflag)
216: dmp_outsects();
217: #endif
218: }
219: /*eject*/
220: OUTSECT *
221: dfn_scn_grp(aptr, dflt)
222:
223: ACTITEM *aptr; /* DFNSCN or DFNGRP entry */
224: int dflt; /* user-supplied or ld-default entry */
225: {
226:
227: /*
228: * Process one AIDFNSCN or AIDFNGRP data structure from
229: * the list of output sections
230: */
231:
232: OUTSECT *osptr, *op;
233: INFILE *inflptr;
234: INSECT *insptr;
235: ENODE *ep;
236: long val;
237: int fill, fillflag;
238: ACTITEM *a2ptr;
239: #if !ONEPROC
240: ACTITEM b;
241: #endif
242:
243: #if DEBUG
244: if( dflag > 2 )
245: fprintf( stderr, "\n\t%04x %s (%s) %d (%s) %04x (%s)\n\t\t%08lx %d %08lx %08lx %d %d (%04x,%04x)",
246: aptr->dfnscn.ainext,
247: (aptr->dfnscn.aitype == AIDFNSCN) ? "AIDFNSCN" : "AIDFNGRP",
248: aptr->dfnscn.aiinflnm,
249: aptr->dfnscn.aiinlnno, aptr->dfnscn.ainame, aptr->dfnscn.aifill,
250: aptr->dfnscn.aiowname, aptr->dfnscn.aibndadr, aptr->dfnscn.aiattown,
251: aptr->dfnscn.aialign, aptr->dfnscn.aiblock, (unsigned) aptr->dfnscn.aifillfg,
252: (unsigned) aptr->dfnscn.aisctype, aptr->dfnscn.sectspec.head, aptr->dfnscn.sectspec.tail );
253: #endif
254:
255: osptr = (OUTSECT *) myalloc(sizeof(OUTSECT));
256: if (aptr->dfnscn.aibndadr != -1L) { /* section bonded */
257: a2ptr = (ACTITEM *) myalloc(sizeof(ACTITEM));
258: a2ptr->bond.aitype = AIBOND;
259: a2ptr->bond.aiinflnm = aptr->dfnscn.aiinflnm;
260: a2ptr->bond.aiinlnno = aptr->dfnscn.aiinlnno;
261: a2ptr->bond.aioutsec = osptr;
262: a2ptr->bond.aiadrbnd = aptr->dfnscn.aibndadr;
263: listadd(l_AI,&bondlist,a2ptr);
264: }
265: else if (aptr->dfnscn.aiowname[0] != '\0') { /*owner specified */
266: a2ptr = (ACTITEM *) myalloc(sizeof(ACTITEM));
267: a2ptr->dfownr.aitype = AIDFOWNR;
268: a2ptr->dfownr.aiinflnm = aptr->dfnscn.aiinflnm;
269: a2ptr->dfownr.aiinlnno = aptr->dfnscn.aiinlnno;
270: a2ptr->dfownr.aioutsec = osptr;
271: copy(a2ptr->dfownr.ainamown, aptr->dfnscn.aiowname, 8);
272: listadd(l_AI,&ownlist,a2ptr);
273: }
274: else if (aptr->dfnscn.aiattown != 0) { /* attr of owner */
275: a2ptr = (ACTITEM *) myalloc(sizeof(ACTITEM));
276: a2ptr->ownatr.aitype = AIOWNATR;
277: a2ptr->ownatr.aiinflnm = aptr->dfnscn.aiinflnm;
278: a2ptr->ownatr.aiinlnno = aptr->dfnscn.aiinlnno;
279: a2ptr->ownatr.aioutsec = osptr;
280: a2ptr->ownatr.aiownatt = aptr->dfnscn.aiattown;
281: listadd(l_AI,&atownlst,a2ptr);
282: }
283:
284: if (aptr->dfnscn.aitype == AIDFNGRP)
285: osptr->oshdr.s_flags = STYP_GROUP;
286: else
287: osptr->oshdr.s_flags = aptr->dfnscn.aisctype;
288: osptr->osalign = aptr->dfnscn.aialign;
289: osptr->osblock = aptr->dfnscn.aiblock;
290: osptr->osfill = aptr->dfnscn.aifill;
291: osptr->osflags |= aptr->dfnscn.aifillfg;
292:
293: /*
294: * A DFNSCN need have no subordinate entries, since the following is
295: * legal:
296: * .text : {}
297: */
298:
299: if( aptr->dfnscn.sectspec.head == NULL )
300: return( osptr );
301:
302: /*
303: * A DFNGRP is a sequence of one or more DFNSCN entries
304: */
305:
306: if( aptr->dfnscn.aitype == AIDFNGRP ) {
307: a2ptr = (ACTITEM *) aptr->dfnscn.sectspec.head;
308: do {
309: if( ! dflt ) {
310: #if !ONEPROC
311: fread( &b, 1, sizeof(ACTITEM), trnfdes );
312: b.dfnscn.aiinflnm = (char *) ((int) b.dfnscn.aiinflnm + (int) strbase);
313: a2ptr = &b;
314: #endif
315: }
316:
317: op = dfn_scn_grp(a2ptr, dflt);
318:
319: op->oshdr.s_paddr = -1L;
320: listadd(l_GRP, osptr, op);
321: numoutsc++;
322: copy(op->oshdr.s_name, a2ptr->dfnscn.ainame, 8);
323:
324: if( (a2ptr = a2ptr->dfnscn.ainext) == NULL )
325: return( osptr );
326: }
327: while( 1 );
328: }
329:
330: /*
331: * Process a DFNSCN with one or more subordinate entries, of type
332: * AIADFILE, AIADDSCN, or AIEVEXPR
333: */
334:
335: a2ptr = (ACTITEM *) aptr->dfnscn.sectspec.head;
336: do {
337: if( ! dflt ) {
338: #if !ONEPROC
339: fread( &b, 1, sizeof(ACTITEM), trnfdes );
340: b.adfile.aiinflnm = (char *) ((int) b.adfile.aiinflnm + (int) strbase);
341: a2ptr = &b;
342: #endif
343: }
344:
345: switch( a2ptr->adfile.aitype ) {
346:
347: case AIADFILE:
348:
349: if( ! dflt )
350: a2ptr->adfile.aifilnam = (char *) ((int) a2ptr->adfile.aifilnam + (int) strbase);
351:
352: #if DEBUG
353: if( dflag > 2 )
354: fprintf( stderr, "\n\t%04x AIADFILE (%s) %d (%s) %d %d %d",
355: a2ptr->adfile.ainext, a2ptr->adfile.aiinflnm,
356: a2ptr->adfile.aiinlnno, a2ptr->adfile.aifilnam, a2ptr->adfile.ainadscs,
357: a2ptr->adfile.aifill2, (unsigned) a2ptr->adfile.aifilflg );
358: #endif
359:
360: if( (inflptr = fndinfil(a2ptr->adfile.aifilnam)) == NULL )
361: break;
362: if( a2ptr->adfile.ainadscs == 0 ) {
363: insptr = inflptr->flishead;
364: while( insptr ) {
365: if( insptr->isoutsec == NULL ) {
366: inscadd(insptr, osptr);
367: insptr->isfill = a2ptr->adfile.aifill2;
368: insptr->isfillfg = a2ptr->adfile.aifilflg;
369: }
370: insptr = insptr->isnext;
371: /*
372: * In case inflptr is library,
373: * get next one
374: */
375: if( (insptr == NULL) && (inflptr->flfiloff > 0L) )
376: while( (inflptr = inflptr->flnext) )
377: if (strcmp(a2ptr->adfile.aifilnam,inflptr->flname) == 0) {
378: insptr = inflptr->flishead;
379: break;
380: }
381: }
382: }
383: else {
384: fill = a2ptr->adfile.aifill2;
385: fillflag = a2ptr->adfile.aifilflg;
386: }
387: break;
388:
389: case AIADDSCN:
390:
391: if( ! dflt )
392: a2ptr->addscn.aiscfile = (char *) ((int) a2ptr->addscn.aiscfile + (int) strbase);
393:
394: #if DEBUG
395: if( dflag > 2 )
396: fprintf( stderr, "\n\t%04x AIADDSCN (%s) %d (%s) %04x (%s)",
397: a2ptr->addscn.ainext, a2ptr->addscn.aiinflnm,
398: a2ptr->addscn.aiinlnno, a2ptr->addscn.ainame, a2ptr->addscn.aifill,
399: a2ptr->addscn.aiscfile );
400: #endif
401:
402: if( (inflptr = fndinfil(a2ptr->addscn.aiscfile)) == NULL )
403: break;
404: insptr = inflptr->flishead;
405: while(insptr) {
406: if (equal(a2ptr->addscn.ainame,insptr->ishdr.s_name,8)) {
407: if (insptr->isoutsec) {
408: lderror(1, a2ptr->addscn.aiinlnno, a2ptr->addscn.aiinflnm,
409: "adding %s(%.8s) to multiple output sections",
410: inflptr->flname,
411: insptr->ishdr.s_name);
412: goto contin1;
413: }
414: inscadd(insptr,osptr);
415: insptr->isfill = fill;
416: insptr->isfillfg = fillflag;
417: insptr = NULL;
418: if (inflptr->flfiloff > 0L)
419: /*
420: * In case inflptr is library,
421: * get next one
422: */
423: while( (inflptr = inflptr->flnext) )
424: if (strcmp(a2ptr->addscn.aiscfile,inflptr->flname) == 0) {
425: insptr = inflptr->flishead;
426: break;
427: }
428: if ( insptr != NULL )
429: continue;
430: else
431: goto contin1;
432: }
433: insptr = insptr->isnext;
434: }
435: lderror(1, a2ptr->addscn.aiinlnno, a2ptr->addscn.aiinflnm,
436: "%s(%.8s) not found",
437: a2ptr->addscn.aiscfile,a2ptr->addscn.ainame);
438: break;
439:
440: case AIEVEXPR:
441:
442: #if DEBUG
443: if( dflag > 2 )
444: fprintf( stderr, "\n\t%04x AIEVEXPR (%s) %d %04x\n\t\tROOT:",
445: a2ptr->evexpr.ainext, a2ptr->evexpr.aiinflnm,
446: a2ptr->evexpr.aiinlnno, a2ptr->evexpr.aiexptr );
447: #endif
448:
449: #if ONEPROC
450: aptr = a2ptr;
451: #else
452: aptr = ldexp( &b );
453: #endif
454:
455: a2ptr = a2ptr->adfile.ainext;
456: ep = aptr->evexpr.aiexptr;
457: cur_dot = osptr->oshdr.s_size;
458:
459: if (ep->gnode.exleft->gnode.exop != DOT) {
460: /*
461: * LHS of assnment is regular symbol
462: */
463: dotacid = 0;
464: dotosptr = osptr;
465: chgdot(ep->gnode.exright);
466: listadd(l_AI, &explist, aptr);
467: }
468: else {
469: /*
470: * LHS is DOT symbol
471: */
472: curexp = aptr;
473: val = eval(ep->gnode.exright);
474: if (val < cur_dot)
475: lderror(1, aptr->evexpr.aiinlnno, aptr->evexpr.aiinflnm,
476: "attempt to decrement DOT");
477: else
478: osptr->oshdr.s_size = val;
479:
480: clrexp( aptr );
481: }
482: goto contin2;
483: }
484:
485: contin1:
486: a2ptr = a2ptr->adfile.ainext;
487: contin2:
488: if (a2ptr == NULL)
489: return( osptr );
490:
491: }
492: while( 1 );
493: }
494: /*eject*/
495: inscadd(pin,pout)
496: INSECT *pin;
497: OUTSECT *pout;
498: {
499:
500: /*
501: * Add an input section to an output section.
502: *
503: * The text, relocation, and lineno info of the input section
504: * are allocated at the end of the output section.
505: */
506:
507: long btype;
508:
509: pin->isoutsec = pout;
510: pin->isdispl = pout->oshdr.s_size;
511: pin->islndisp = ((long) pout->oshdr.s_nlnno * (long) LINESZ);
512: pout->oshdr.s_size += pin->ishdr.s_size;
513: pout->oshdr.s_nlnno += pin->ishdr.s_nlnno;
514:
515: if (rflag) {
516: pin->isrldisp = ((long) pout->oshdr.s_nreloc * (long) RELSZ);
517: pout->oshdr.s_nreloc += pin->ishdr.s_nreloc;
518: }
519:
520: btype = pin->ishdr.s_flags & BASIC_TYPES;
521: if (btype)
522: pout->oshdr.s_flags |= btype;
523: else if ( equal( _TEXT, pin->ishdr.s_name, 8 ))
524: pout->oshdr.s_flags |= STYP_TEXT;
525: else if ( equal( _DATA, pin->ishdr.s_name, 8 ))
526: pout->oshdr.s_flags |= STYP_DATA;
527: else if ( equal( _BSS, pin->ishdr.s_name, 8 ))
528: pout->oshdr.s_flags |= STYP_BSS;
529:
530: pout->osflags |= (pin->ishdr.s_flags & STYP_DSECT) ? OSDSECT : OSREG;
531: if (pin->ishdr.s_flags & STYP_INFO)
532: pout->osflags |= OSINFO;
533: if (pin->ishdr.s_flags & STYP_COPY)
534: pout->osflags |= OSCOPY;
535:
536: listadd(l_INC,pout,pin);
537: }
538: /*eject*/
539: INFILE *
540: fndinfil(fnam)
541: char *fnam;
542: {
543:
544: /*
545: * Locate the input file structure by a given name, and
546: * return a pointer to the structure.
547: *
548: * Note: fnam must be a null terminated string.
549: */
550:
551: register INFILE *p;
552:
553: p = (INFILE *) infilist.head;
554: while (p) {
555: if (strcmp(fnam,p->flname) == 0)
556: return(p);
557: p = p->flnext;
558: }
559:
560: return(NULL);
561: }
562: /*eject*/
563: chgdot(p)
564: ENODE *p;
565: {
566: register SYMTAB *sym;
567: ITEMID add_dot();
568:
569: /*
570: * This function is called when an assignment is encountered
571: * within an output section specification, and the LHS of the
572: * assnment is to a symbol other than DOT. Any occurances of
573: * DOT within the RHS expression must be replaced by a reference
574: * to a dummy symbol table entry, which will have the correct
575: * value after the output section is relocated.
576: */
577:
578: switch(p->gnode.exop) {
579: case DOT:
580: if( dotacid == 0 )
581: dotacid = add_dot(cur_dot, dotosptr);
582: p->nnode.exsymptr = dotacid;
583: break;
584: case NAME:
585: case INT:
586: break;
587: default:
588: if (p->gnode.exleft)
589: chgdot(p->gnode.exleft);
590: if (p->gnode.exright)
591: chgdot(p->gnode.exright);
592: }
593: }
594: /*eject*/
595: add_pad()
596: {
597:
598: /*
599: * If the "-B" flag was specified, add any necessary "padding sections"
600: * to the outpt file
601: */
602:
603: register ANODE *ap; /* ptr into avlist */
604: ANODE *newap; /* ptr to padding section node */
605: register OUTSECT *osp;
606: register INSECT *isp;
607: int no_need_pad, /* = 1 iff don't need padding */
608: counter; /* used to make unique names */
609: char padname[8]; /* padding section name */
610:
611: /*
612: * Look for an output section which meets one of two conditions:
613: *
614: * 1. The section is comprised entirely of uninitialized .bss
615: * sections
616: * 2. The section is of zero length
617: *
618: * For every output section of these types, add an additional output
619: * section immediatly after it. This "padding section" has only two
620: * non-zero/non-NULL/non-trivial characteristics:
621: * 1. It is composed of Bflag bytes of zero
622: * 2. It is written under control of BLOCK(Bflag)
623: *
624: * Note that padding sections have a virtual/physical address
625: * of -1 (to generate errors from any user program or utility
626: * attempting to use these values), and flags indicating that
627: * it is a padding section
628: */
629:
630: counter = 0;
631: for( ap = (ANODE *) avlist.head; ap; ap = ap->adnext ) {
632: if( ap->adtype != ADSECT )
633: continue;
634:
635: osp = ap->adscnptr;
636: no_need_pad = (osp->osflags & FILL);
637: for( isp = osp->osinclhd; isp; isp = isp->isincnxt )
638: if( (isp->ishdr.s_scnptr > 0) || (isp->isfillfg) )
639: no_need_pad = 1;
640: if( ap->adsize == 0L )
641: no_need_pad = 0;
642:
643: if( no_need_pad )
644: continue;
645:
646: osp = (OUTSECT *) myalloc(sizeof(OUTSECT));
647: numoutsc++;
648: sprintf( padname, "-pad%2d-", counter++ );
649: copy( osp->oshdr.s_name, padname, 8 );
650: osp->oshdr.s_paddr = -1L;
651: osp->oshdr.s_vaddr = -1L;
652: osp->oshdr.s_size = Bflag;
653: osp->oshdr.s_flags = STYP_PAD;
654: osp->osblock = Bflag;
655:
656: newap = (ANODE *) myalloc(sizeof(ANODE));
657: newap->adtype = ADPAD;
658: newap->adsize = Bflag;
659: newap->adscnptr = osp;
660:
661: listins( l_ADR, &avlist, ap, newap );
662: }
663:
664: #if DEBUG
665: if( dflag > 1 ) {
666: fprintf( stderr, "\nadd_pad" );
667: dump_mem();
668: }
669: #endif
670:
671: }
672: /*eject*/
673: updatsms()
674: {
675:
676: /*
677: * After allocation, this function sets
678: * 1. The section number of all output sections
679: * 2. The virtual addresses of all input sections (isnewvad)
680: * 3. The file offset of output sections
681: *
682: * In addition, the relocated value for all global symbols is
683: * computed and stored in the symbol table, along with the new
684: * section number.
685: *
686: * The virtual addresses of output sections are set by
687: * audit_regions in allocation.
688: */
689:
690: register SYMTAB *symp;
691: register OUTSECT *osp;
692: register INSECT *isp;
693: int snum, init;
694: long vaddr, indx;
695: long filoffst, lnnoptr, nrelocs;
696: ANODE *ap;
697: INFILE *fp;
698:
699: /*
700: * Compute the starting file offset of the first output section
701: *
702: * ********** NOTE NOTE NOTE NOTE **********
703: *
704: * Increase the size of the optional header by the amount of
705: * space needed to generate a patch list
706: *
707: * ********** NOTE NOTE NOTE NOTE **********
708: */
709:
710: hflag += psize();
711: filoffst = (long) FILHSZ + hflag + SCNHSZ * numoutsc;
712:
713: nrelocs = 0L;
714: snum = 0;
715:
716: for( ap = (ANODE *) avlist.head; ap; ap = ap->adnext ) {
717: if (ap->adtype == ADSECT) {
718: osp = ap->adscnptr;
719: /*
720: ***** Special processing *****
721: *
722: * The description of the _TV output section is
723: * changed, so as to make it equivalent to that
724: * section of the transfer vector actually used
725: * in this ld run
726: *
727: * Note that in the default case - no ASSIGN or
728: * RANGE commands, the entire transfer vector
729: * is used, and hence this code produces no
730: * change.
731: *
732: * When ASSIGN and RANGE commands are present,
733: * the actual section of the transfer vector
734: * used is typically a subset of the entire
735: * vector. Output only the piece used
736: */
737: #if TRVEC
738: if( tvflag && equal(osp->oshdr.s_name,_TV,8) ) {
739: osp->oshdr.s_paddr +=
740: (tvspec.tvrange[0] * TVENTSZ);
741: osp->oshdr.s_vaddr +=
742: (tvspec.tvrange[0] * TVENTSZ);
743: osp->oshdr.s_size =
744: ((tvspec.tvrange[1]-tvspec.tvrange[0]+1)*TVENTSZ);
745: }
746: #endif
747: init = (osp->osflags & FILL); /* section is initialized*/
748: osp->ossecnum = ++snum;
749: vaddr = osp->oshdr.s_vaddr;
750: for( isp = osp->osinclhd; isp; isp = isp->isincnxt ) {
751: isp->isnewvad = vaddr + isp->isdispl;
752: isp->isnewpad = osp->oshdr.s_paddr + isp->isdispl;
753: if (isp->ishdr.s_scnptr > 0 || isp->isfillfg)
754: init = 1;
755: }
756:
757: if ((osp->oshdr.s_flags & STYP_NOLOAD) || (osp->oshdr.s_flags & STYP_DSECT))
758: init = 0;
759: if (init) {
760: filoffst += alignment(osp->osblock,filoffst);
761: osp->oshdr.s_scnptr = filoffst;
762: filoffst += osp->oshdr.s_size;
763: if (rflag)
764: nrelocs += (long) osp->oshdr.s_nreloc;
765: if (filoffst % 2)
766: ++filoffst;
767: }
768: else
769: osp->oshdr.s_scnptr = 0L;
770: }
771: else if( ap->adtype == ADPAD ) {
772: osp = ap->adscnptr;
773: osp->ossecnum = ++snum;
774: filoffst += alignment(osp->osblock,filoffst);
775: osp->oshdr.s_scnptr = filoffst;
776: filoffst += osp->oshdr.s_size;
777: if( filoffst % 2 )
778: ++filoffst;
779: }
780: }
781:
782: /*
783: * Do the same for the "dummy" sections (DSECTS)
784: */
785:
786: for( osp = (OUTSECT *) dsectlst.head; osp; osp = osp->osdsnext ) {
787: osp->ossecnum = ++snum;
788: for( isp = osp->osinclhd; isp; isp = isp->isincnxt ) {
789: isp->isnewvad = osp->oshdr.s_vaddr + isp->isdispl;
790: isp->isnewpad = osp->oshdr.s_paddr + isp->isdispl;
791: }
792: if ( osp->oshdr.s_flags & (STYP_COPY | STYP_INFO)) {
793: filoffst += alignment(osp->osblock,filoffst);
794: osp->oshdr.s_scnptr = filoffst;
795: filoffst += osp->oshdr.s_size;
796: if ( rflag )
797: nrelocs += (long) osp->oshdr.s_nreloc;
798: if ( filoffst % 2)
799: ++filoffst;
800: } else {
801: osp->oshdr.s_nreloc = 0;
802: osp->oshdr.s_nlnno = 0;
803: }
804: }
805:
806: /*
807: * Loop through sections a 2nd time to set the
808: * file pointer to relocation and line numbers for each section
809: */
810:
811: lnnoptr = filoffst + nrelocs * (long) RELSZ;
812: for( ap = (ANODE *) avlist.head; ap; ap = ap->adnext ) {
813: if (ap->adtype == ADSECT) {
814: osp = ap->adscnptr;
815: if (osp->oshdr.s_flags & STYP_NOLOAD) {
816: osp->oshdr.s_nreloc = 0;
817: osp->oshdr.s_nlnno = 0;
818: continue;
819: }
820: if( rflag && (osp->oshdr.s_nreloc != 0) ) {
821: osp->oshdr.s_relptr = filoffst;
822: filoffst += ((long)osp->oshdr.s_nreloc *
823: (long) RELSZ);
824: }
825: #if UNIX || XL
826: if( (!sflag && !xflag) && (osp->oshdr.s_nlnno != 0) ) {
827: #else
828: if( (!sflag ) && (osp->oshdr.s_nlnno != 0) ) {
829: #endif
830: osp->oshdr.s_lnnoptr = lnnoptr;
831: lnnoptr += ((long)osp->oshdr.s_nlnno *
832: (long) LINESZ);
833: }
834: }
835: }
836:
837: /*
838: * Do the same for the "copy" sections (COPY)
839: */
840:
841: for( osp = (OUTSECT *) dsectlst.head; osp; osp = osp->osdsnext ) {
842: if ( osp->oshdr.s_flags & (STYP_COPY | STYP_INFO)) {
843: if ( rflag && (osp->oshdr.s_nreloc != 0) ) {
844: osp->oshdr.s_relptr = filoffst;
845: filoffst += ((long) osp->oshdr.s_nreloc
846: * (long) RELSZ);
847: }
848: if ( (! sflag) && (osp->oshdr.s_nlnno != 0) ) {
849: osp->oshdr.s_lnnoptr = lnnoptr;
850: lnnoptr += ((long) osp->oshdr.s_nlnno *
851: (long) LINESZ);
852: }
853: }
854: }
855:
856: symtborg = filoffst = lnnoptr;
857: fp = (INFILE *) infilist.head;
858: indx = 0;
859: while (fp) {
860: fp->flsymndx = indx;
861: indx += fp->flnlsyms;
862: fp = fp->flnext;
863: }
864:
865: symp = NULL;
866: while( (symp = loopsym(symp, 1)) != NULL ) {
867: if( symp->sment.n_scnum > 0 ) {
868: isp = symp->smscnptr;
869: symp->sment.n_scnum = isp->isoutsec->ossecnum;
870: symp->smnewval = symp->sment.n_value
871: + isp->isnewpad - isp->ishdr.s_paddr;
872: symp->smnewvirt = symp->smnewval
873: - isp->isnewpad + isp->isnewvad;
874: if( symp->smlocflg ) {
875: symp->smoutndx += isp->isfilptr->flsymndx;
876: }
877: else {
878: symp->smoutndx = indx++;
879: indx += symp->sment.n_numaux;
880: }
881: }
882: else {
883: if ((symp->sment.n_zeroes == 0) ||
884: (strncmp( symp->sment.n_name, ".dot", 4 ) != 0))
885: symp->smoutndx = indx++;
886: symp->smnewval = symp->sment.n_value;
887: symp->smnewvirt = symp->sment.n_value;
888: indx += symp->sment.n_numaux;
889: }
890: }
891: #if FLEXNAMES
892: tnumsyms = indx;
893: #endif
894: }
895: /*eject*/
896: OUTSECT *
897: findoscn(number)
898: int number; /* number of desired section */
899: {
900:
901: /*
902: * Look through the output section list, outsclst,
903: * for a section with the specified number. Return
904: * a pointer to that element of the list. If no
905: * section exists with that number, return NULL.
906: */
907:
908: register OUTSECT *osptr;
909:
910: osptr = (OUTSECT *) outsclst.head;
911: while ( osptr != NULL ) {
912: if ( osptr->ossecnum == number )
913: return (osptr);
914: osptr = osptr->osnext;
915: }
916:
917: return (NULL);
918: }
919: /*eject*/
920: split_scns()
921: {
922:
923: /*
924: * Run though the output section list. If the size of any output
925: * section is greater then MAXSCNSZ, split the output section into
926: * two (or more) output sections
927: *
928: * The name of a new section is the first char of the old name,
929: * followed by a number, followed by the rest of the old
930: * name. Only eight characters are kept.
931: */
932:
933: OUTSECT *osp, *newosp, *nxtosp;
934: INSECT *isp, *nxtisp;
935: char *oldname, newname[20]; /* 8 + 4 + extra */
936: int scnnumber;
937: long newdisp, startdisp; /* OUTSECT displacements */
938:
939: /*
940: * "osp" scans down the outsclst, and "nxtosp" will
941: * always point to the next section on the original
942: * list. If we have to split osp, the new node
943: * will be newosp, and nxtosp will not change.
944: */
945:
946: for( osp = (OUTSECT *) outsclst.head; osp; osp = nxtosp ) {
947: nxtosp = osp->osnext;
948:
949: /* begin KLUDGE */
950: adjsize(osp);
951: /* end KLUDGE */
952:
953: if (osp->oshdr.s_flags & STYP_DSECT)
954: continue;
955:
956: if( (osp->osinclhd == osp->osincltl) || (osp->oshdr.s_size <= MAXSCNSZ) ) {
957: /* Either there is only one input section in the
958: * output section, or the output section is
959: * within the permissible size
960: */
961: if( (isp = osp->osinclhd) == NULL )
962: continue;
963: if( isp->ishdr.s_size > MAXSCNSIZE ) {
964: lderror(1,0,NULL, "section %.8s in file %s too big",
965: isp->ishdr.s_name, isp->isfilptr->flname);
966: osp->osinclhd = osp->osincltl = NULL;
967: }
968: continue;
969: }
970:
971: /*
972: * An output section is too large, and must be split.
973: *
974: * Walk through the list of input sections, to build
975: * two (or more) output sections which are all within
976: * the permissible size range
977: */
978:
979: osp->oshdr.s_nreloc = 0;
980: osp->oshdr.s_nlnno = 0;
981: isp = osp->osinclhd;
982: osp->osinclhd = osp->osincltl = NULL;
983: scnnumber = 0;
984: oldname = osp->oshdr.s_name;
985:
986: newdisp = 0L;
987: if( isp != NULL )
988: startdisp = osp->oshdr.s_size = isp->isdispl;
989: else
990: startdisp = osp->oshdr.s_size = 0L;
991:
992: /*
993: * "isp" points to the current input section which we
994: * are trying to add to the output section given by
995: * "osp"
996: */
997:
998: for(; isp; isp = nxtisp ) {
999: nxtisp = isp->isincnxt;
1000: if( osp->oshdr.s_size + isp->ishdr.s_size <= MAXSCNSZ ) {
1001: newdisp = isp->isdispl - startdisp;
1002: if( osp->oshdr.s_size > newdisp )
1003: lderror(1,0, NULL,
1004: "internal error: split_scns, size of %.8s exceeds its new displacement",
1005: osp->oshdr.s_name);
1006:
1007: osp->oshdr.s_size = newdisp;
1008: isp->isincnxt = NULL;
1009: inscadd(isp, osp);
1010: }
1011: else if ( osp->oshdr.s_size != 0 ) {
1012: nxtisp = isp; /* back up to reprocess */
1013: newosp = (OUTSECT *) myalloc(sizeof(OUTSECT));
1014: numoutsc++;
1015: sprintf(newname, "%c%x%.6s", *oldname,
1016: scnnumber++, oldname + 1);
1017: copy(newosp->oshdr.s_name, newname, 8);
1018: newosp->oshdr.s_paddr = -1L;
1019: newosp->osnext = osp->osnext;
1020: osp->osnext = newosp;
1021: if( (OUTSECT *) outsclst.tail == osp )
1022: outsclst.tail = (char *) newosp;
1023: osp = newosp;
1024: newdisp = 0L;
1025: startdisp = isp->isdispl;
1026: }
1027: else if ( isp->ishdr.s_size <= MAXSCNSIZE ) {
1028: isp->isincnxt = NULL;
1029: inscadd(isp, osp);
1030: }
1031: else
1032: lderror(1,0,NULL, "section %.8s in file %s is too big",
1033: isp->ishdr.s_name, isp->isfilptr->flname);
1034: }
1035:
1036: }
1037:
1038: }
1039: /*eject*/
1040: psize()
1041: {
1042: /*
1043: * Determine the size of the patch list. This is done by looking for
1044: * all output sections having the name of ".patchnn", where nn is a
1045: * two-digit number
1046: *
1047: * This routine returns, as an int value, the size of the patch list
1048: */
1049:
1050: register int index, space;
1051: char pname[10];
1052: OUTSECT *fndoutsec();
1053:
1054: if( ! pflag )
1055: return( 0 );
1056: else
1057: space = sizeof(long);
1058:
1059: /*
1060: * Patch sections, if they exist, must be named consecutively, starting
1061: * at ".patch00"
1062: */
1063:
1064: for( index = 0; index < 100; index++ ) {
1065: if (index < 10)
1066: sprintf(pname, ".patch0%d", index);
1067: else
1068: sprintf( pname, ".patch%d", index );
1069: if( fndoutsec(pname) == NULL )
1070: break;
1071: space += PESIZE;
1072: }
1073:
1074: return( space );
1075: }
1076: /*eject*/
1077: OUTSECT *
1078: fndoutsec(nam)
1079: char *nam;
1080: {
1081: register OUTSECT *p, *q;
1082:
1083: for( p = (OUTSECT *) outsclst.head; p; p=p->osnext ) {
1084: if (p->oshdr.s_flags & STYP_GROUP)
1085: for( q = (OUTSECT *) p->osinclhd; q; q=q->osnext ) {
1086: if (equal(nam,q->oshdr.s_name,8))
1087: return(q);
1088: }
1089: else
1090: if (equal(nam,p->oshdr.s_name,8))
1091: return(p);
1092: }
1093: return(NULL);
1094: }
1095:
1096:
1097:
1098:
1099: #if ILDOPT
1100: add_extra()
1101: {
1102:
1103: /* If the "-ild" flag was specified, add sections to the output file to
1104: * cover any remaining configured memory.
1105: */
1106:
1107: register ANODE *ap, *newap; /* ptr into avlist */
1108: OUTSECT *osp1, *osp2; /* ptrs to the new output section headers */
1109: int counter; /* used to make unique names */
1110: char sectname[9]; /* new section name */
1111:
1112: /* For each remaining area of available memory, create a fake output section
1113: * that fits in that area. The purpose of this is to cover all of configured
1114: * memory so that the incremental ld will be able to determine the memory
1115: * configuration. Increase numoutsc to leave room for the .history section
1116: * header.
1117: */
1118:
1119: numoutsc++;
1120: counter = 0;
1121: for (ap = (ANODE *) avlist.head; ap; ap = ap->adnext) {
1122: if (counter > 99)
1123: break;
1124: if (ap->adtype != ADAVAIL)
1125: continue;
1126: if ( ap != (ANODE *) avlist.head && ap->adprev->adtype != ADAVAIL &&
1127: ap->adprev->adscnptr != NULL &&
1128: (ap->adprev->adscnptr->oshdr.s_flags & STYP_NOLOAD) &&
1129: ap != (ANODE *) avlist.tail && ap->adnext->adtype != ADAVAIL &&
1130: ap->adnext->adscnptr != NULL &&
1131: (ap->adnext->adscnptr->oshdr.s_flags & STYP_NOLOAD) )
1132: continue;
1133:
1134: ap->adtype = ADSECT;
1135: newap = (ANODE *) myalloc( sizeof(ANODE) + 2 * sizeof(OUTSECT));
1136: osp1 = (OUTSECT *) (newap + 1);
1137: osp2 = osp1 + 1;
1138: numoutsc += 2;
1139: if (counter < 10)
1140: sprintf(sectname, ".i_l_d0%d", counter++);
1141: else
1142: sprintf( sectname, ".i_l_d%d", counter++);
1143: copy( osp1->oshdr.s_name, sectname, 8 );
1144: osp1->oshdr.s_flags = STYP_DSECT;
1145: ap->adscnptr = osp1;
1146:
1147: if (counter < 10)
1148: sprintf( sectname, ".i_l_d0%d", counter++);
1149: else
1150: sprintf( sectname, ".i_l_d%d", counter++ );
1151: copy( osp2->oshdr.s_name, sectname, 8 );
1152: osp2->oshdr.s_paddr = ap->adpaddr;
1153: osp2->oshdr.s_vaddr = ap->adpaddr;
1154: osp2->oshdr.s_size = ap->adsize;
1155: osp2->oshdr.s_flags = STYP_DSECT;
1156: osp2->osflags = 0;
1157:
1158: newap->adtype = ADSECT;
1159: newap->adpaddr = ap->adpaddr;
1160: newap->adsize = ap->adsize;
1161: newap->adscnptr = osp2;
1162: newap->admemp = ap->admemp;
1163: newap->adregp = ap->adregp;
1164: listins( l_ADR, &avlist, ap, newap );
1165: }
1166: }
1167: #endif
1168:
1169:
1170:
1171:
1172: long
1173: check_sect( osptr )
1174: OUTSECT *osptr;
1175: {
1176:
1177: /*
1178: * check the flags in the output section. if all the input sections are dummy
1179: * sections, the output section should be a dummy section.
1180: * If no input section was a regular section and one was a copy section
1181: * the output will be a copy section. If any input section was an info
1182: * section, the output section will have the info flag on. (Most flags
1183: * are not mutually exclusive.)
1184: * if a bss section is combined with data or text, the bss section is
1185: * initialized, and becomes data.
1186: * return the size of the section if the output section is not a dummy
1187: * (the size is used in allocating space for a group).
1188: */
1189:
1190: if ((osptr->osflags & OSDSECT) && !(osptr->osflags & OSREG)) {
1191: osptr->oshdr.s_flags |= STYP_DSECT;
1192: /* remember COPY section also has OSDSECT on */
1193: if (osptr->osflags & OSCOPY)
1194: osptr->oshdr.s_flags |= STYP_COPY;
1195: }
1196: if (osptr->osflags & OSINFO)
1197: osptr->oshdr.s_flags |= STYP_INFO;
1198:
1199: if ((osptr->oshdr.s_flags & STYP_BSS) &&
1200: ((osptr->oshdr.s_flags & (STYP_TEXT | STYP_DATA)) ||
1201: (osptr->osflags & FILL))) {
1202: osptr->oshdr.s_flags ^= STYP_BSS;
1203: osptr->oshdr.s_flags |= STYP_DATA;
1204: }
1205:
1206: if ( !(osptr->oshdr.s_flags & BASIC_TYPES))
1207: if (equal( _TEXT, osptr->oshdr.s_name, 8 ))
1208: osptr->oshdr.s_flags |= STYP_TEXT;
1209: else if (equal( _DATA, osptr->oshdr.s_name, 8 ))
1210: osptr->oshdr.s_flags |= STYP_DATA;
1211: else if (equal( _BSS, osptr->oshdr.s_name, 8 ))
1212: osptr->oshdr.s_flags |= STYP_BSS;
1213:
1214: return ((osptr->oshdr.s_flags & STYP_DSECT) ? 0L : osptr->oshdr.s_size);
1215: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.