|
|
1.1 root 1: static char ID[] = "@(#) output.c: 1.30 12/10/83";
2: #include <stdio.h>
3:
4: #if PORTAR
5: #include <ar.h>
6: #endif
7:
8: #include "system.h"
9: #include "reloc.h"
10: #include "linenum.h"
11: #include "structs.h"
12: #include "extrns.h"
13: #include "ldfcn.h"
14:
15: #if TRVEC
16: #include "tv.h"
17: #include "ldtv.h"
18: #endif
19:
20: #include "aouthdr.h"
21: #include "slotvec.h"
22: #include "sgs.h"
23: #include "patch.h"
24: #include "sgsmacros.h"
25: #include "instr.h"
26: #include "params.h"
27: #include "ldmacros.h"
28:
29:
30: #if AR32W && !UNIX
31: #define MAXSCNBS 20
32: #else
33: #define MAXSCNBS 4
34: #endif
35:
36: /*
37: #if NATIVE || UNIX
38: #define MODE 0777
39: #else
40: #define MODE 0666
41: #endif
42: */
43: #define MODE 0666 /* rob - we always want no execute for 5620s */
44:
45: static long lastfile = -1L; /* symtab index of previous .file entry */
46: static long nextfile = -1L; /* symtab index of next .file entry */
47: static char undefmsg; /* has the undefined message been printed? */
48:
49: #if FLEXNAMES
50: static long string_buf_length = 0;
51: static char *last_string_ptr = NULL;
52: #endif
53:
54: extern unsigned svhighslt;
55: extern unsigned short macflags; /* defined in ld1.c */
56: extern unsigned short swapb2();
57:
58: /*eject*/
59: output()
60: {
61:
62: /*
63: * Produce the output object file
64: */
65:
66:
67: FILE *fdes, *sdes, *rdes;
68: #if FLEXNAMES
69: FILE *strdes;
70: long strtborg;
71: #endif
72: int fd;
73: FILHDR outflhdr;
74: unsigned *buf;
75: ANODE *ap;
76: OUTSECT *osp;
77: INSECT *isp;
78: register SYMTAB *symp;
79: short fill;
80: long indx;
81: extern long time();
82: #if AR16WR
83: char rdesbuf[BUFSIZ], fdesbuf[BUFSIZ], sdesbuf[BUFSIZ];
84: #endif
85:
86: /*
87: * Only generate output if there were no fatal errors,
88: * and the output file can be opened
89: *
90: * NOTE: there is no return from these two lderror calls
91: */
92:
93: if( (errlev > 1) || (errlev && (!rflag || !aflag)) )
94: lderror(2,0,NULL, "Error(s). No output written to %s",
95: outfilnm);
96:
97: buf = (unsigned *) myalloc(BUFSIZ);
98:
99: if( cflag != 4 ) {
100: if( (fd = creat(outfilnm, MODE)) < 0 )
101: lderror(2,0,NULL, "Can't create output file %s", outfilnm);
102: close(fd);
103: fdes = fopen(outfilnm, "w");
104: #if AR16WR
105: setbuf( fdes, fdesbuf );
106: #endif
107: zerofile(fdes, buf, BUFSIZ);
108: }
109: else {
110: copy(outfilnm, "/dev/null", 10);
111: fdes = fopen(outfilnm, "w");
112: }
113:
114: /*
115: * Prepare to generate relocation information
116: */
117:
118: if( rflag ) {
119: rdes = fopen(outfilnm, "w");
120: #if AR16WR
121: setbuf( rdes, rdesbuf );
122: #endif
123: } else
124: rdes = NULL;
125:
126: /*
127: * Prepare to generate a symbol table
128: */
129:
130: if( ! sflag ) {
131: /*
132: * Seek to beginning of symbol table
133: */
134: sdes = fopen(outfilnm, "w");
135: #if AR16WR
136: setbuf( sdes, sdesbuf );
137: #endif
138: fseek(sdes, symtborg, 0);
139:
140: #if FLEXNAMES
141: /* prepare to generate a string table */
142:
143: strdes = fopen(outfilnm, "w");
144: strtborg = symtborg + SYMESZ * tnumsyms + 4;
145: fseek(strdes,strtborg,0);
146: #endif
147: }
148: else {
149: sdes = NULL;
150: #if FLEXNAMES
151: strdes = NULL;
152: #endif
153: }
154:
155: zero((char *) &outflhdr, FILHSZ);
156: fseek(fdes, (long) (FILHSZ + hflag), 0);
157:
158: /*
159: * Output the section headers
160: *
161: * This is done in two steps:
162: * 1. All allocated sections
163: * 2. All unallocated sections (e.g., DSECTS)
164: */
165:
166: for( ap = (ANODE *) avlist.head; ap; ap = ap->adnext ) {
167:
168: if( ap->adtype == ADSECT ) {
169: #if UNIX || XL
170: if( sflag || xflag )
171: #else
172: if( sflag )
173: #endif
174: ap->adscnptr->oshdr.s_nlnno = 0;
175: /*
176: * Reduce "physical" size of .patch section (as far
177: * as ldp is concerned) but leave "true" size
178: * available for patch list construction in wrtplst()
179: */
180: if( (pflag > 0) && equal(ap->adscnptr->oshdr.s_name,".patch",6) ) {
181: indx = ap->adscnptr->oshdr.s_size;
182: ap->adscnptr->oshdr.s_size = (long) pflag;
183: fwrite(ap->adscnptr, SCNHSZ, 1, fdes);
184: ap->adscnptr->oshdr.s_size = indx;
185: }
186: else
187: fwrite(ap->adscnptr, SCNHSZ, 1, fdes);
188: /* Issue a warning if a section starts on an odd byte
189: boundary! This is NEVER adviseable, although it is
190: possible that for certain unforseen special
191: applications, it may be necessary, so it is put
192: in as a warning vice a fatal error; this is
193: applicable in varying degrees of severity for
194: all SGSs */
195: if(ap->adscnptr->oshdr.s_paddr & 0x01L)
196: lderror(0,0,NULL,"Section %.8s starts on an odd byte boundary!",ap->adscnptr->oshdr.s_name);
197:
198: }
199:
200: if( ap->adtype == ADPAD )
201: fwrite(ap->adscnptr, SCNHSZ, 1, fdes);
202:
203: }
204:
205: for( osp = (OUTSECT *) dsectlst.head; osp; osp = osp->osdsnext ) {
206: /*
207: * Special processing for COPY and INFO sections:
208: * 1) remove DSECT (signifying no alloc) flag
209: * 2) leave section size intact
210: */
211:
212: if ( osp->oshdr.s_flags & (STYP_COPY | STYP_INFO)) {
213: osp->oshdr.s_flags ^= STYP_DSECT;
214: }
215: else
216: osp->oshdr.s_size = 0L; /* DSECTS get 0 size */
217: fwrite(osp, SCNHSZ, 1, fdes);
218: }
219:
220: #if ILDOPT
221: if (ildflag) {
222: SCNHDR shdr;
223: copy( shdr.s_name, ".history", 8 );
224: shdr.s_flags = STYP_DSECT;
225: shdr.s_paddr = 0l;
226: shdr.s_vaddr = 0l;
227: shdr.s_size = 0l;
228: shdr.s_scnptr = 0l;
229: shdr.s_relptr = 0l;
230: shdr.s_lnnoptr = 0l;
231: shdr.s_nreloc = 0;
232: shdr.s_nlnno = 0;
233: fwrite( &shdr, SCNHSZ, 1, fdes );
234: }
235: #endif
236:
237: #if TRVEC
238: /*
239: * Now do whatever is necessary to initialize tv.
240: */
241:
242: if (tvflag && aflag)
243: tvinit();
244:
245: #endif
246:
247: /*
248: * Close transfer file
249: */
250:
251: #if !ONEPROC
252: if (ferror(trnfdes))
253: lderror(2,0,NULL,"I/O error on transfer file");
254: fclose( trnfdes );
255: #if AR16WR
256: free( trnfbuf );
257: #endif
258: #endif
259:
260: /*
261: * Allocate buffer for slot vectors used by plocsyms
262: */
263:
264: svinit(maxrelocsms);
265:
266: /*
267: * Process each input file, in order
268: *
269: * The act of processing a file can result in the detection of fatal
270: * errors. These are indicated by setting "errlev" to 2
271: *
272: * Currently known fatal errors:
273: * 1. Undefined symbols when "-r" flag is not set
274: */
275:
276: #if FLEXNAMES
277: wrtinfl(fdes, sdes, strdes, rdes, buf);
278: #else
279: wrtinfl(fdes, sdes, rdes, buf);
280: #endif
281:
282: if ( errlev > 1 ) /* unresolved refs in absolute load */
283: lderror(2,0,NULL, "Symbol referencing errors. No output written to %s",
284: outfilnm);
285:
286: if ( aflag && errlev )
287: lderror(2,0,NULL, "Output file %s not executable", outfilnm);
288:
289: fflush(fdes);
290:
291: #if TRVEC
292: /*
293: * Complete tv processing
294: */
295:
296: if (tvflag && aflag)
297: tvfinish();
298:
299: #endif
300:
301: /*
302: * Fill any necessary holes between sections, in .bss
303: */
304:
305: for( osp = (OUTSECT *) outsclst.head; osp; osp = osp->osnext ) {
306:
307: if( osp->oshdr.s_scnptr != 0L ) {
308: long disp;
309: long offset;
310:
311: #if TRVEC
312: /*
313: * Don't fill the _TV section.
314: * It is built by the link editor.
315: */
316: if( equal(osp->oshdr.s_name, _TV, 8) )
317: continue;
318: #endif
319:
320: indx = 0;
321: fill = (osp->osflags & FILL) ? osp->osfill : globfill;
322: #if AR16WR || AR32WR
323: #if SWABFMT
324: /*
325: * Interchange bytes of the fill constant
326: */
327: fill = ((fill >> 8) & 0xff) + ((fill & 0xff) << 8);
328: #endif
329: #endif
330: isp = osp->osinclhd;
331: while( indx < osp->oshdr.s_size ) {
332: if( isp == NULL )
333: disp = osp->oshdr.s_size;
334: else
335: disp = isp->isdispl;
336: if( disp > indx ) { /* fill needed */
337: offset = osp->oshdr.s_scnptr + indx;
338: fseek(fdes, offset, 0);
339: for( ; indx < disp-1; indx += sizeof(short) )
340: fwrite(&fill, sizeof(short), 1, fdes);
341: if( indx < disp ) {
342: fwrite(&fill, sizeof(char), 1, fdes);
343: indx++;
344: }
345: }
346: if( isp != NULL ) {
347: indx += isp->ishdr.s_size;
348: isp = isp->isincnxt;
349: }
350: }
351: }
352: }
353:
354: /*
355: * Write global symbols at end of symbol table
356: */
357:
358: undefmsg = 0;
359: symp = NULL;
360: while( (symp = loopsym(symp, 1)) != NULL ) {
361: symp->sment.n_value = symp->smnewval;
362: if( (symp->smlocflg == 0) && ! sflag ) {
363: AUXTAB *auxp;
364: char *save_ptr;
365: /*
366: * set last .file entry to point to first
367: * global symbol entry
368: */
369: if ( lastfile != -1L ) {
370: setfile( sdes, noutsyms);
371: lastfile = -1L;
372: }
373:
374: if( Hflag && (symp->sment.n_sclass == C_EXT) )
375: symp->sment.n_sclass = C_STAT;
376: #if FLEXNAMES
377: if (symp->sment.n_zeroes == 0L) {
378: save_ptr = symp->sment.n_nptr;
379: strwrite(strdes,&symp->sment, symp->smnamelength);
380: }
381: #endif
382: if ( fwrite(symp, SYMESZ, 1, sdes) != 1 )
383: lderror(2,0,NULL,
384: "Cannot complete output file %s. Write error.", outfilnm);
385: #if FLEXNAMES
386: if (symp->sment.n_zeroes == 0L)
387: symp->sment.n_nptr = save_ptr;
388: #endif
389:
390: noutsyms++;
391: auxp = NULL;
392: while( (auxp = loopaux(symp, auxp, 0)) != NULL ) {
393: if (auxp->axent.x_sym.x_tvndx == P_TV)
394: auxp->axent.x_sym.x_tvndx = N_TV;
395: #if UNIX || XL || DMERT
396: if ((BTYPE(symp->sment.n_type) == T_STRUCT ||
397: BTYPE(symp->sment.n_type) == T_UNION ||
398: BTYPE(symp->sment.n_type) == T_ENUM ||
399: symp->sment.n_sclass == C_EOS) && auxp->axent.x_sym.x_tagndx > 0) {
400: #if UNIX
401: if (xflag)
402: #endif
403: #if DMERT
404: if (symp->smscnptr && symp->smscnptr->isfilptr->flplib)
405: #endif
406: #if XL
407: if (xflag || (symp->smscnptr && symp->smscnptr->isfilptr->flplib))
408: #endif
409: auxp->axent.x_sym.x_tagndx = 0;
410: }
411: #endif
412: fwrite(auxp, AUXESZ, 1, sdes);
413: noutsyms++;
414: }
415: }
416: }
417: #if FLEXNAMES
418: /*
419: * Once all symbols have been written, write size of string table.
420: * Symbol table file descriptor points to beginning of string table.
421: * Final value of stroffset is size of string table.
422: */
423: if ( last_string_ptr )
424: fwrite( last_string_ptr, string_buf_length, 1, strdes );
425: if ( stroffset > 4L &&
426: fwrite(&stroffset, sizeof(stroffset), 1, sdes) != 1)
427: lderror(2,0,NULL,
428: "fail to write size of string table for file %s",
429: outfilnm);
430: #endif
431:
432: /*
433: * Output the file header
434: */
435:
436: outflhdr.f_magic = magic;
437: if( sflag ) {
438: outflhdr.f_symptr = 0L;
439: outflhdr.f_nsyms = 0L;
440: outflhdr.f_flags |= (F_LNNO | F_LSYMS);
441: }
442: #if UNIX || XL
443: else if ( xflag ) {
444: outflhdr.f_symptr = symtborg;
445: outflhdr.f_nsyms = noutsyms;
446: outflhdr.f_flags |= (F_LNNO | F_LSYMS);
447: }
448: #endif
449: else {
450: outflhdr.f_symptr = symtborg;
451: outflhdr.f_nsyms = noutsyms;
452: }
453: if( ! rflag )
454: outflhdr.f_flags |= F_RELFLG;
455: if ( ! errlev && aflag )
456: outflhdr.f_flags |= F_EXEC;
457: #if AR16WR
458: outflhdr.f_flags |= F_AR16WR;
459: #endif
460: #if AR32WR
461: outflhdr.f_flags |= F_AR32WR;
462: #endif
463: #if AR32W
464: outflhdr.f_flags |= F_AR32W;
465: #endif
466: #if M32
467: /* macflags is used to remember if any input files have F_BM32B on */
468: outflhdr.f_flags |= macflags;
469: #endif
470: if ( pflag )
471: outflhdr.f_flags |= F_PATCH;
472: outflhdr.f_nscns = numoutsc;
473: outflhdr.f_timdat = (long) time(0);
474: outflhdr.f_opthdr = hflag;
475: fseek(fdes, 0L, 0); /* seek to beginning of file */
476: fwrite(&outflhdr, FILHSZ, 1, fdes);
477:
478: /*
479: * If requested, supply an old a.out file header in the optional
480: * header of the output file
481: */
482:
483: if( Xflag )
484: wrtaout(fdes, &outflhdr);
485:
486: /*
487: * Zero the unused portion of the optional header
488: */
489:
490: fill = hflag - (Xflag ? sizeof(AOUTHDR) : 0) - psize();
491: if( fill > 0 ) {
492: zero((char *) buf, BUFSIZ);
493: for( ; fill > 0; fill -= BUFSIZ )
494: fwrite(buf, min(fill, BUFSIZ), 1, fdes);
495: }
496:
497: /*
498: * If requested, construct a patch list. This list is the last thing
499: * built in the optional header
500: */
501:
502: if( pflag )
503: wrtplst(fdes);
504:
505: /*
506: * Close and clean up
507: */
508:
509: if (ferror(fdes))
510: lderror(2,0,NULL,"I/O error on output file %s", outfilnm);
511: fclose(fdes);
512: if ( ! sflag ) {
513: if (ferror(sdes))
514: lderror(2,0,NULL,"I/O error on output file %s",
515: outfilnm);
516: fclose(sdes);
517: #if FLEXNAMES
518: if (ferror(strdes))
519: lderror(2,0,NULL,"I/O error on output file %s",
520: outfilnm);
521: fclose(strdes);
522: #endif
523: }
524: if( rflag ) {
525: if (ferror(rdes))
526: lderror(2,0,NULL,"I/O error on output file %s",
527: outfilnm);
528: fclose(rdes);
529: }
530:
531: free( buf );
532: /*
533: * Release slot vector buffers or frames
534: */
535:
536: #if !NOSDP
537: svfini();
538: #endif
539:
540: if ( outflhdr.f_flags & F_EXEC ) {
541: int mask;
542: mask = umask(0);
543: umask(mask);
544: chmod(outfilnm, MODE & ~mask);
545: }
546: }
547: /*eject*/
548: #if FLEXNAMES
549: wrtinfl(fdes, sdes, strdes, rdes, buf)
550: FILE *fdes, *sdes, *strdes, *rdes;
551: #else
552: wrtinfl(fdes, sdes, rdes, buf)
553: FILE *fdes, *sdes, *rdes;
554: #endif
555: char *buf;
556: {
557:
558: /*
559: * This routine is called once per run to relocate the
560: * text, relocation information, and line number entries.
561: */
562:
563: SCNHDR scnbuf[MAXSCNBS];
564: LDFILE *ifd, *rfd, ifdbuf, rfdbuf;
565: short fill;
566: int lo_scnh, hi_scnh, relocfg;
567: long ndx, offset, oldoffst, paddiff;
568:
569: INFILE *infl, /* current input file */
570: *pnfl; /* previous input file*/
571: register INSECT *isp;
572: OUTSECT *osp;
573: LINENO *lentry;
574: LINENO lentrybuf;
575: SLOTVEC *svp;
576: SYMTAB *gsp;
577:
578: lentry = &lentrybuf;
579:
580: ifd = &ifdbuf;
581: rfd = &rfdbuf;
582: IOPTR(ifd) = NULL;
583: pnfl = NULL;
584: infl = (INFILE *)infilist.head;
585:
586: while ( infl != NULL ) {
587:
588: OFFSET(ifd) = OFFSET(rfd) = infl->flfiloff;
589: if ( IOPTR(ifd) == NULL ) { /* start new input file */
590: #if COMMON
591: if (strcmp(infl->flname,COMF77) == 0) {
592: /* skip the dummy file for F77 common data */
593: infl = infl->flnext;
594: continue;
595: };
596: #endif
597: if( (IOPTR(ifd) = fopen(infl->flname,"r")) == NULL ||
598: (IOPTR(rfd) = fopen(infl->flname,"r")) == NULL )
599: lderror(2,0,NULL, "Can't open %s", infl->flname);
600: if( infl->flfiloff == 0L)
601: TYPE(ifd) = TYPE(rfd) = 0;
602: else
603: TYPE(ifd) = TYPE(rfd) = USH_ARTYPE;
604: }
605: if( TYPE(ifd) == ARTYPE ) {
606: if (FSEEK(ifd,0L,BEGINNING) != OKFSEEK)
607: lderror(2,0,NULL,"internal error: fail to seek to the member of %s",
608: infl->flname);
609: }
610: if( FREAD(&(HEADER(ifd)),FILHSZ,1,ifd) != 1 )
611: lderror(2,0,NULL,"fail to read file header of %s",infl->flname);
612: HEADER(rfd) = HEADER(ifd);
613: lo_scnh = 1;
614: if ((hi_scnh = getrec2(scnbuf,ifd,1)) == 0) {
615: lderror(2,0,NULL,"fail to read section headers of %s",
616: infl->flname);
617: }
618:
619: /*
620: * Process the local symbol table. Build the slot vector entries, to
621: * permit easier relocation of symbol references
622: */
623:
624: #if FLEXNAMES
625: noutsyms += plocsyms(sdes, strdes, ifd, infl);
626: #else
627: noutsyms += plocsyms(sdes, ifd, infl);
628: #endif
629:
630: /*
631: * Process each section in this file which is to be used for link
632: * editing
633: */
634:
635: for( isp = infl->flishead; isp; isp = isp->isnext ) {
636:
637: osp = isp->isoutsec;
638: offset = osp->oshdr.s_scnptr + isp->isdispl;
639:
640: /*
641: * Ignore zero-length input sections, and output section
642: * which are all zeros
643: */
644: if( (isp->ishdr.s_size == 0L) || (osp->oshdr.s_scnptr == 0L) )
645: continue;
646:
647: /*
648: * If the input section was not initialized, but the output
649: * section is, "fill" the section with the appropriate value
650: */
651: if( isp->ishdr.s_scnptr == 0L ) {
652: if( isp->isfillfg )
653: fill = isp->isfill;
654: else if( osp->osflags & FILL )
655: fill = osp->osfill;
656: else
657: fill = globfill;
658: #if AR16WR || AR32WR
659: #if SWABFMT
660: /*
661: * Interchange bytes of the fill constant
662: */
663: fill = ((fill >> 8) & 0x00ff) + ((fill << 8) & 0xff00);
664: #endif
665: #endif
666: fseek(fdes, offset, 0);
667: for( ndx=0; ndx < isp->ishdr.s_size-1; ndx +=2 )
668: fwrite(&fill, sizeof(short), 1, fdes);
669: if( ndx < isp->ishdr.s_size )
670: fwrite(&fill, sizeof(char), 1, fdes);
671: continue;
672: }
673:
674: /*
675: * Process an initialized input section
676: */
677:
678: if( isp->isecnum < lo_scnh || isp->isecnum > hi_scnh) {
679: lo_scnh = isp->isecnum;
680: if ((hi_scnh = getrec2(scnbuf,ifd,lo_scnh)) == 0)
681: lderror(2,0,NULL,"fail to read section header %d of %s",
682: isp->isecnum,infl->flname);
683: hi_scnh += lo_scnh;
684: }
685: if( FSEEK(ifd,scnbuf[isp->isecnum - lo_scnh].s_scnptr,
686: BEGINNING) != OKFSEEK)
687: lderror(2,0,NULL, "Seek to %s section %.8s failed",
688: infl->flname, isp->ishdr.s_name);
689: /*
690: * Prepare to process relocation entries, if any
691: */
692: if( (relocfg = isp->ishdr.s_nreloc) > 0 ) {
693: if( FSEEK(rfd,scnbuf[isp->isecnum - lo_scnh].s_relptr,
694: BEGINNING) != OKFSEEK) {
695: lderror(1,0,NULL, "Seek to %s section %.8s reloc entries failed",
696: infl->flname, isp->ishdr.s_name);
697: relocfg = 0;
698: }
699: }
700: fseek(fdes, offset, 0);
701: if( rflag && relocfg ) {
702: offset = osp->oshdr.s_relptr + isp->isrldisp;
703: fseek(rdes, offset, 0);
704: }
705:
706: relocate(ifd, rfd, infl, isp, osp, fdes, rdes, &paddiff, &relocfg, buf);
707:
708: /*
709: * Process line numbers, if present
710: */
711:
712: #if UNIX || XL
713: if( !sflag && !xflag
714: #else
715: if( !sflag
716: #endif
717: && scnbuf[isp->isecnum - lo_scnh].s_nlnno > 0) {
718: long lnptr;
719:
720: if( FSEEK(ifd,scnbuf[isp->isecnum - lo_scnh].s_lnnoptr,
721: BEGINNING) != OKFSEEK)
722: lderror(2,0,NULL, "Seek to %s section %.8s lnno failed",
723: infl->flname, isp->ishdr.s_name);
724: oldoffst = ftell(sdes);
725: offset = osp->oshdr.s_lnnoptr + isp->islndisp;
726: fseek(fdes, offset, 0);
727: lnptr = offset;
728: for( ndx = 0; ndx < isp->ishdr.s_nlnno; ndx++ ) {
729: AUXENT ax;
730: AUXENT *axp;
731:
732: if (FREAD(lentry,LINESZ,1,ifd) != 1)
733: lderror(2,0,NULL,"fail to read lnno of section %.8s of file %s",
734: isp->ishdr.s_name,infl->flname);
735: if( lentry->l_lnno == 0 ) {
736: if( (svp = svread(lentry->l_addr.l_symndx)) == NULL ) {
737: lderror(1,0,NULL, "line nbr entry (%ld %d) found for non-relocatable symbol: section %.8s, file %s",
738: lentry->l_addr.l_symndx,lentry->l_lnno, isp->ishdr.s_name, infl->flname);
739: continue;
740: }
741: lentry->l_addr.l_symndx = svp->svnewndx;
742: offset = symtborg + (1+lentry->l_addr.l_symndx)*SYMESZ
743: + ((char *) &ax.x_sym.x_fcnary.x_fcn.x_lnnoptr - (char *) &ax);
744: fseek(sdes, offset, 0);
745: fwrite(&lnptr, sizeof(long), 1, sdes);
746: }
747: else
748: lentry->l_addr.l_paddr += paddiff;
749: fwrite(lentry, LINESZ, 1, fdes);
750: lnptr += LINESZ;
751: } /* for */
752: fseek(sdes, oldoffst, 0);
753: } /* if */
754: } /* for isp */
755:
756: pnfl = infl;
757: infl = infl->flnext;
758:
759: /* see if next input file is from same archive */
760: if ( (pnfl->flfiloff > 0L) && (infl != NULL) )
761: if ( strcmp(pnfl->flname, infl->flname) == 0 &&
762: pnfl->flfiloff < infl->flfiloff )
763: continue;
764:
765: fclose(IOPTR(ifd));
766: fclose(IOPTR(rfd));
767: IOPTR(ifd) = NULL;
768: }
769: }
770:
771: long
772: #if FLEXNAMES
773: plocsyms(sdes, strdes, infd, infl)
774: FILE *strdes; /* current place in output string table */
775: #else
776: plocsyms(sdes, infd, infl)
777: #endif
778: FILE *sdes; /* current place in output symbol table */
779: INFILE *infl; /* input file control block */
780: LDFILE *infd; /* input file I/O descriptor */
781: {
782:
783: /*
784: * This routine is called once per input file to process its local
785: * symbol table
786: *
787: * Each symbol is relocated and written to the output file
788: *
789: * In addition, a "slot vector" entry is built so that wrtinfl
790: * can easily get at relocation info for all symbols in the file.
791: *
792: * The "slot" contains the old and new symbol values, old and new symbol
793: * table index, and new section number
794: */
795:
796: register SYMTAB *gsp;
797: register SYMENT *sm;
798: register long count;
799: register AUXTAB *auxp;
800:
801: int *newscnum, *segment;
802: long *ovaddr, *nvaddr, *opaddr, *npaddr;
803: SLOTVEC *svp;
804: int i,
805: secnum, /* section in which defined */
806: reloctag, /* needs x_tagndx relocated */
807: relocend, /* needs x_endndx relocated */
808: tvndx; /* tv slot index or return
809: code from tvslot() */
810: long sltval1, sltval2;
811: long ndx;
812: AUXENT *ax;
813: #if FLEXNAMES
814: char *strtabptr;
815: int strtabsz;
816: #endif
817: SYMENT sm_buf;
818: AUXENT ax_buf;
819: INSECT *isp;
820: int swrite_flag, awrite_flag;
821: char tmp_numaux;
822: long nsymstrip;
823: char stripflag;
824: #if PORTAR
825: struct ar_hdr memberhdr;
826: #endif
827: char *symname;
828:
829: /*
830: * Initialize:
831: * 1. Set slot vector starting slot number to zero
832: * 2. Get the number and position of the symbols in the input file
833: * 3. Allocate space for six arrays
834: * 4. Position the input file to the symbol table
835: */
836:
837: svhighslt = 0;
838:
839: i = HEADER(infd).f_nscns + 1;
840: nsymstrip = 0L;
841: ndx = infl->flsymndx;
842:
843: newscnum = (int *) myalloc( 2*(i*sizeof(int)) + 4*(i*sizeof(long)) );
844: segment = newscnum + i;
845: ovaddr = (long *) (segment + i);
846: nvaddr = ovaddr + i;
847: opaddr = nvaddr + i;
848: npaddr = opaddr + i;
849:
850: #if FLEXNAMES && PORTAR
851: /* read string table if one exists */
852:
853: if (TYPE(infd) == USH_ARTYPE){
854: if (FSEEK(infd,-(int)(sizeof(struct ar_hdr)),BEGINNING) != OKFSEEK ||
855: FREAD(&memberhdr,sizeof(struct ar_hdr), 1, infd) != 1 ||
856: strncmp(memberhdr.ar_fmag,ARFMAG, sizeof(memberhdr.ar_fmag)))
857: lderror(2,0,NULL,"fail to read archive header of file %s",
858: infl->flname);
859: if (sscanf(memberhdr.ar_size,"%ld",&ar_size) != 1)
860: lderror(2,0,NULL,"invalid archive size for file %s", infl->flname);
861: }
862: strtabsz = 0L;
863: if (infl->flstrings)
864: strtabptr = infl->flstrings;
865: else
866: strtabptr = strtabread(infd,infl->flname, &strtabsz);
867: #endif
868:
869: if( HEADER(infd).f_symptr <= 0L ||
870: FSEEK(infd,HEADER(infd).f_symptr,BEGINNING) != OKFSEEK ) {
871: free( newscnum );
872: return(0);
873: }
874:
875: /*
876: * Define the contents of the six arrays
877: */
878:
879: i = 0;
880: for( isp = infl->flishead; isp; isp = isp->isnext ) {
881: OUTSECT *os;
882: newscnum[++i] = isp->isoutsec->ossecnum;
883: ovaddr[i] = isp->ishdr.s_vaddr;
884: opaddr[i] = isp->ishdr.s_paddr;
885: nvaddr[i] = isp->isnewvad;
886: npaddr[i] = isp->isnewpad;
887: os = isp->isoutsec;
888: segment[i] = (int) ((os->oshdr.s_paddr - os->oshdr.s_vaddr) >> 4);
889: }
890:
891: /*
892: * Process each symbol in the symbol table
893: */
894:
895: sm = &sm_buf;
896: ax = &ax_buf;
897: for( count = 0; count < HEADER(infd).f_nsyms; count++) {
898:
899: #if TRVEC
900: tvndx = 0;
901: #else
902: tvndx = -1;
903: #endif
904: reloctag = 0;
905: relocend = 0;
906:
907: if (fread(sm, SYMESZ, 1, IOPTR(infd)) != 1)
908: lderror(2,0,NULL,"fail to read symbol table of file %s",
909: infl->flname);
910:
911: #if FLEXNAMES
912: if (sm->n_zeroes == 0L)
913: {
914: if (strtabptr == NULL)
915: lderror( 2, 0, NULL, "no string table in file %s", infl->flname );
916: sm->n_nptr = strtabptr + sm->n_offset;
917: }
918: #endif
919: symname = PTRNAME(sm);
920:
921: switch(sm->n_sclass) {
922: case C_EXT:
923: case C_EXTDEF:
924: gsp = findsym( symname );
925: swrite_flag = 0;
926: secnum = sm->n_scnum;
927: /*
928: * Determine what will be stored in the slot vector
929: */
930:
931: procext(&tvndx, secnum, &sltval1, &sltval2, ovaddr, nvaddr, gsp, sm);
932:
933: /*
934: * Output defined local symbols
935: */
936: if( gsp->smlocflg && (secnum > 0) ) {
937: svcreate(count, sltval1, sltval2, gsp->smoutndx, gsp->sment.n_scnum,
938: (tvndx != -1) ? SV_TV : 0);
939: if( ! sflag ) {
940: char *save_ptr;
941:
942: sltval1 = gsp->sment.n_value;
943: gsp->sment.n_value = gsp->smnewval;
944: if( Hflag ) {
945: gsp->sment.n_sclass = C_STAT;
946: swrite_flag = 1;
947: }
948: #if FLEXNAMES
949: if (gsp->sment.n_zeroes == 0L) {
950: save_ptr = gsp->sment.n_nptr;
951: strwrite(strdes,&gsp->sment, gsp->smnamelength);
952: }
953: #endif
954: fwrite(gsp, SYMESZ, 1, sdes);
955: #if FLEXNAMES
956: if (gsp->sment.n_zeroes == 0L)
957: gsp->sment.n_nptr = save_ptr;
958: #endif
959:
960: gsp->sment.n_value = sltval1;
961: if( gsp->sment.n_numaux > 0 ) {
962: auxp = getaux(gsp->smauxid);
963: awrite_flag = 0;
964: if( auxp->axent.x_sym.x_tagndx > 0 ) {
965: #if UNIX || DMERT || XL
966: #if UNIX
967: if (xflag)
968: #endif
969: #if DMERT
970: if (infl->flplib)
971: #endif
972: #if XL
973: if (infl->flplib || xflag)
974: #endif
975: auxp->axent.x_sym.x_tagndx = 0;
976: else
977: #endif
978: auxp->axent.x_sym.x_tagndx += infl->flsymndx - nsymstrip;
979: awrite_flag = 1;
980: }
981: if( auxp->axent.x_sym.x_fcnary.x_fcn.x_endndx > 0 ) {
982: #if UNIX || XL
983: if (xflag)
984: auxp->axent.x_sym.x_fcnary.x_fcn.x_endndx = ndx + 2;
985: else
986: #endif
987: auxp->axent.x_sym.x_fcnary.x_fcn.x_endndx += infl->flsymndx - nsymstrip;
988: awrite_flag = 1;
989: }
990: if( auxp->axent.x_sym.x_tvndx == P_TV)
991: auxp->axent.x_sym.x_tvndx = N_TV;
992: #if DMERT || XL
993: if (infl->flplib) {
994: auxp->axent.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0L;
995: awrite_flag = 1;
996: }
997: #endif
998:
999: fwrite(auxp, AUXESZ, 1, sdes);
1000: PUTAUX(auxp, awrite_flag);
1001: }
1002: }
1003: if( sm->n_numaux > 0 ) {
1004: if (fseek(IOPTR(infd), (long) (sm->n_numaux * AUXESZ), 1) != OKFSEEK)
1005: lderror(2,0,NULL,"fail to skip the aux entry of %s",
1006: infl->flname);
1007: }
1008: ndx += 1 + sm->n_numaux;
1009: count += sm->n_numaux;
1010: }
1011: else {
1012: /*
1013: * Symbol is not defined (in this run)
1014: */
1015: if ( (gsp->sment.n_scnum == 0) && aflag &&
1016: (tvndx == -1)) {
1017: /*
1018: * Undefined symbol in an absolute run
1019: * (ignore undefined tv symbols)
1020: */
1021: svcreate(count, sltval1, sltval2, gsp->smoutndx,
1022: gsp->sment.n_scnum, SV_ERR);
1023: if( ! undefmsg ) {
1024: fprintf( stderr, "undefined\t\tfirst referenced\n" );
1025: fprintf( stderr, " symbol \t\t in file\n" );
1026: undefmsg = 1;
1027: errlev = (rflag) ? 1 : 2;
1028: }
1029: if( ! gsp->smundmsg ) {
1030: fprintf( stderr, "%-20.20s\t\t%s",
1031: symname, infl->flname);
1032: fprintf( stderr, "\n" );
1033: gsp->smundmsg = 1;
1034: swrite_flag = 1;
1035: }
1036: }
1037: else
1038: /*
1039: * Undefine symbol, but run not absoute
1040: * (or it has a tv slot)
1041: */
1042: svcreate(count, sltval1, sltval2, gsp->smoutndx,
1043: gsp->sment.n_scnum,
1044: (tvndx != -1) ? SV_TV : 0);
1045: if( sm->n_numaux > 0 ) {
1046: if (fseek(IOPTR(infd), (long) (sm->n_numaux * SYMESZ), 1) != OKFSEEK)
1047: lderror(2,0,NULL,"fail to skip the aux entries of %s",
1048: infl->flname);
1049: count += sm->n_numaux;
1050: if (!sflag && (sectnum > 0 || (secnum == 0 && sm->n_value > 0 ))) {
1051: /*
1052: * If symbol is defined here but not
1053: * written here, relocate the tag index
1054: * in the aux entry
1055: */
1056: auxp = getaux(gsp->smauxid);
1057: if( auxp->axent.x_sym.x_tagndx > 0 ) {
1058: #if UNIX || XL || DMERT
1059: #if UNIX
1060: if (xflag)
1061: #endif
1062: #if DMERT
1063: if (infl->flplib)
1064: #endif
1065: #if XL
1066: if (infl->flplib || xflag)
1067: #endif
1068: auxp->axent.x_sym.x_tagndx = 0;
1069: else
1070: #endif
1071: auxp->axent.x_sym.x_tagndx += infl->flsymndx;
1072: PUTAUX(auxp, 1);
1073: }
1074: else
1075: PUTAUX(auxp, 0);
1076: }
1077: }
1078: }
1079: PUTSYM(gsp, swrite_flag);
1080: break;
1081: case C_STAT:
1082: case C_HIDDEN:
1083: /*
1084: * Absolute statics are generated by the assembler
1085: */
1086: if( sm->n_scnum <= 0 )
1087: goto wrtsym;
1088: sm->n_value += (npaddr[sm->n_scnum] - opaddr[sm->n_scnum]);
1089:
1090: proclocstat(sm, infd, segment, newscnum, &tvndx, ovaddr, nvaddr, opaddr, npaddr, ndx, &sltval1, &sltval2, count);
1091:
1092: if( ISFCN(sm->n_type) )
1093: relocend = 1;
1094:
1095: case C_FIELD:
1096: case C_REGPARM:
1097: /*
1098: * .text, .data, and .bss are C_STATs with
1099: * x_tagndx > 0. They also have secnum > 0,
1100: * but they must not have x_tagndx relocated
1101: * but static structs, unions and enums should
1102: * so differentiate on BTYPE(fundamental type)
1103: */
1104:
1105: if ( (BTYPE(sm->n_type)==T_ENUM) || (BTYPE(sm->n_type)==T_UNION) ||
1106: (BTYPE(sm->n_type)==T_STRUCT) )
1107: reloctag = 1;
1108:
1109: goto wrtsym;
1110: case C_BLOCK:
1111: relocend = 1;
1112: case C_LABEL:
1113: case C_FCN:
1114: sm->n_value += (npaddr[sm->n_scnum] - opaddr[sm->n_scnum]);
1115: wrtsym:
1116: #if UNIX
1117: if (sm->n_sclass != C_STAT && sm->n_sclass != C_FILE && xflag) {
1118: #endif
1119: #if XL
1120: if (sm->n_sclass != C_STAT && sm->n_sclass != C_FILE && xflag || infl->flplib) {
1121: #endif
1122: #if DMERT
1123: if (infl->flplib) {
1124: #endif
1125: #if UNIX || DMERT || XL
1126: stripflag = 1;
1127: if (!sflag) {
1128: nsymstrip++;
1129: }
1130: }
1131: else
1132: #endif
1133: stripflag = 0;
1134:
1135: if( !sflag && !stripflag ) {
1136: if( sm->n_scnum > 0 )
1137: sm->n_scnum = newscnum[sm->n_scnum];
1138: #if FLEXNAMES
1139: if (sm->n_zeroes == 0L)
1140: strwrite(strdes,sm, strlen( sm->n_nptr ) + 1);
1141: #endif
1142: fwrite(sm, SYMESZ, 1, sdes);
1143: ndx++;
1144: }
1145: tmp_numaux = sm->n_numaux;
1146: for( i = 0; i < tmp_numaux; i++ ) {
1147: if (FREAD(ax,AUXESZ,1,infd) != 1)
1148: lderror(2,0,NULL,"fail to read aux entries of file %s",
1149: infl->flname);
1150: #if UNIX || DMERT || XL
1151: if (!sflag && stripflag) {
1152: nsymstrip++;
1153: }
1154: #endif
1155:
1156: if( !sflag && !stripflag) {
1157: if( reloctag && ax->x_sym.x_tagndx > 0 )
1158: #if UNIX || XL || DMERT
1159: #if UNIX
1160: if (xflag)
1161: #endif
1162: #if DMERT
1163: if (infl->flplib)
1164: #endif
1165: #if XL
1166: if (xflag || infl->flplib)
1167: #endif
1168: ax->x_sym.x_tagndx = 0;
1169: else
1170: #endif
1171: ax->x_sym.x_tagndx +=infl->flsymndx - nsymstrip;
1172: if( relocend && ax->x_sym.x_fcnary.x_fcn.x_endndx > 0 )
1173: #if UNIX || XL
1174: if (xflag)
1175: ax->x_sym.x_fcnary.x_fcn.x_endndx += ndx + 1;
1176: else
1177: #endif
1178: ax->x_sym.x_fcnary.x_fcn.x_endndx += infl->flsymndx - nsymstrip;
1179: #if TRVEC
1180: if( (tvndx != -1) && aflag )
1181: ax->x_sym.x_tvndx = tvndx;
1182: if (ax->x_sym.x_tvndx == P_TV)
1183: ax->x_sym.x_tvndx = N_TV;
1184: #endif
1185: fwrite(ax, AUXESZ, 1, sdes);
1186: ndx++;
1187: }
1188: count++;
1189: }
1190: break;
1191: case C_STRTAG:
1192: case C_UNTAG:
1193: case C_ENTAG:
1194: /*
1195: * Relocate x_tagndx and x_endndx
1196: */
1197: relocend = 1;
1198: case C_ARG:
1199: case C_AUTO:
1200: case C_EOS:
1201: case C_MOS:
1202: case C_MOU:
1203: case C_REG:
1204: case C_TPDEF:
1205: /*
1206: * Relocate only x_tagndx
1207: */
1208: reloctag = 1;
1209: goto wrtsym;
1210: case C_FILE:
1211: /*
1212: * Don't relocate since it is not a symbol name
1213: *
1214: * Update previous .file entry (if any) and
1215: * set new value for later update
1216: * This should chain .file entries together,
1217: * for field update, but it is assumed that
1218: * each input *.o file contains a .file entry
1219: * as the first entry in its symbol table
1220: */
1221: #if DMERT || XL
1222: if (!sflag && !infl->flplib && (lastfile != -1L) && (nextfile != ndx))
1223: #else
1224: if (!sflag && (lastfile != -1L) && (nextfile != ndx))
1225: #endif
1226: setfile( sdes, ndx );
1227: if (infl->flnext)
1228: {
1229: nextfile = infl->flnext->flsymndx;
1230: sm->n_value = nextfile;
1231: }
1232: lastfile = ndx;
1233:
1234:
1235: default:
1236: /*
1237: * no relocation
1238: */
1239: goto wrtsym;
1240: }
1241: }
1242:
1243: i = HEADER(infd).f_nscns + 1;
1244: free( newscnum );
1245:
1246: #if FLEXNAMES
1247: if (last_string_ptr)
1248: {
1249: fwrite( last_string_ptr, string_buf_length, 1, strdes );
1250: last_string_ptr = NULL;
1251: string_buf_length = 0;
1252: }
1253: if (strtabptr && (strtabsz > MAXKEEPSIZE))
1254: free( strtabptr );
1255: #endif
1256:
1257: return(ndx - infl->flsymndx);
1258: }
1259:
1260:
1261:
1262:
1263: wrtaout(fdes, fhdr)
1264: FILE *fdes; /* file descriptor seeked to start of optional hdr */
1265: FILHDR *fhdr;
1266: {
1267:
1268: /*
1269: * Write UNIX aout header into optional header block, if -X flag set.
1270: * This function assumes that the sections .text, .data, and .bss
1271: * exist by name.
1272: */
1273:
1274: AOUTHDR aout;
1275: OUTSECT *osptr;
1276: SYMTAB *symp;
1277: char found;
1278:
1279: #if M32
1280: aout.magic = ( Nflag ? AOUT1MAGIC : AOUT2MAGIC );
1281: #else
1282: aout.magic = ( Nflag ? AOUT2MAGIC : AOUT1MAGIC );
1283: #endif
1284: #if PAGING
1285: if ( Fflag && !Nflag )
1286: aout.magic = PAGEMAGIC;
1287: #endif
1288: found = 0;
1289: for( osptr = (OUTSECT *) outsclst.head; osptr; osptr=osptr->osnext ) {
1290: if( equal(osptr->oshdr.s_name, _TEXT, 8) ) {
1291: aout.tsize = osptr->oshdr.s_size;
1292: aout.text_start = osptr->oshdr.s_paddr;
1293: found++;
1294: }
1295: else if( equal(osptr->oshdr.s_name, _DATA, 8) ) {
1296: aout.dsize = osptr->oshdr.s_size;
1297: aout.data_start = osptr->oshdr.s_paddr;
1298: found++;
1299: }
1300: else if( equal(osptr->oshdr.s_name, _BSS, 8) ) {
1301: aout.bsize = osptr->oshdr.s_size;
1302: found++;
1303: }
1304: }
1305:
1306: adjaout(&aout);
1307:
1308: if( found != 3 )
1309: lderror(0,0,NULL,
1310: "Sections .text .data or .bss not found. Optional header may be useless");
1311:
1312: #if OLDAOUT
1313: aout.ssize = fhdr->f_nsyms * SYMESZ;
1314: aout.nsize = 0L;
1315: aout.flags = 0;
1316: if( ! rflag )
1317: aout.flags |= RELFLG;
1318: if( aout.text_start != 0L )
1319: aout.flags |= SETTEXT;
1320: if( aout.text_start + aout.tsize != aout.data_start )
1321: aout.flags |= SETDATA;
1322: if( sflag )
1323: aout.flags |= NSYMFLG;
1324: #else
1325: aout.vstamp = VSflag;
1326: #endif
1327:
1328: /*
1329: * The entry point is obtained from the following sources, in order:
1330: *
1331: * 1. value of the symbol given in the "-e" flag
1332: * 2. value of the symbol _CSTART
1333: * 3. value of the symbol MAIN
1334: */
1335:
1336: if ( (symp = findsym(epsymbol)) ||
1337: (symp = findsym(_CSTART)) ||
1338: (symp = findsym(_MAIN)) ) {
1339: aout.entry = symp->sment.n_value;
1340: PUTSYM(symp, 0);
1341: } else
1342: aout.entry = 0L;
1343:
1344: fwrite(&aout, sizeof(AOUTHDR), 1, fdes);
1345: }
1346: /*eject*/
1347: wrtplst(fdes)
1348: FILE *fdes;
1349: {
1350: /*
1351: * Output the patch list
1352: */
1353:
1354: register int index;
1355: register OUTSECT *osptr;
1356: long count;
1357: char pname[10];
1358: PENTRY block;
1359: OUTSECT *fndoutsec();
1360:
1361: /*
1362: * The file pointer fdes is assumed positioned at the start of the
1363: * patch list
1364: *
1365: * Step 1: Output the block count
1366: */
1367:
1368: count = ( (long)((psize() - sizeof(long)) / PESIZE));
1369: fwrite(&count, sizeof(long), 1, fdes);
1370:
1371: /*
1372: * Step 2: Output a PENTRY structure for each patch segment
1373: */
1374:
1375: for( index = 0; index < count; index++ ) {
1376: if (index < 10)
1377: sprintf( pname, ".patch0%d", index);
1378: else
1379: sprintf(pname, ".patch%d", index);
1380: osptr = fndoutsec(pname);
1381: block.type01.blk_type = (char) FREE_patch;
1382: block.type01.blk_addr = osptr->oshdr.s_paddr;
1383: block.type01.blk_size = osptr->oshdr.s_size;
1384: block.type01.blk_scnum = (unsigned short) osptr->ossecnum;
1385: fwrite(&block, PESIZE, 1, fdes);
1386: }
1387: }
1388:
1389:
1390: setfile( symdes, cursym )
1391:
1392: FILE *symdes;
1393: long cursym;
1394: {
1395:
1396: /*
1397: * Update the previous .file entry in the symbol table
1398: *
1399: * symdes = symbol table output file
1400: * cursym = index of symbol table entry about to be written
1401: *
1402: * static lastfile = index of previous .file entry
1403: */
1404:
1405: long here, /* where we are now */
1406: there; /* where to write update value */
1407:
1408: here = symtborg + cursym * (long)SYMESZ;
1409: there= symtborg + (lastfile * (long) SYMESZ) + (long)SYMNMLEN;
1410: fseek(symdes, there-here, 1);
1411: fwrite(&cursym, sizeof(long), 1, symdes);
1412: fseek(symdes, here-there-sizeof(long), 1);
1413: return(1);
1414: }
1415:
1416: #if FLEXNAMES
1417: strwrite(strdes,sm, strlength)
1418: FILE *strdes; /* pointer to current position in string table */
1419: SYMENT *sm; /* ptr to symbol whose name is to be written in string table */
1420: int strlength;
1421: {
1422: if ((last_string_ptr + string_buf_length) == sm->n_nptr)
1423: string_buf_length += strlength;
1424: else
1425: {
1426: if (last_string_ptr && fwrite(last_string_ptr, string_buf_length, 1, strdes ) != 1)
1427: lderror(2,0,NULL, "fail to write symbol name %s in string table for file %s",
1428: last_string_ptr, outfilnm);
1429: last_string_ptr = sm->n_nptr;
1430: string_buf_length = strlength;
1431: }
1432:
1433: sm->n_offset = stroffset;
1434: stroffset += strlength;
1435: }
1436: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.