Pristine Ack-5.5
[Ack-5.5.git] / util / led / main.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 #ifndef lint
6 static char rcsid[] = "$Id: main.c,v 3.15 1996/11/21 10:14:26 ceriel Exp $";
7 #endif
8
9 /*
10  * led - linkage editor for ACK assemblers output format
11  */
12
13 #include <stdio.h>
14 #include <out.h>
15 #include "const.h"
16 #include "debug.h"
17 #include "defs.h"
18 #include "memory.h"
19 #include "orig.h"
20
21 extern bool     incore;
22 #ifndef NOSTATISTICS
23 int             statistics;
24 #endif
25 #ifndef NDEBUG
26 int                     DEB = 0;
27 #endif
28 int             Verbose = 0;
29
30 static                  initializations();
31 static                  first_pass();
32 static long             number();
33 static                  setlign();
34 static                  setbase();
35 static struct outname   *makename();
36 static                  pass1();
37 static                  evaluate();
38 static                  norm_commons();
39 static                  complete_sections();
40 static                  change_names();
41 static bool             tstbit();
42 static                  second_pass();
43 static                  pass2();
44 #ifndef NOSTATISTICS
45 static                  do_statistics();
46 #endif
47
48 main(argc, argv)
49         int     argc;
50         char    **argv;
51 {
52         initializations(argc, argv);
53         first_pass(argv);
54 #ifndef NOSTATISTICS
55         if (statistics) do_statistics();
56 #endif
57         freeze_core();
58         evaluate();
59         beginoutput();
60         second_pass(argv);
61         endoutput();
62         stop();
63 }
64
65 #ifndef NOSTATISTICS
66 static
67 do_statistics()
68 {
69         register struct memory *m = mems;
70
71         while (m <= &mems[NMEMS-1]) {
72                 fprintf(stderr, "mem %d: full %lx, free %lx\n",
73                                 (int)(m - mems),
74                                 (long) m->mem_full,
75                                 (long) m->mem_left);
76                 m++;
77         }
78 }
79 #endif
80
81 char            *progname;      /* Name this program was invoked with. */
82 int             passnumber;     /* Pass we are in. */
83 struct outhead  outhead;        /* Header of final output file. */
84 struct outsect  outsect[MAXSECT];/* Its section table. */
85
86 /* ARGSUSED */
87 static
88 initializations(argc, argv)
89         int             argc;
90         char            *argv[];
91 {
92         /*
93          * Avoid malloc()s.
94          */
95         setbuf(stdin, (char *)NULL);
96         setbuf(stdout, (char *)NULL);
97         setbuf(stderr, (char *)NULL);
98
99         progname = argv[0];
100         passnumber = FIRST;
101         init_core();
102         init_symboltable();
103         outhead.oh_magic = O_MAGIC;
104         outhead.oh_stamp = O_STAMP;
105 }
106
107 /* ------------------------ ROUTINES OF FIRST PASS ------------------------- */
108
109 int     flagword = 0;           /* To store command-line options. */
110 char    *outputname = "a.out";  /* Name of the resulting object file. */
111 int     exitstatus = 0;
112
113 /*
114  * Scan the arguments.
115  * If the argument starts with a '-', it's a flag, else it is either
116  * a plain file to be loaded, or an archive.
117  */
118 static
119 first_pass(argv)
120         register char           **argv;
121 {
122         register char           *argp;
123         int                     sectno;
124         int                     h;
125         extern int              atoi();
126         extern char             *strindex();
127         extern int              hash();
128         extern struct outname   *searchname();
129
130         while (*++argv) {
131                 argp = *argv;
132                 if (*argp != '-') {
133                         pass1(argp);
134                         continue;
135                 }
136                 /* It's a flag. */
137                 switch (*++argp) {
138                 case 'a':
139                         /*
140                          * The rest of the argument must be of the form
141                          * `<section number>:<alignment>', where
142                          * <section number> and <alignment> are numbers.
143                          * <alignment> will be the alignment in the machine of
144                          * section <section number>.
145                          */
146                         sectno = atoi(++argp);
147                         if ((argp = strindex(argp, ':')) == (char *)0)
148                                 fatal("usage: -a<section number>:<alignment>");
149                         setlign(sectno, number(++argp));
150                         break;
151                 case 'b':
152                         /*
153                          * The rest of the argument must be of the form
154                          * `<section number>:<base>', where <section number>
155                          * and base are decimal numbers. <base> will be
156                          * the base address in the machine of section
157                          * <section number>.
158                          */
159                         sectno = atoi(++argp);
160                         if ((argp = strindex(argp, ':')) == (char *)0)
161                                 fatal("usage: -b<section number>:<base>");
162                         setbase(sectno, number(++argp));
163                         break;
164                 case 'c':
165                         /*
166                          * Leave relocation information in the output, so that
167                          * a next pass can see where relocation was done. The 
168                          * resulting output however is no longer relocatable.
169                          */
170                         flagword &= ~RFLAG;
171                         flagword |= CFLAG;
172                         break;
173 #ifndef NDEBUG
174                 case 'd':
175                         DEB = 1;
176                         break;
177 #endif
178                 case 'n':
179                         /* In the resulting name list, leave offsets with
180                            respect to the beginning of the section instead
181                            of absolute addresses.
182                         */
183                         flagword |= NFLAG;
184                         break;
185
186                 case 'o':
187                         /*
188                          * The `name' argument after -o is used as name
189                          * of the led output file, instead of "a.out".
190                          */
191                         if ((outputname = *++argv) == (char *)0)
192                                 fatal("-o needs filename");
193                         break;
194                 case 'r':
195                         /*
196                          * Generate relocation information in the output file
197                          * so that it can be the subject of another led run.
198                          * This flag also prevents final definitions from being
199                          * given to common symbols, and suppresses the
200                          * `Undefined:' diagnostic.
201                          */
202                         if (flagword & CFLAG) break;
203                         if (flagword & SFLAG)
204                                 warning("-r contradicts -s: -s ignored");
205                         flagword |= RFLAG;
206                         break;
207                 case 's':
208                         /*
209                          * `Strip' the output, that is, remove the symbol table
210                          * and relocation table to save space (but impair the
211                          * usefullness of the debuggers). This information can
212                          * also be removed by astrip(1).
213                          */
214                         if (flagword & RFLAG)
215                                 warning("-s contradicts -r: -s ignored");
216                         else
217                                 flagword |= SFLAG;
218                         break;
219                 case 'u':
220                         /*
221                          * Take the following argument as a symbol and enter it
222                          * as undefined in the symbol table. This is useful for
223                          * loading wholly from a library, since initially the
224                          * symbol table is empty and an unresolved reference is
225                          * needed to force the loading of the first routine.
226                          */
227                         if (*++argv == (char *)0)
228                                 fatal("-u needs symbol name");
229                         h = hash(*argv);
230                         if (searchname(*argv, h) == (struct outname *)0)
231                                 entername(makename(*argv), h);
232                         break;
233                 case 'v':
234                         Verbose = 1;
235                         break;
236                 case 'S':
237                         statistics = 1;
238                         break;
239                 default:
240                         warning("bad flag letter %c", *argp);
241                         break;
242                 }
243         }
244 }
245
246 /*
247  * If `s' starts with 0x/0X, it's hexadecimal,
248  * else if it starts with 0b/0B, it's binary,
249  * else if it starts with 0, it's octal,
250  * else it's decimal.
251  */
252 static long
253 number(s)
254         register char   *s;
255 {
256         register int    digit;
257         register long   value = 0;
258         register int    radix = 10;
259
260         if (*s == '0') {
261                 radix = 8;
262                 s++;
263                 if (*s == 'x' || *s == 'X') {
264                         radix = 16;
265                         s++;
266                 } else if (*s == 'b' || *s == 'B') {
267                         radix = 2;
268                         s++;
269                 }
270         }
271         while (digit = *s++) {
272                 if (digit >= 'A' && digit <= 'F')
273                         digit = digit - 'A' + 10;
274                 else if (digit >= 'a' && digit <= 'f')
275                         digit = digit - 'a' + 10;
276                 else if (digit >= '0' && digit <= '9')
277                         digit = digit - '0';
278                 else
279                         fatal("wrong digit %c", digit);
280                 if (digit >= radix)
281                         fatal("digit %c exceeds radix %d", digit, radix);
282                 value = radix * value + digit;
283         }
284         return value;
285 }
286
287 /*
288  * We use one bit per section to indicate whether a base was already given or
289  * not. Only one base may be given. The same applies for alignments.
290  */
291 static char     basemap[MAXSECT / WIDTH];
292 static long     sect_base[MAXSECT];
293 static char     lignmap[MAXSECT / WIDTH];
294 static long     sect_lign[MAXSECT];
295
296 /*
297 /*
298  * Set the alignment of section `sectno' to `lign', if this doesn't
299  * conflict with earlier alignment.
300  */
301 static
302 setlign(sectno, lign)
303         register int    sectno;
304         register long   lign;
305 {
306         extern bool     setbit();
307
308         if (setbit(sectno, lignmap) && sect_lign[sectno] != lign)
309                 fatal("section has different alignments");
310         if (lign == (long)0)
311                 fatal("alignment cannot be zero");
312         sect_lign[sectno] = lign;
313 }
314
315 /*
316  * Set the base of section `sectno' to `base', if no other base has been
317  * given yet.
318  */
319 static
320 setbase(sectno, base)
321         register int    sectno;
322         register long   base;
323 {
324         extern bool     setbit();
325
326         if (setbit(sectno, basemap) && sect_base[sectno] != base)
327                 fatal("section has different bases");
328         sect_base[sectno] = base;
329 }
330
331 static struct outname *
332 makename(string)
333         char    *string;
334 {
335         static struct outname   namebuf;
336
337         namebuf.on_mptr = string;
338         namebuf.on_type = S_UND + S_EXT;
339         namebuf.on_valu = (long)0;
340
341         return &namebuf;
342 }
343
344 /*
345  * If `file' is a plain file, symboltable information and section sizes are
346  * extracted. If it is an archive it is examined to see if it defines any
347  * undefined symbols.
348  */
349 static
350 pass1(file)
351         char    *file;
352 {
353         if (getfile(file) == PLAIN) {
354                 debug("%s: plain file\n", file, 0, 0, 0);
355                 extract();
356         } else {
357                 /* It must be an archive. */
358                 debug("%s: archive\n", file, 0, 0, 0);
359                 arch();
360         }
361         closefile(file);
362 }
363
364 /* ---------------- ROUTINES BETWEEN FIRST AND SECOND PASS ----------------- */
365
366 /*
367  * After pass 1 we know the sizes of all commons so we can give each common
368  * name an address within its section and we can compute the sizes of all
369  * sections in the machine. After this we can compute the bases of all
370  * sections. We then add the section bases to the values of names in
371  * corresponding sections.
372  */
373 static
374 evaluate()
375 {
376         norm_commons();
377         complete_sections();
378         if (!(flagword&(RFLAG|NFLAG)))
379                 change_names();
380 }
381
382 extern unsigned short   NGlobals, NLocals;
383
384 /*
385  * Sect_comm[N] is the number of common bytes in section N.
386  * It is computed after pass 1.
387  */
388 long    sect_comm[MAXSECT];
389
390 /*
391  * If there are undefined names, we print them and we set a flag so that
392  * the output can be subject to another led run and we return.
393  * We now know how much space each common name needs. We change the value
394  * of the common name from the size to the address within its section,
395  * just like "normal" names. We also count the total size of common names
396  * within each section to be able to compute the final size in the machine.
397  */
398 static
399 norm_commons()
400 {
401         register struct outname *name;
402         register int            cnt;
403         register int            und = FALSE;
404
405         name = (struct outname *)address(ALLOGLOB, (ind_t)0);
406         cnt = NGlobals;
407         while (cnt-- > 0) {
408                 if (ISUNDEFINED(name)) {
409                         if (!und) {
410                                 und = TRUE;
411                                 if (!(flagword & RFLAG)) {
412                                         exitstatus = 1;
413                                         fprintf(stderr, "Undefined:\n");
414                                 }
415                                 outhead.oh_flags |= HF_LINK;
416                                 if (flagword & RFLAG) break;
417                                 flagword = (flagword & ~SFLAG) | RFLAG;
418                         }
419                         fprintf(stderr, "\t%s\n",
420                                 address(ALLOGCHR, (ind_t)name->on_foff)
421                         );
422                 }
423                 name++;
424         }
425         if (flagword & RFLAG) return;
426
427         /*
428          * RFLAG is off, so we need not produce relocatable output.
429          * We can now assign an address to common names.
430          * It also means that there are no undefined names.
431          */
432         name = (struct outname *)address(ALLOGLOB, (ind_t)0);
433         cnt = NGlobals;
434         while (cnt-- > 0) {
435                 if (!ISABSOLUTE(name) && ISCOMMON(name)) {
436                         register long   size;
437                         register int    sectindex;
438
439                         size = name->on_valu;   /* XXX rounding? */
440                         sectindex = (name->on_type & S_TYP) - S_MIN;
441                         name->on_valu =
442                                 outsect[sectindex].os_size +
443                                 sect_comm[sectindex];
444                         sect_comm[sectindex] += size;
445                         name->on_type &= ~S_COM;
446                 }
447                 name++;
448         }
449 }
450
451 struct orig     relorig[MAXSECT];
452
453 /*
454  * Compute the offsets in file and machine that the sections will have.
455  * Also set the origins to 0.
456  */
457 static
458 complete_sections()
459 {
460         register long   base = 0;
461         register long   foff;
462         register struct outsect *sc;
463         register int    sectindex;
464
465         foff = SZ_HEAD + outhead.oh_nsect * SZ_SECT;
466         for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++) {
467                 relorig[sectindex].org_size = (long)0;
468                 sc = &outsect[sectindex];
469                 sc->os_foff = foff;
470                 foff += sc->os_flen;
471
472                 if (flagword & RFLAG)
473                         continue;
474
475                 sc->os_size += sect_comm[sectindex];
476                 sc->os_lign =
477                         tstbit(sectindex, lignmap) ? sect_lign[sectindex] : 1;
478                 if (tstbit(sectindex, basemap)) {
479                         base = sect_base[sectindex];
480                         if (sc->os_lign && base % sc->os_lign)
481                                 fatal("base not aligned");
482                 } else if (sc->os_lign) {
483                         base += sc->os_lign - 1;
484                         base -= base % sc->os_lign;
485                 }
486                 sc->os_base = base;
487                 base += sc->os_size;
488         }
489 }
490
491 /*
492  * For each name we add the base of its section to its value, unless
493  * the output has to be able to be linked again, as indicated by RFLAG.
494  */
495 static
496 change_names()
497 {
498         register int            cnt;
499         register struct outname *name;
500
501         name = (struct outname *)address(ALLOGLOB, (ind_t)0);
502         cnt = NGlobals;
503         while (cnt-- > 0) {
504                 addbase(name);
505                 name++;
506         }
507         if (!incore)
508                 return;
509         /*
510          * Do the same with the local names.
511          */
512         name = (struct outname *)address(ALLOLOCL, (ind_t)0);
513         cnt = NLocals;
514         while (cnt-- > 0) {
515                 addbase(name);
516                 name++;
517         }
518 }
519
520 #define BIT     0x01
521
522 /*
523  * This function sets a bit with index `indx' in string.
524  * It returns whether it was already set.
525  */
526 bool
527 setbit(indx, string)
528         int     indx;
529         char    string[];
530 {
531         register int    byte_index, bit_index;
532         register int    byte;
533
534         byte_index = indx / WIDTH;      /* Index of byte with bit we need. */
535         bit_index = indx % WIDTH;       /* Index of bit we need. */
536         byte = string[byte_index];
537         byte >>= bit_index;
538         if (byte & BIT) return TRUE;
539
540         byte = BIT;
541         byte <<= bit_index;
542         string[byte_index] |= byte;
543         return FALSE;
544 }
545
546 /*
547  * This function returns whether the bit given by `indx' is set in `string'.
548  */
549 static bool
550 tstbit(indx, string)
551         int     indx;
552         char    string[];
553 {
554         register int    byte_index, bit_index;
555         register int    byte;
556
557         byte_index = indx / WIDTH;      /* Index of byte with bit we need. */
558         bit_index = indx % WIDTH;       /* Index of bit we need. */
559         byte = string[byte_index];
560         byte >>= bit_index;
561
562         return byte & BIT;
563 }
564
565 /*
566  * Add the base of the section of a name to its value.
567  */
568 addbase(name)
569         struct outname  *name;
570 {
571         register int    type = name->on_type & S_TYP;
572         register int    sectindex = type - S_MIN;
573
574         if (type == S_UND || type == S_ABS || type == S_CRS)
575                 return;
576         if (name->on_type & S_COM)
577                 return;
578
579         name->on_valu += outsect[sectindex].os_base;
580         debug(  "%s: type 0x%x, value %ld\n",
581                 address((name->on_type & S_EXT) ? ALLOGCHR : ALLOLCHR,
582                         (ind_t)name->on_foff
583                 ),
584                 name->on_type, name->on_valu, 0
585         );
586 }
587
588 /* ------------------------ ROUTINES OF SECOND PASS ------------------------ */
589
590 /*
591  * Flags have already been processed, so we ignore them here.
592  */
593 static
594 second_pass(argv)
595         char    **argv;
596 {
597         passnumber = SECOND;
598         while (*++argv) {
599                 if ((*argv)[0] != '-') {
600                         pass2(*argv);
601                         continue;
602                 }
603                 switch ((*argv)[1]) {
604                 case 'o':
605                 case 'u':
606                         ++argv;
607                         break;
608                 default:
609                         break;
610                 }
611         }
612 }
613
614 static
615 pass2(file)
616         char    *file;
617 {
618         if (getfile(file) == PLAIN) {
619                 debug("%s: plain file\n", file, 0, 0, 0);
620                 finish();
621         } else {
622                 /* It must be an archive. */
623                 debug("%s: archive\n", file, 0, 0, 0);
624                 arch2();
625         }
626         closefile(file);
627 }