• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

Revision2fa0b342a5cd580781d2b9348a87f33a92d363fa (tree)
Zeit1991-03-22 06:29:06
AutorDavid Henkel-Wallace <gumby@cygn...>
CommiterDavid Henkel-Wallace

Log Message

Initial revision

Ändern Zusammenfassung

Diff

--- /dev/null
+++ b/binutils/ar.c
@@ -0,0 +1,850 @@
1+
2+
3+
4+/* ar.c - Archive modify and extract. */
5+/*
6+ Bugs: should use getopt the way tar does (complete w/optional -) and
7+ should have long options too. GNU ar used to check file against filesystem
8+ in quick_update and replace operations (would check mtime). Doesn't warn
9+ when name truncated. No way to specify pos_end. Error messages should be
10+ more consistant.
11+*/
12+#include "sysdep.h"
13+#include "bfd.h"
14+#include "ar.h"
15+#include <stdio.h>
16+#include <sys/time.h>
17+#include <errno.h>
18+#define BUFSIZE 8192
19+/* Not great to have these here. Should they be exported or not? */
20+PROTO(size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd * abfd));
21+PROTO(size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd * abfd));
22+/* PROTO (void, open_inarch, (char *archive_filename)); */
23+#ifdef __STDC__
24+static void open_inarch(char *archive_filename);
25+#else
26+static void open_inarch();
27+#endif /* __STDC__ */
28+
29+PROTO(void, map_over_members, (void (*function) (), char **files, int count));
30+PROTO(void, print_contents, (bfd * member));
31+PROTO(void, extract_file, (bfd * abfd));
32+PROTO(void, delete_members, (char **files_to_delete));
33+PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
34+PROTO(void, move_members, (char **files_to_move));
35+PROTO(void, replace_members, (char **files_to_replace));
36+PROTO(void, print_descr, (bfd * abfd));
37+PROTO(void, ranlib_only, (char *archname));
38+
39+/** Globals and flags */
40+
41+char *program_name = NULL;
42+bfd bogus_archive;
43+bfd *inarch; /* The input arch we're manipulating */
44+
45+/* Nonzero means don't warn about creating the archive file if necessary. */
46+int silent_create = 0;
47+/* Nonzero means describe each action performed. */
48+int verbose = 0;
49+/* Nonzero means preserve dates of members when extracting them. */
50+int preserve_dates = 0;
51+/*
52+ Nonzero means don't replace existing members whose dates are more recent
53+ than the corresponding files.
54+*/
55+int newer_only = 0;
56+/* write a __.SYMDEF member into the modified archive. */
57+boolean write_armap = false;
58+/*
59+ Nonzero means don't update __.SYMDEF unless command line explicitly
60+ requested it
61+*/
62+int ignore_symdef = 0;
63+/*
64+ Nonzero means it's the name of an existing member; position new or moved
65+ files with respect to this one.
66+*/
67+char *posname = NULL;
68+/*
69+ Sez how to use `posname': pos_before means position before that member.
70+ pos_after means position after that member. pos_end means always at end.
71+ pos_default means default appropriately. For the latter two, `posname'
72+ should also be zero.
73+*/
74+enum pos {
75+ pos_default, pos_before, pos_after, pos_end
76+} postype = pos_default;
77+
78+/*
79+ The option parsing should be in its own function. It will be when I have
80+ getopt working.
81+*/
82+int
83+main(argc, argv)
84+ int argc;
85+ char **argv;
86+{
87+ char *arg_ptr;
88+ char c;
89+ enum {
90+ none = 0, delete, replace, print_table,
91+ print_files, extract, move, quick_append
92+ } operation = none;
93+ int arg_index;
94+ char **files;
95+ char *inarch_filename;
96+ char *temp;
97+ program_name = argv[0];
98+
99+
100+ temp = strrchr(program_name, '/');
101+ if (temp == (char *) NULL)
102+ temp = program_name; /* shouldn't happen, but... */
103+ else
104+ ++temp;
105+ if (!strcmp(temp, "ranlib")) {
106+ if (argc < 2)
107+ fatal("Too few command arguments.");
108+ ranlib_only(argv[1]);
109+ }
110+
111+
112+ if (argc < 3)
113+ fatal("Too few command arguments.");
114+
115+ arg_ptr = argv[1];
116+
117+ if (*arg_ptr == '-')
118+ ++arg_ptr; /* compatibility */
119+
120+ while (c = *arg_ptr++) {
121+ switch (c) {
122+ case 'd':
123+ case 'm':
124+ case 'p':
125+ case 'q':
126+ case 'r':
127+ case 't':
128+ case 'x':
129+ if (operation != none)
130+ fatal("two different operation switches specified");
131+ switch (c) {
132+ case 'd':
133+ operation = delete;
134+ break;
135+ case 'm':
136+ operation = move;
137+ break;
138+ case 'p':
139+ operation = print_files;
140+ break;
141+ case 'q':
142+ operation = quick_append;
143+ break;
144+ case 'r':
145+ operation = replace;
146+ break;
147+ case 't':
148+ operation = print_table;
149+ break;
150+ case 'x':
151+ operation = extract;
152+ break;
153+ }
154+ case 'l':
155+ break;
156+ case 'c':
157+ silent_create = 1;
158+ break;
159+ case 'o':
160+ preserve_dates = 1;
161+ break;
162+ case 's':
163+ write_armap = true;
164+ break;
165+ case 'u':
166+ newer_only = 1;
167+ break;
168+ case 'v':
169+ verbose = 1;
170+ break;
171+ case 'a':
172+ postype = pos_after;
173+ break;
174+ case 'b':
175+ postype = pos_before;
176+ break;
177+ case 'i':
178+ postype = pos_before;
179+ break;
180+ default:
181+ fatal("invalid option %c", c);
182+ }
183+ }
184+
185+ if (operation == none && write_armap)
186+ ranlib_only(argv[2]);
187+
188+ if (operation == none)
189+ fatal("no operation specified");
190+
191+ if (newer_only && operation != replace)
192+ fatal("'u' only meaningful with 'r' option.");
193+
194+ arg_index = 2;
195+
196+ if (postype != pos_default)
197+ posname = argv[arg_index++];
198+
199+ inarch_filename = argv[arg_index++];
200+
201+ if (arg_index < argc) {
202+ files = argv + arg_index;
203+ while (arg_index < argc)
204+ if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
205+ ignore_symdef = 1;
206+ break;
207+ }
208+ }
209+ else
210+ files = NULL;
211+
212+ if (operation == quick_append) {
213+ if (files != NULL)
214+ do_quick_append(inarch_filename, files);
215+ exit(0);
216+ }
217+
218+
219+ open_inarch(inarch_filename);
220+ /*
221+ If we have no archive, and we've been asked to replace then create one
222+ */
223+
224+ if (operation == replace &&
225+ inarch == &bogus_archive) {
226+ silent_create = 1;
227+ do_quick_append(inarch_filename, 0);
228+ open_inarch(inarch_filename);
229+ }
230+
231+ switch (operation) {
232+
233+ case print_table:
234+ map_over_members(print_descr, files, argc - 3);
235+ break;
236+
237+ case print_files:
238+ map_over_members(print_contents, files, argc - 3);
239+ break;
240+
241+ case extract:
242+ map_over_members(extract_file, files, argc - 3);
243+ break;
244+
245+ case delete:
246+ if (files != NULL)
247+ delete_members(files);
248+ break;
249+
250+ case move:
251+ if (files != NULL)
252+ move_members(files);
253+ break;
254+
255+ case replace:
256+ if (files != NULL || write_armap)
257+ replace_members(files);
258+ break;
259+
260+ /* Shouldn't happen! */
261+ default:
262+ fprintf(stderr, "Sorry; this option not implemented.\n");
263+ }
264+
265+ return (0);
266+} /* main() */
267+
268+static
269+char *normalize(file)
270+char *file;
271+{
272+ char * filename = strrchr(file, '/');
273+ if (filename != (char *)NULL) {
274+ filename ++;
275+ }
276+ else {
277+ filename = file;
278+ }
279+ return filename;
280+}
281+
282+static void
283+open_inarch(archive_filename)
284+ char *archive_filename;
285+{
286+ bfd **last_one;
287+ bfd *next_one;
288+ struct stat sbuf;
289+ bfd_error = no_error;
290+ if (stat(archive_filename, &sbuf) != 0) {
291+ if (errno != ENOENT)
292+ bfd_fatal(archive_filename);
293+ if (!silent_create)
294+ fprintf(stderr,
295+ "%s: creating %s\n", program_name, archive_filename);
296+
297+ inarch = &bogus_archive;
298+ inarch->filename = archive_filename;
299+ inarch->has_armap = true;
300+
301+ }
302+ else {
303+ inarch = bfd_openr(archive_filename, NULL);
304+ if (inarch == NULL) {
305+ bloser:
306+ bfd_perror(archive_filename);
307+ exit(1);
308+ }
309+
310+ if (bfd_check_format(inarch, bfd_archive) != true)
311+ fatal("File %s is not an archive.", archive_filename);
312+ last_one = &(inarch->next);
313+ /* Read all the contents right away, regardless. */
314+ for (next_one = bfd_openr_next_archived_file(inarch, NULL);
315+ next_one;
316+ next_one = bfd_openr_next_archived_file(inarch, next_one)) {
317+ *last_one = next_one;
318+ last_one = &next_one->next;
319+ }
320+ *last_one = (bfd *) NULL;
321+ if (bfd_error != no_more_archived_files)
322+ goto bloser;
323+ }
324+}
325+
326+
327+
328+/*
329+ If count is 0, then function is called once on each entry. if nonzero,
330+ count is the length of the files chain; function is called on each entry
331+ whose name matches one in files
332+*/
333+void
334+map_over_members(function, files, count)
335+ void (*function) ();
336+ char **files;
337+ int count;
338+{
339+ bfd *head;
340+
341+
342+
343+
344+ if (count == 0) {
345+ for (head = inarch->next; head; head = head->next)
346+ function(head);
347+ return;
348+ }
349+ /*
350+ This may appear to be a baroque way of accomplishing what we want.
351+ however we have to iterate over the filenames in order to notice where
352+ a filename is requested but does not exist in the archive. Ditto
353+ mapping over each file each time -- we want to hack multiple
354+ references.
355+ */
356+
357+ for (; count > 0; files++, count--) {
358+ boolean found = false;
359+ for (head = inarch->next; head; head = head->next)
360+ if ((head->filename != NULL) &&
361+ (!strcmp(*files, head->filename))) {
362+ found = true;
363+ function(head);
364+ }
365+ if (!found)
366+ fprintf(stderr, "No entry %s in archive.\n", *files);
367+ }
368+}
369+
370+
371+/* Things which are interesting to map over all or some of the files: */
372+
373+void
374+print_descr(abfd)
375+ bfd *abfd;
376+{
377+ print_arelt_descr(abfd, verbose);
378+}
379+
380+void
381+print_contents(abfd)
382+ bfd *abfd;
383+{
384+ int ncopied = 0;
385+ struct stat buf;
386+ long size;
387+ if (bfd_stat_arch_elt(abfd, &buf) != 0)
388+ fatal("Internal stat error on %s", abfd->filename);
389+
390+ if (verbose)
391+ printf("\n<member %s>\n\n", abfd->filename);
392+
393+ bfd_seek(abfd, 0, SEEK_SET);
394+
395+ size = buf.st_size;
396+ while (ncopied < size) {
397+ char cbuf[BUFSIZE];
398+ int nread;
399+ int tocopy = size - ncopied;
400+ if (tocopy > BUFSIZE)
401+ tocopy = BUFSIZE;
402+
403+ nread = bfd_read(cbuf, 1, tocopy, abfd); /* oops -- broke
404+ abstraction! */
405+
406+ if (nread != tocopy)
407+ fatal("file %s not a valid archive", abfd->my_archive->filename);
408+ fwrite(cbuf, 1, nread, stdout);
409+ ncopied += tocopy;
410+ }
411+}
412+
413+
414+/*
415+ Extract a member of the archive into its own file.
416+
417+We defer opening the new file until after we have read a BUFSIZ chunk of the
418+ old one, since we know we have just read the archive header for the old
419+ one. Since most members are shorter than BUFSIZ, this means we will read
420+ the old header, read the old data, write a new inode for the new file, and
421+ write the new data, and be done. This 'optimization' is what comes from
422+ sitting next to a bare disk and hearing it every time it seeks. -- Gnu
423+ Gilmore
424+*/
425+
426+void
427+extract_file(abfd)
428+ bfd *abfd;
429+{
430+ FILE *ostream;
431+ char cbuf[BUFSIZE];
432+ int nread,
433+ tocopy;
434+ int ncopied = 0;
435+ long size;
436+ struct stat buf;
437+ if (bfd_stat_arch_elt(abfd, &buf) != 0)
438+ fatal("Internal stat error on %s", abfd->filename);
439+ size = buf.st_size;
440+
441+ if (verbose)
442+ printf("x - %s\n", abfd->filename);
443+
444+ bfd_seek(abfd, 0, SEEK_SET);
445+
446+ ostream = 0;
447+ while (ncopied < size) {
448+ tocopy = size - ncopied;
449+ if (tocopy > BUFSIZE)
450+ tocopy = BUFSIZE;
451+
452+ nread = bfd_read(cbuf, 1, tocopy, abfd);
453+ if (nread != tocopy)
454+ fatal("file %s not a valid archive", abfd->my_archive->filename);
455+
456+ /* See comment above; this saves disk arm motion */
457+ if (!ostream) {
458+ /* Seems like an abstraction violation, eh? Well it's OK! */
459+ ostream = fopen(abfd->filename, "w");
460+ if (!ostream) {
461+ perror(abfd->filename);
462+ exit(1);
463+ }
464+ }
465+ /* no need to byte-swap; the two formats are presumably compatible(!) */
466+ fwrite(cbuf, 1, nread, ostream);
467+ ncopied += tocopy;
468+ }
469+
470+ fclose(ostream);
471+ chmod(abfd->filename, buf.st_mode);
472+
473+ if (preserve_dates) {
474+#ifdef USG
475+ long tb[2];
476+ tb[0] = buf.st_mtime;
477+ tb[1] = buf.st_mtime;
478+ utime(abfd->filename, tb); /* FIXME check result */
479+#else
480+ struct timeval tv[2];
481+ tv[0].tv_sec = buf.st_mtime;
482+ tv[0].tv_usec = 0;
483+ tv[1].tv_sec = buf.st_mtime;
484+ tv[1].tv_usec = 0;
485+ utimes(abfd->filename, tv); /* FIXME check result */
486+#endif
487+ }
488+}
489+
490+
491+/* Just do it quickly; don't worry about dups, armap, or anything like that */
492+
493+/* This is ugly! XXX */
494+
495+PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (char *filename));
496+
497+void
498+do_quick_append(archive_filename, files_to_append)
499+ char *archive_filename;
500+ char **files_to_append;
501+
502+{
503+ FILE *ofile,
504+ *ifile;
505+ char buf[BUFSIZE];
506+ long tocopy,
507+ thistime;
508+ bfd *temp;
509+ struct stat sbuf;
510+ boolean newfile = false;
511+ bfd_error = no_error;
512+
513+ if (stat(archive_filename, &sbuf) != 0) {
514+ if (errno != ENOENT)
515+ bfd_fatal(archive_filename);
516+ newfile = true;
517+ }
518+
519+
520+ ofile = fopen(archive_filename, "a+");
521+ if (ofile == NULL) {
522+ perror(program_name);
523+ exit(1);
524+ }
525+
526+ /* bletch */
527+ temp = bfd_openr(archive_filename, NULL);
528+ if (temp == NULL) {
529+ bfd_perror(archive_filename);
530+ exit(1);
531+ }
532+ if (newfile == false) {
533+ if (bfd_check_format(temp, bfd_archive) != true)
534+ fatal("File %s is not an archive.", archive_filename);
535+ }
536+ else {
537+ fwrite(ARMAG, 1, SARMAG, ofile);
538+ if (!silent_create)
539+ fprintf(stderr, "%s: creating %s\n", program_name, archive_filename);
540+ }
541+
542+ /* assume it's an achive, go straight to the end, sans $200 */
543+ fseek(ofile, 0, 2);
544+
545+ for (; files_to_append && *files_to_append; ++files_to_append) {
546+ struct ar_hdr *hdr = bfd_special_undocumented_glue(*files_to_append);
547+ if (hdr == NULL) {
548+ bfd_perror(*files_to_append);
549+ exit(1);
550+ }
551+
552+ BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
553+
554+ ifile = fopen(*files_to_append, "r");
555+ if (ifile == NULL)
556+ bfd_perror(program_name);
557+
558+ if (stat(*files_to_append, &sbuf) != 0)
559+ bfd_perror(*files_to_append);
560+
561+ tocopy = sbuf.st_size;
562+
563+ /* XXX should do error-checking! */
564+ fwrite(hdr, 1, sizeof(struct ar_hdr), ofile);
565+
566+
567+ while (tocopy > 0) {
568+ thistime = tocopy;
569+ if (thistime > BUFSIZE)
570+ thistime = BUFSIZE;
571+ fread(buf, 1, thistime, ifile);
572+ fwrite(buf, 1, thistime, ofile);
573+ tocopy -= thistime;
574+ }
575+ fclose(ifile);
576+ if ((sbuf.st_size % 2) == 1)
577+ putc('\n', ofile);
578+ }
579+ fclose(ofile);
580+ bfd_close(temp);
581+}
582+
583+
584+void
585+write_archive()
586+{
587+ bfd *obfd;
588+ char *xmalloc();
589+ int namelen = strlen(inarch->filename);
590+ char *new_name = xmalloc(namelen + 6);
591+ bfd *contents_head = inarch->next;
592+ if (inarch == &bogus_archive) {
593+ /* How can this be ? */
594+ return;
595+ }
596+ else {
597+
598+ strcpy(new_name, inarch->filename);
599+ strcpy(new_name + namelen, ".art");
600+ obfd = bfd_openw(new_name, bfd_get_target(inarch));
601+
602+ if (obfd == NULL)
603+ bfd_fatal(inarch->filename);
604+
605+ bfd_set_format(obfd, bfd_archive);
606+ obfd->has_armap = write_armap;
607+
608+ if (bfd_set_archive_head(obfd, contents_head) != true)
609+ bfd_fatal(inarch->filename);
610+
611+ if (!bfd_close(obfd))
612+ bfd_fatal(inarch->filename);
613+ if (rename(new_name, inarch->filename) != 0)
614+ bfd_fatal(inarch->filename);
615+ }
616+}
617+
618+
619+
620+/*
621+ returns a pointer to the pointer to the entry which should be rplacd'd
622+ into when altering. default_pos should be how to interpret pos_default,
623+ and should be a pos value.
624+*/
625+
626+bfd **
627+get_pos_bfd(contents, default_pos)
628+ bfd **contents;
629+ enum pos default_pos;
630+{
631+ bfd **after_bfd;
632+
633+ enum pos realpos = (postype == pos_default ? default_pos : postype);
634+ switch (realpos) {
635+
636+ case pos_end:
637+ after_bfd = contents;
638+ while (*after_bfd) {
639+ after_bfd = &((*after_bfd)->next);
640+ }
641+
642+ break;
643+#if 0
644+ case pos_after:
645+ for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
646+ if (!strcpy(after_bfd->filename, posname))
647+ break;
648+ break;
649+ case pos_before:
650+ for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
651+ if (after_bfd->next && (!strcpy(after_bfd->next->filename, posname)))
652+ break;
653+#endif
654+ }
655+
656+ return after_bfd;
657+}
658+
659+
660+void
661+delete_members(files_to_delete)
662+ char **files_to_delete;
663+{
664+ bfd **current_ptr_ptr;
665+ boolean found;
666+ boolean something_changed = false;
667+ for (; *files_to_delete != NULL; ++files_to_delete) {
668+ /*
669+ In a.out systems, the armap is optional. It's also called
670+ __.SYMDEF. So if the user asked to delete it, we should remember
671+ that fact. The name is NULL in COFF archives, so using this as a
672+ key is as good as anything I suppose
673+ */
674+ if (!strcmp(*files_to_delete, "__.SYMDEF")) {
675+ inarch->has_armap = false;
676+ write_armap = false;
677+ continue;
678+ }
679+
680+ found = false;
681+ current_ptr_ptr = &(inarch->next);
682+ while (*current_ptr_ptr) {
683+ if (strcmp(*files_to_delete, (*current_ptr_ptr)->filename) == 0) {
684+ found = true;
685+ something_changed = true;
686+ if (verbose)
687+ printf("d - %s\n",
688+ *files_to_delete);
689+ *current_ptr_ptr = ((*current_ptr_ptr)->next);
690+ goto next_file;
691+
692+ }
693+ else {
694+ current_ptr_ptr = &((*current_ptr_ptr)->next);
695+ }
696+ }
697+
698+ if (verbose && found == false) {
699+ printf("No member named `%s'\n", *files_to_delete);
700+ }
701+next_file:;
702+
703+ }
704+
705+ if (something_changed == true) {
706+ write_archive();
707+ }
708+}
709+
710+
711+/* Reposition existing members within an archive */
712+
713+void
714+move_members(files_to_move)
715+ char **files_to_move;
716+{
717+ bfd **after_bfd; /* New entries go after this one */
718+ bfd **current_ptr_ptr; /* cdr pointer into contents */
719+
720+
721+
722+
723+ for (; *files_to_move; ++files_to_move) {
724+ current_ptr_ptr = &(inarch->next);
725+ while (*current_ptr_ptr) {
726+ bfd *current_ptr = *current_ptr_ptr;
727+ if (strcmp(normalize(*files_to_move), current_ptr->filename) == 0) {
728+ /*
729+ Move this file to the end of the list - first cut from
730+ where it is.
731+ */
732+ *current_ptr_ptr = current_ptr->next;
733+
734+ /* Now glue to end */
735+ after_bfd = get_pos_bfd(&inarch->next, pos_end);
736+ *after_bfd = current_ptr;
737+ current_ptr->next = (bfd *) NULL;
738+
739+ if (verbose)
740+ printf("m - %s\n", *files_to_move);
741+
742+ goto next_file;
743+ }
744+ current_ptr_ptr = &((*current_ptr_ptr)->next);
745+ }
746+ fprintf(stderr, "No entry %s in archive %s!\n",
747+ *files_to_move, inarch->filename);
748+ exit(1);
749+next_file:;
750+ }
751+
752+ write_archive();
753+}
754+
755+
756+/* Ought to default to replacing in place, but this is existing practice! */
757+
758+void
759+replace_members(files_to_move)
760+ char **files_to_move;
761+{
762+ bfd **after_bfd; /* New entries go after this one */
763+ bfd *current;
764+ bfd **current_ptr;
765+ bfd *temp;
766+ /*
767+ If the first item in the archive is an __.SYMDEF then remove it
768+ */
769+ if (inarch->next &&
770+ strcmp(inarch->next->filename, "__.SYMDEF") == 0) {
771+ inarch->next = inarch->next->next;
772+ }
773+
774+
775+
776+ while (files_to_move && *files_to_move) {
777+ current_ptr = &inarch->next;
778+ while (*current_ptr) {
779+ current = *current_ptr;
780+
781+ if (!strcmp(normalize(*files_to_move), current->filename)) {
782+ /* snip out this entry from the chain */
783+ *current_ptr = current->next;
784+ if (newer_only) {
785+ struct stat fsbuf,
786+ asbuf;
787+ if (stat(*files_to_move, &fsbuf) != 0) {
788+ if (errno != ENOENT)
789+ bfd_fatal(*files_to_move);
790+ goto next_file;
791+ }
792+ if (bfd_stat_arch_elt(current, &asbuf) != 0)
793+ fatal("Internal stat error on %s", current->filename);
794+
795+ if (fsbuf.st_mtime <= asbuf.st_mtime)
796+ goto next_file;
797+ }
798+
799+
800+ after_bfd = get_pos_bfd(&inarch->next, pos_end);
801+ temp = *after_bfd;
802+ *after_bfd = bfd_openr(*files_to_move, NULL);
803+ if (*after_bfd == (bfd *) NULL) {
804+ fprintf(stderr, "Can't open file %s\n", *files_to_move);
805+ exit(1);
806+ }
807+ (*after_bfd)->next = temp;
808+
809+ if (verbose) {
810+ printf("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
811+ *files_to_move);
812+ }
813+ goto next_file;
814+ }
815+ current_ptr = &(current->next);
816+ }
817+
818+ /* It isn't in there, so add to end */
819+
820+ after_bfd = get_pos_bfd(&inarch->next, pos_end);
821+ temp = *after_bfd;
822+ *after_bfd = bfd_openr(*files_to_move, NULL);
823+ if (*after_bfd == (bfd *) NULL) {
824+ fprintf(stderr, "Can't open file %s\n", *files_to_move);
825+ exit(1);
826+ }
827+ if (verbose) {
828+ printf("c - %s\n", *files_to_move);
829+ }
830+
831+ (*after_bfd)->next = temp;
832+
833+next_file:;
834+
835+ files_to_move++;
836+ }
837+
838+
839+ write_archive();
840+}
841+
842+void
843+ranlib_only(archname)
844+ char *archname;
845+{
846+ write_armap = true;
847+ open_inarch(archname);
848+ write_archive();
849+ exit(0);
850+}
--- /dev/null
+++ b/binutils/bucomm.c
@@ -0,0 +1,151 @@
1+/*** bucomm.c -- Bin Utils COMmon code.
2+
3+ We might put this in a library someday so it could be dynamically
4+ loaded, but for now it's not necessary */
5+
6+#include "sysdep.h"
7+#include "bfd.h"
8+#include <varargs.h>
9+
10+char *target = NULL; /* default as late as possible */
11+
12+/* Yes, this is what atexit is for, but that isn't guaranteed yet.
13+ And yes, I know this isn't as good, but it does what is needed just fine */
14+void (*exit_handler) ();
15+
16+/** Memory hackery */
17+
18+PROTO (char *, malloc, (unsigned size));
19+PROTO (char *, realloc, (char *ptr, unsigned size));
20+
21+
22+/* Error reporting */
23+
24+char *program_name;
25+
26+void
27+bfd_fatal (string)
28+ char *string;
29+{
30+ char *errmsg = bfd_errmsg (bfd_error);
31+
32+ if (string)
33+ fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
34+ else
35+ fprintf (stderr, "%s: %s\n", program_name, errmsg);
36+
37+ if (NULL != exit_handler) (*exit_handler) ();
38+ exit (1);
39+}
40+
41+#ifndef NO_STDARG
42+void
43+fatal (Format)
44+ const char *Format;
45+{
46+ va_list args;
47+
48+ va_start (args, Format);
49+ vfprintf (stderr, Format, args);
50+ va_end (args);
51+ (void) putc ('\n', stderr);
52+ if (NULL != exit_handler) (*exit_handler) ();
53+ exit (1);
54+}
55+#else
56+#ifndef NO_VARARGS
57+void fatal (va_alist)
58+ va_dcl
59+{
60+ char *Format;
61+ va_list args;
62+
63+ va_start (args);
64+ Format = va_arg(args, char *);
65+ vfprintf (stderr, Format, args);
66+ va_end (args);
67+ (void) putc ('\n', stderr);
68+ if (NULL != exit_handler) (*exit_handler) ();
69+ exit (1);
70+} /* fatal() */
71+#else
72+/*VARARGS1 */
73+fatal (Format, args)
74+ char *Format;
75+{
76+ as_where ();
77+ _doprnt (Format, &args, stderr); /* not terribly portable, but... */
78+ (void) putc ('\n', stderr);
79+ if (NULL != exit_handler) (*exit_handler) ();
80+ exit (1);
81+}
82+#endif /* not NO_VARARGS */
83+#endif /* not NO_STDARG */
84+
85+
86+/** Display the archive header for an element as if it were an ls -l listing */
87+
88+/* Mode User\tGroup\tSize\tDate Name */
89+
90+void
91+print_arelt_descr (abfd, verbose)
92+ bfd *abfd;
93+ boolean verbose;
94+{
95+ struct stat buf;
96+ char modebuf[11];
97+ char timebuf[40];
98+ long when;
99+ long current_time = time ((long *) 0);
100+
101+ if (verbose) {
102+
103+ if (bfd_stat_arch_elt (abfd, &buf) == 0) { /* if not, huh? */
104+
105+ mode_string (buf.st_mode, modebuf);
106+ modebuf[10] = '\0';
107+ fputs (modebuf, stdout);
108+
109+ when = buf.st_mtime;
110+ strcpy (timebuf, ctime (&when));
111+
112+ /* This code comes from gnu ls. */
113+ if ((current_time - when > 6 * 30 * 24 * 60 * 60)
114+ || (current_time - when < 0)) {
115+ /* The file is fairly old or in the future.
116+ POSIX says the cutoff is 6 months old;
117+ approximate this by 6*30 days.
118+ Show the year instead of the time of day. */
119+ strcpy (timebuf + 11, timebuf + 19);
120+ }
121+ timebuf[16] = 0;
122+
123+ printf (" %d\t%d\t%ld\t%s ", buf.st_uid, buf.st_gid, buf.st_size, timebuf);
124+ }
125+ }
126+
127+ puts (abfd->filename);
128+}
129+
130+/* Like malloc but get fatal error if memory is exhausted. */
131+char *
132+xmalloc (size)
133+ unsigned size;
134+{
135+ register char *result = malloc (size);
136+ if (result == NULL && size != NULL) fatal ("virtual memory exhausted");
137+
138+ return result;
139+}
140+
141+/* Like realloc but get fatal error if memory is exhausted. */
142+char *
143+xrealloc (ptr, size)
144+ char *ptr;
145+ unsigned size;
146+{
147+ register char *result = realloc (ptr, size);
148+ if (result == 0 && size != 0) fatal ("virtual memory exhausted");
149+
150+ return result;
151+}
--- /dev/null
+++ b/binutils/filemode.c
@@ -0,0 +1,193 @@
1+/* filemode.c -- make a string describing file modes
2+ Copyright (C) 1985, 1990 Free Software Foundation, Inc.
3+
4+ This program is free software; you can redistribute it and/or modify
5+ it under the terms of the GNU General Public License as published by
6+ the Free Software Foundation; either version 1, or (at your option)
7+ any later version.
8+
9+ This program is distributed in the hope that it will be useful,
10+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ GNU General Public License for more details.
13+
14+ You should have received a copy of the GNU General Public License
15+ along with this program; if not, write to the Free Software
16+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17+
18+#include <sys/types.h>
19+#include <sys/stat.h>
20+
21+void mode_string ();
22+static char ftypelet ();
23+static void rwx ();
24+static void setst ();
25+
26+/* filemodestring - fill in string STR with an ls-style ASCII
27+ representation of the st_mode field of file stats block STATP.
28+ 10 characters are stored in STR; no terminating null is added.
29+ The characters stored in STR are:
30+
31+ 0 File type. 'd' for directory, 'c' for character
32+ special, 'b' for block special, 'm' for multiplex,
33+ 'l' for symbolic link, 's' for socket, 'p' for fifo,
34+ '-' for any other file type
35+
36+ 1 'r' if the owner may read, '-' otherwise.
37+
38+ 2 'w' if the owner may write, '-' otherwise.
39+
40+ 3 'x' if the owner may execute, 's' if the file is
41+ set-user-id, '-' otherwise.
42+ 'S' if the file is set-user-id, but the execute
43+ bit isn't set.
44+
45+ 4 'r' if group members may read, '-' otherwise.
46+
47+ 5 'w' if group members may write, '-' otherwise.
48+
49+ 6 'x' if group members may execute, 's' if the file is
50+ set-group-id, '-' otherwise.
51+ 'S' if it is set-group-id but not executable.
52+
53+ 7 'r' if any user may read, '-' otherwise.
54+
55+ 8 'w' if any user may write, '-' otherwise.
56+
57+ 9 'x' if any user may execute, 't' if the file is "sticky"
58+ (will be retained in swap space after execution), '-'
59+ otherwise.
60+ 'T' if the file is sticky but not executable. */
61+
62+void
63+filemodestring (statp, str)
64+ struct stat *statp;
65+ char *str;
66+{
67+ mode_string (statp->st_mode, str);
68+}
69+
70+/* Like filemodestring, but only the relevant part of the `struct stat'
71+ is given as an argument. */
72+
73+void
74+mode_string (mode, str)
75+ unsigned short mode;
76+ char *str;
77+{
78+ str[0] = ftypelet (mode);
79+ rwx ((mode & 0700) << 0, &str[1]);
80+ rwx ((mode & 0070) << 3, &str[4]);
81+ rwx ((mode & 0007) << 6, &str[7]);
82+ setst (mode, str);
83+}
84+
85+/* Return a character indicating the type of file described by
86+ file mode BITS:
87+ 'd' for directories
88+ 'b' for block special files
89+ 'c' for character special files
90+ 'm' for multiplexor files
91+ 'l' for symbolic links
92+ 's' for sockets
93+ 'p' for fifos
94+ '-' for any other file type. */
95+
96+static char
97+ftypelet (bits)
98+ unsigned short bits;
99+{
100+ switch (bits & S_IFMT)
101+ {
102+ default:
103+ return '-';
104+ case S_IFDIR:
105+ return 'd';
106+#ifdef S_IFLNK
107+ case S_IFLNK:
108+ return 'l';
109+#endif
110+#ifdef S_IFCHR
111+ case S_IFCHR:
112+ return 'c';
113+#endif
114+#ifdef S_IFBLK
115+ case S_IFBLK:
116+ return 'b';
117+#endif
118+#ifdef S_IFMPC
119+ case S_IFMPC:
120+ case S_IFMPB:
121+ return 'm';
122+#endif
123+#ifdef S_IFSOCK
124+ case S_IFSOCK:
125+ return 's';
126+#endif
127+#ifdef S_IFIFO
128+#if S_IFIFO != S_IFSOCK
129+ case S_IFIFO:
130+ return 'p';
131+#endif
132+#endif
133+#ifdef S_IFNWK /* HP-UX */
134+ case S_IFNWK:
135+ return 'n';
136+#endif
137+ }
138+}
139+
140+/* Look at read, write, and execute bits in BITS and set
141+ flags in CHARS accordingly. */
142+
143+static void
144+rwx (bits, chars)
145+ unsigned short bits;
146+ char *chars;
147+{
148+ chars[0] = (bits & S_IREAD) ? 'r' : '-';
149+ chars[1] = (bits & S_IWRITE) ? 'w' : '-';
150+ chars[2] = (bits & S_IEXEC) ? 'x' : '-';
151+}
152+
153+/* Set the 's' and 't' flags in file attributes string CHARS,
154+ according to the file mode BITS. */
155+
156+static void
157+setst (bits, chars)
158+ unsigned short bits;
159+ char *chars;
160+{
161+#ifdef S_ISUID
162+ if (bits & S_ISUID)
163+ {
164+ if (chars[3] != 'x')
165+ /* Set-uid, but not executable by owner. */
166+ chars[3] = 'S';
167+ else
168+ chars[3] = 's';
169+ }
170+#endif
171+#ifdef S_ISGID
172+ if (bits & S_ISGID)
173+ {
174+ if (chars[6] != 'x')
175+ /* Set-gid, but not executable by group. */
176+ chars[6] = 'S';
177+ else
178+ chars[6] = 's';
179+ }
180+#endif
181+#ifdef S_ISVTX
182+ if (bits & S_ISVTX)
183+ {
184+ if (chars[9] != 'x')
185+ /* Sticky, but not executable by others. */
186+ chars[9] = 'T';
187+ else
188+ chars[9] = 't';
189+ }
190+#endif
191+}
192+
193+
--- /dev/null
+++ b/binutils/i960-pinsn.c
@@ -0,0 +1,820 @@
1+/* Disassemble i80960 instructions.
2+ */
3+
4+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5+
6+This file is part of BFD, the Binary File Diddler.
7+
8+BFD is free software; you can redistribute it and/or modify
9+it under the terms of the GNU General Public License as published by
10+the Free Software Foundation; either version 1, or (at your option)
11+any later version.
12+
13+BFD is distributed in the hope that it will be useful,
14+but WITHOUT ANY WARRANTY; without even the implied warranty of
15+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+GNU General Public License for more details.
17+
18+You should have received a copy of the GNU General Public License
19+along with BFD; see the file COPYING. If not, write to
20+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21+
22+/* $Id$
23+ $Log
24+*/
25+#include <stdio.h>
26+#include "sysdep.h"
27+#include "bfd.h"
28+
29+extern char *xmalloc();
30+extern int fputs();
31+
32+static char *reg_names[] = {
33+/* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7",
34+/* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
35+/* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
36+/* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp",
37+/* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3"
38+};
39+
40+
41+static FILE *stream; /* Output goes here */
42+static void print_addr();
43+static void ctrl();
44+static void cobr();
45+static void reg();
46+static int mem();
47+static void ea();
48+static void dstop();
49+static void regop();
50+static void invalid();
51+static int pinsn();
52+static void put_abs();
53+
54+
55+/* Print the i960 instruction at address 'memaddr' in debugged memory,
56+ * on stream 's'. Returns length of the instruction, in bytes.
57+ */
58+int
59+print_insn_i960( memaddr, buffer, s )
60+ bfd_vma memaddr;
61+uint8e_type *buffer;
62+ FILE *s;
63+{
64+ unsigned int word1, word2;
65+
66+ stream = s;
67+ word1 =buffer [0] |( buffer[1]<< 8) | (buffer[2] << 16) | ( buffer[3] <<24);
68+ word2 =buffer [4] |( buffer[5]<< 8) | (buffer[6] << 16) | ( buffer[7] <<24);
69+ return pinsn( memaddr, word1, word2 );
70+}
71+
72+#define IN_GDB
73+
74+/*****************************************************************************
75+ * All code below this point should be identical with that of
76+ * the disassembler in gdmp960.
77+ *****************************************************************************/
78+
79+struct tabent {
80+ char *name;
81+ char numops;
82+};
83+
84+static int
85+pinsn( memaddr, word1, word2 )
86+ unsigned long memaddr;
87+ unsigned long word1, word2;
88+{
89+ int instr_len;
90+
91+ instr_len = 4;
92+ put_abs( word1, word2 );
93+
94+ /* Divide instruction set into classes based on high 4 bits of opcode*/
95+ switch ( (word1 >> 28) & 0xf ){
96+ case 0x0:
97+ case 0x1:
98+ ctrl( memaddr, word1, word2 );
99+ break;
100+ case 0x2:
101+ case 0x3:
102+ cobr( memaddr, word1, word2 );
103+ break;
104+ case 0x5:
105+ case 0x6:
106+ case 0x7:
107+ reg( word1 );
108+ break;
109+ case 0x8:
110+ case 0x9:
111+ case 0xa:
112+ case 0xb:
113+ case 0xc:
114+ instr_len = mem( memaddr, word1, word2, 0 );
115+ break;
116+ default:
117+ /* invalid instruction, print as data word */
118+ invalid( word1 );
119+ break;
120+ }
121+ return instr_len;
122+}
123+
124+/****************************************/
125+/* CTRL format */
126+/****************************************/
127+static void
128+ctrl( memaddr, word1, word2 )
129+ unsigned long memaddr;
130+ unsigned long word1, word2;
131+{
132+ int i;
133+ static struct tabent ctrl_tab[] = {
134+ NULL, 0, /* 0x00 */
135+ NULL, 0, /* 0x01 */
136+ NULL, 0, /* 0x02 */
137+ NULL, 0, /* 0x03 */
138+ NULL, 0, /* 0x04 */
139+ NULL, 0, /* 0x05 */
140+ NULL, 0, /* 0x06 */
141+ NULL, 0, /* 0x07 */
142+ "b", 1, /* 0x08 */
143+ "call", 1, /* 0x09 */
144+ "ret", 0, /* 0x0a */
145+ "bal", 1, /* 0x0b */
146+ NULL, 0, /* 0x0c */
147+ NULL, 0, /* 0x0d */
148+ NULL, 0, /* 0x0e */
149+ NULL, 0, /* 0x0f */
150+ "bno", 1, /* 0x10 */
151+ "bg", 1, /* 0x11 */
152+ "be", 1, /* 0x12 */
153+ "bge", 1, /* 0x13 */
154+ "bl", 1, /* 0x14 */
155+ "bne", 1, /* 0x15 */
156+ "ble", 1, /* 0x16 */
157+ "bo", 1, /* 0x17 */
158+ "faultno", 0, /* 0x18 */
159+ "faultg", 0, /* 0x19 */
160+ "faulte", 0, /* 0x1a */
161+ "faultge", 0, /* 0x1b */
162+ "faultl", 0, /* 0x1c */
163+ "faultne", 0, /* 0x1d */
164+ "faultle", 0, /* 0x1e */
165+ "faulto", 0, /* 0x1f */
166+ };
167+
168+ i = (word1 >> 24) & 0xff;
169+ if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
170+ invalid( word1 );
171+ return;
172+ }
173+
174+ fputs( ctrl_tab[i].name, stream );
175+ if ( word1 & 2 ){ /* Predicts branch not taken */
176+ fputs( ".f", stream );
177+ }
178+
179+ if ( ctrl_tab[i].numops == 1 ){
180+ /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
181+ word1 &= 0x00ffffff;
182+ if ( word1 & 0x00800000 ){ /* Sign bit is set */
183+ word1 |= (-1 & ~0xffffff); /* Sign extend */
184+ }
185+ putc( '\t', stream );
186+ print_addr( word1 + memaddr );
187+ }
188+}
189+
190+/****************************************/
191+/* COBR format */
192+/****************************************/
193+static void
194+cobr( memaddr, word1, word2 )
195+ unsigned long memaddr;
196+ unsigned long word1, word2;
197+{
198+ int src1;
199+ int src2;
200+ int i;
201+
202+ static struct tabent cobr_tab[] = {
203+ "testno", 1, /* 0x20 */
204+ "testg", 1, /* 0x21 */
205+ "teste", 1, /* 0x22 */
206+ "testge", 1, /* 0x23 */
207+ "testl", 1, /* 0x24 */
208+ "testne", 1, /* 0x25 */
209+ "testle", 1, /* 0x26 */
210+ "testo", 1, /* 0x27 */
211+ NULL, 0, /* 0x28 */
212+ NULL, 0, /* 0x29 */
213+ NULL, 0, /* 0x2a */
214+ NULL, 0, /* 0x2b */
215+ NULL, 0, /* 0x2c */
216+ NULL, 0, /* 0x2d */
217+ NULL, 0, /* 0x2e */
218+ NULL, 0, /* 0x2f */
219+ "bbc", 3, /* 0x30 */
220+ "cmpobg", 3, /* 0x31 */
221+ "cmpobe", 3, /* 0x32 */
222+ "cmpobge", 3, /* 0x33 */
223+ "cmpobl", 3, /* 0x34 */
224+ "cmpobne", 3, /* 0x35 */
225+ "cmpoble", 3, /* 0x36 */
226+ "bbs", 3, /* 0x37 */
227+ "cmpibno", 3, /* 0x38 */
228+ "cmpibg", 3, /* 0x39 */
229+ "cmpibe", 3, /* 0x3a */
230+ "cmpibge", 3, /* 0x3b */
231+ "cmpibl", 3, /* 0x3c */
232+ "cmpibne", 3, /* 0x3d */
233+ "cmpible", 3, /* 0x3e */
234+ "cmpibo", 3, /* 0x3f */
235+ };
236+
237+ i = ((word1 >> 24) & 0xff) - 0x20;
238+ if ( cobr_tab[i].name == NULL ){
239+ invalid( word1 );
240+ return;
241+ }
242+
243+ fputs( cobr_tab[i].name, stream );
244+ if ( word1 & 2 ){ /* Predicts branch not taken */
245+ fputs( ".f", stream );
246+ }
247+ putc( '\t', stream );
248+
249+ src1 = (word1 >> 19) & 0x1f;
250+ src2 = (word1 >> 14) & 0x1f;
251+
252+ if ( word1 & 0x02000 ){ /* M1 is 1 */
253+ fprintf( stream, "%d", src1 );
254+ } else { /* M1 is 0 */
255+ fputs( reg_names[src1], stream );
256+ }
257+
258+ if ( cobr_tab[i].numops > 1 ){
259+ if ( word1 & 1 ){ /* S2 is 1 */
260+ fprintf( stream, ",sf%d,", src2 );
261+ } else { /* S1 is 0 */
262+ fprintf( stream, ",%s,", reg_names[src2] );
263+ }
264+
265+ /* Extract displacement and convert to address
266+ */
267+ word1 &= 0x00001ffc;
268+ if ( word1 & 0x00001000 ){ /* Negative displacement */
269+ word1 |= (-1 & ~0x1fff); /* Sign extend */
270+ }
271+ print_addr( memaddr + word1 );
272+ }
273+}
274+
275+/****************************************/
276+/* MEM format */
277+/****************************************/
278+static int /* returns instruction length: 4 or 8 */
279+mem( memaddr, word1, word2, noprint )
280+ unsigned long memaddr;
281+ unsigned long word1, word2;
282+ int noprint; /* If TRUE, return instruction length, but
283+ * don't output any text.
284+ */
285+{
286+ int i, j;
287+ int len;
288+ int mode;
289+ int offset;
290+ char *reg1, *reg2, *reg3;
291+
292+ /* This lookup table is too sparse to make it worth typing in, but not
293+ * so large as to make a sparse array necessary. We allocate the
294+ * table at runtime, initialize all entries to empty, and copy the
295+ * real ones in from an initialization table.
296+ *
297+ * NOTE: In this table, the meaning of 'numops' is:
298+ * 1: single operand
299+ * 2: 2 operands, load instruction
300+ * -2: 2 operands, store instruction
301+ */
302+ static struct tabent *mem_tab = NULL;
303+ static struct { int opcode; char *name; char numops; } mem_init[] = {
304+#define MEM_MIN 0x80
305+ 0x80, "ldob", 2,
306+ 0x82, "stob", -2,
307+ 0x84, "bx", 1,
308+ 0x85, "balx", 2,
309+ 0x86, "callx", 1,
310+ 0x88, "ldos", 2,
311+ 0x8a, "stos", -2,
312+ 0x8c, "lda", 2,
313+ 0x90, "ld", 2,
314+ 0x92, "st", -2,
315+ 0x98, "ldl", 2,
316+ 0x9a, "stl", -2,
317+ 0xa0, "ldt", 2,
318+ 0xa2, "stt", -2,
319+ 0xb0, "ldq", 2,
320+ 0xb2, "stq", -2,
321+ 0xc0, "ldib", 2,
322+ 0xc2, "stib", -2,
323+ 0xc8, "ldis", 2,
324+ 0xca, "stis", -2,
325+#define MEM_MAX 0xca
326+#define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
327+ 0, NULL, 0
328+ };
329+
330+ if ( mem_tab == NULL ){
331+ mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
332+ bzero( (void *) mem_tab, MEM_SIZ );
333+ for ( i = 0; mem_init[i].opcode != 0; i++ ){
334+ j = mem_init[i].opcode - MEM_MIN;
335+ mem_tab[j].name = mem_init[i].name;
336+ mem_tab[j].numops = mem_init[i].numops;
337+ }
338+ }
339+
340+ i = ((word1 >> 24) & 0xff) - MEM_MIN;
341+ mode = (word1 >> 10) & 0xf;
342+
343+ if ( (mem_tab[i].name != NULL) /* Valid instruction */
344+ && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */
345+ len = 8;
346+ } else {
347+ len = 4;
348+ }
349+
350+ if ( noprint ){
351+ return len;
352+ }
353+
354+ if ( (mem_tab[i].name == NULL) || (mode == 6) ){
355+ invalid( word1 );
356+ return len;
357+ }
358+
359+ fprintf( stream, "%s\t", mem_tab[i].name );
360+
361+ reg1 = reg_names[ (word1 >> 19) & 0x1f ]; /* MEMB only */
362+ reg2 = reg_names[ (word1 >> 14) & 0x1f ];
363+ reg3 = reg_names[ word1 & 0x1f ]; /* MEMB only */
364+ offset = word1 & 0xfff; /* MEMA only */
365+
366+ switch ( mem_tab[i].numops ){
367+
368+ case 2: /* LOAD INSTRUCTION */
369+ if ( mode & 4 ){ /* MEMB FORMAT */
370+ ea( memaddr, mode, reg2, reg3, word1, word2 );
371+ fprintf( stream, ",%s", reg1 );
372+ } else { /* MEMA FORMAT */
373+ fprintf( stream, "0x%x", (unsigned) offset );
374+ if (mode & 8) {
375+ fprintf( stream, "(%s)", reg2 );
376+ }
377+ fprintf( stream, ",%s", reg1 );
378+ }
379+ break;
380+
381+ case -2: /* STORE INSTRUCTION */
382+ if ( mode & 4 ){ /* MEMB FORMAT */
383+ fprintf( stream, "%s,", reg1 );
384+ ea( memaddr, mode, reg2, reg3, word1, word2 );
385+ } else { /* MEMA FORMAT */
386+ fprintf( stream, "%s,0x%x", reg1, (unsigned) offset );
387+ if (mode & 8) {
388+ fprintf( stream, "(%s)", reg2 );
389+ }
390+ }
391+ break;
392+
393+ case 1: /* BX/CALLX INSTRUCTION */
394+ if ( mode & 4 ){ /* MEMB FORMAT */
395+ ea( memaddr, mode, reg2, reg3, word1, word2 );
396+ } else { /* MEMA FORMAT */
397+ fprintf( stream, "0x%x", (unsigned) offset );
398+ if (mode & 8) {
399+ fprintf( stream, "(%s)", reg2 );
400+ }
401+ }
402+ break;
403+ }
404+
405+ return len;
406+}
407+
408+/****************************************/
409+/* REG format */
410+/****************************************/
411+static void
412+reg( word1 )
413+ unsigned long word1;
414+{
415+ int i, j;
416+ int opcode;
417+ int fp;
418+ int m1, m2, m3;
419+ int s1, s2;
420+ int src, src2, dst;
421+ char *mnemp;
422+
423+ /* This lookup table is too sparse to make it worth typing in, but not
424+ * so large as to make a sparse array necessary. We allocate the
425+ * table at runtime, initialize all entries to empty, and copy the
426+ * real ones in from an initialization table.
427+ *
428+ * NOTE: In this table, the meaning of 'numops' is:
429+ * 1: single operand, which is NOT a destination.
430+ * -1: single operand, which IS a destination.
431+ * 2: 2 operands, the 2nd of which is NOT a destination.
432+ * -2: 2 operands, the 2nd of which IS a destination.
433+ * 3: 3 operands
434+ *
435+ * If an opcode mnemonic begins with "F", it is a floating-point
436+ * opcode (the "F" is not printed).
437+ */
438+
439+ static struct tabent *reg_tab = NULL;
440+ static struct { int opcode; char *name; char numops; } reg_init[] = {
441+#define REG_MIN 0x580
442+ 0x580, "notbit", 3,
443+ 0x581, "and", 3,
444+ 0x582, "andnot", 3,
445+ 0x583, "setbit", 3,
446+ 0x584, "notand", 3,
447+ 0x586, "xor", 3,
448+ 0x587, "or", 3,
449+ 0x588, "nor", 3,
450+ 0x589, "xnor", 3,
451+ 0x58a, "not", -2,
452+ 0x58b, "ornot", 3,
453+ 0x58c, "clrbit", 3,
454+ 0x58d, "notor", 3,
455+ 0x58e, "nand", 3,
456+ 0x58f, "alterbit", 3,
457+ 0x590, "addo", 3,
458+ 0x591, "addi", 3,
459+ 0x592, "subo", 3,
460+ 0x593, "subi", 3,
461+ 0x598, "shro", 3,
462+ 0x59a, "shrdi", 3,
463+ 0x59b, "shri", 3,
464+ 0x59c, "shlo", 3,
465+ 0x59d, "rotate", 3,
466+ 0x59e, "shli", 3,
467+ 0x5a0, "cmpo", 2,
468+ 0x5a1, "cmpi", 2,
469+ 0x5a2, "concmpo", 2,
470+ 0x5a3, "concmpi", 2,
471+ 0x5a4, "cmpinco", 3,
472+ 0x5a5, "cmpinci", 3,
473+ 0x5a6, "cmpdeco", 3,
474+ 0x5a7, "cmpdeci", 3,
475+ 0x5ac, "scanbyte", 2,
476+ 0x5ae, "chkbit", 2,
477+ 0x5b0, "addc", 3,
478+ 0x5b2, "subc", 3,
479+ 0x5cc, "mov", -2,
480+ 0x5d8, "eshro", 3,
481+ 0x5dc, "movl", -2,
482+ 0x5ec, "movt", -2,
483+ 0x5fc, "movq", -2,
484+ 0x600, "synmov", 2,
485+ 0x601, "synmovl", 2,
486+ 0x602, "synmovq", 2,
487+ 0x603, "cmpstr", 3,
488+ 0x604, "movqstr", 3,
489+ 0x605, "movstr", 3,
490+ 0x610, "atmod", 3,
491+ 0x612, "atadd", 3,
492+ 0x613, "inspacc", -2,
493+ 0x614, "ldphy", -2,
494+ 0x615, "synld", -2,
495+ 0x617, "fill", 3,
496+ 0x630, "sdma", 3,
497+ 0x631, "udma", 0,
498+ 0x640, "spanbit", -2,
499+ 0x641, "scanbit", -2,
500+ 0x642, "daddc", 3,
501+ 0x643, "dsubc", 3,
502+ 0x644, "dmovt", -2,
503+ 0x645, "modac", 3,
504+ 0x646, "condrec", -2,
505+ 0x650, "modify", 3,
506+ 0x651, "extract", 3,
507+ 0x654, "modtc", 3,
508+ 0x655, "modpc", 3,
509+ 0x656, "receive", -2,
510+ 0x659, "sysctl", 3,
511+ 0x660, "calls", 1,
512+ 0x662, "send", 3,
513+ 0x663, "sendserv", 1,
514+ 0x664, "resumprcs", 1,
515+ 0x665, "schedprcs", 1,
516+ 0x666, "saveprcs", 0,
517+ 0x668, "condwait", 1,
518+ 0x669, "wait", 1,
519+ 0x66a, "signal", 1,
520+ 0x66b, "mark", 0,
521+ 0x66c, "fmark", 0,
522+ 0x66d, "flushreg", 0,
523+ 0x66f, "syncf", 0,
524+ 0x670, "emul", 3,
525+ 0x671, "ediv", 3,
526+ 0x673, "ldtime", -1,
527+ 0x674, "Fcvtir", -2,
528+ 0x675, "Fcvtilr", -2,
529+ 0x676, "Fscalerl", 3,
530+ 0x677, "Fscaler", 3,
531+ 0x680, "Fatanr", 3,
532+ 0x681, "Flogepr", 3,
533+ 0x682, "Flogr", 3,
534+ 0x683, "Fremr", 3,
535+ 0x684, "Fcmpor", 2,
536+ 0x685, "Fcmpr", 2,
537+ 0x688, "Fsqrtr", -2,
538+ 0x689, "Fexpr", -2,
539+ 0x68a, "Flogbnr", -2,
540+ 0x68b, "Froundr", -2,
541+ 0x68c, "Fsinr", -2,
542+ 0x68d, "Fcosr", -2,
543+ 0x68e, "Ftanr", -2,
544+ 0x68f, "Fclassr", 1,
545+ 0x690, "Fatanrl", 3,
546+ 0x691, "Flogeprl", 3,
547+ 0x692, "Flogrl", 3,
548+ 0x693, "Fremrl", 3,
549+ 0x694, "Fcmporl", 2,
550+ 0x695, "Fcmprl", 2,
551+ 0x698, "Fsqrtrl", -2,
552+ 0x699, "Fexprl", -2,
553+ 0x69a, "Flogbnrl", -2,
554+ 0x69b, "Froundrl", -2,
555+ 0x69c, "Fsinrl", -2,
556+ 0x69d, "Fcosrl", -2,
557+ 0x69e, "Ftanrl", -2,
558+ 0x69f, "Fclassrl", 1,
559+ 0x6c0, "Fcvtri", -2,
560+ 0x6c1, "Fcvtril", -2,
561+ 0x6c2, "Fcvtzri", -2,
562+ 0x6c3, "Fcvtzril", -2,
563+ 0x6c9, "Fmovr", -2,
564+ 0x6d9, "Fmovrl", -2,
565+ 0x6e1, "Fmovre", -2,
566+ 0x6e2, "Fcpysre", 3,
567+ 0x6e3, "Fcpyrsre", 3,
568+ 0x701, "mulo", 3,
569+ 0x708, "remo", 3,
570+ 0x70b, "divo", 3,
571+ 0x741, "muli", 3,
572+ 0x748, "remi", 3,
573+ 0x749, "modi", 3,
574+ 0x74b, "divi", 3,
575+ 0x78b, "Fdivr", 3,
576+ 0x78c, "Fmulr", 3,
577+ 0x78d, "Fsubr", 3,
578+ 0x78f, "Faddr", 3,
579+ 0x79b, "Fdivrl", 3,
580+ 0x79c, "Fmulrl", 3,
581+ 0x79d, "Fsubrl", 3,
582+ 0x79f, "Faddrl", 3,
583+#define REG_MAX 0x79f
584+#define REG_SIZ ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
585+ 0, NULL, 0
586+ };
587+
588+ if ( reg_tab == NULL ){
589+ reg_tab = (struct tabent *) xmalloc( REG_SIZ );
590+ bzero( (void *) reg_tab, REG_SIZ );
591+ for ( i = 0; reg_init[i].opcode != 0; i++ ){
592+ j = reg_init[i].opcode - REG_MIN;
593+ reg_tab[j].name = reg_init[i].name;
594+ reg_tab[j].numops = reg_init[i].numops;
595+ }
596+ }
597+
598+ opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
599+ i = opcode - REG_MIN;
600+
601+ if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
602+ invalid( word1 );
603+ return;
604+ }
605+
606+ mnemp = reg_tab[i].name;
607+ if ( *mnemp == 'F' ){
608+ fp = 1;
609+ mnemp++;
610+ } else {
611+ fp = 0;
612+ }
613+
614+ fputs( mnemp, stream );
615+
616+ s1 = (word1 >> 5) & 1;
617+ s2 = (word1 >> 6) & 1;
618+ m1 = (word1 >> 11) & 1;
619+ m2 = (word1 >> 12) & 1;
620+ m3 = (word1 >> 13) & 1;
621+ src = word1 & 0x1f;
622+ src2 = (word1 >> 14) & 0x1f;
623+ dst = (word1 >> 19) & 0x1f;
624+
625+ if ( reg_tab[i].numops != 0 ){
626+ putc( '\t', stream );
627+
628+ switch ( reg_tab[i].numops ){
629+ case 1:
630+ regop( m1, s1, src, fp );
631+ break;
632+ case -1:
633+ dstop( m3, dst, fp );
634+ break;
635+ case 2:
636+ regop( m1, s1, src, fp );
637+ putc( ',', stream );
638+ regop( m2, s2, src2, fp );
639+ break;
640+ case -2:
641+ regop( m1, s1, src, fp );
642+ putc( ',', stream );
643+ dstop( m3, dst, fp );
644+ break;
645+ case 3:
646+ regop( m1, s1, src, fp );
647+ putc( ',', stream );
648+ regop( m2, s2, src2, fp );
649+ putc( ',', stream );
650+ dstop( m3, dst, fp );
651+ break;
652+ }
653+ }
654+}
655+
656+
657+/*
658+ * Print out effective address for memb instructions.
659+ */
660+static void
661+ea( memaddr, mode, reg2, reg3, word1, word2 )
662+ unsigned long memaddr;
663+ int mode;
664+ char *reg2, *reg3;
665+int word1;
666+ unsigned int word2;
667+{
668+ int scale;
669+ static int scale_tab[] = { 1, 2, 4, 8, 16 };
670+
671+ scale = (word1 >> 7) & 0x07;
672+ if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
673+ invalid( word1 );
674+ return;
675+ }
676+ scale = scale_tab[scale];
677+
678+ switch (mode) {
679+ case 4: /* (reg) */
680+ fprintf( stream, "(%s)", reg2 );
681+ break;
682+ case 5: /* displ+8(ip) */
683+ print_addr( word2+8+memaddr );
684+ break;
685+ case 7: /* (reg)[index*scale] */
686+ if (scale == 1) {
687+ fprintf( stream, "(%s)[%s]", reg2, reg3 );
688+ } else {
689+ fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
690+ }
691+ break;
692+ case 12: /* displacement */
693+ print_addr( word2 );
694+ break;
695+ case 13: /* displ(reg) */
696+ print_addr( word2 );
697+ fprintf( stream, "(%s)", reg2 );
698+ break;
699+ case 14: /* displ[index*scale] */
700+ print_addr( word2 );
701+ if (scale == 1) {
702+ fprintf( stream, "[%s]", reg3 );
703+ } else {
704+ fprintf( stream, "[%s*%d]", reg3, scale );
705+ }
706+ break;
707+ case 15: /* displ(reg)[index*scale] */
708+ print_addr( word2 );
709+ if (scale == 1) {
710+ fprintf( stream, "(%s)[%s]", reg2, reg3 );
711+ } else {
712+ fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
713+ }
714+ break;
715+ default:
716+ invalid( word1 );
717+ return;
718+ }
719+}
720+
721+
722+/************************************************/
723+/* Register Instruction Operand */
724+/************************************************/
725+static void
726+regop( mode, spec, reg, fp )
727+ int mode, spec, reg, fp;
728+{
729+ if ( fp ){ /* FLOATING POINT INSTRUCTION */
730+ if ( mode == 1 ){ /* FP operand */
731+ switch ( reg ){
732+ case 0: fputs( "fp0", stream ); break;
733+ case 1: fputs( "fp1", stream ); break;
734+ case 2: fputs( "fp2", stream ); break;
735+ case 3: fputs( "fp3", stream ); break;
736+ case 16: fputs( "0f0.0", stream ); break;
737+ case 22: fputs( "0f1.0", stream ); break;
738+ default: putc( '?', stream ); break;
739+ }
740+ } else { /* Non-FP register */
741+ fputs( reg_names[reg], stream );
742+ }
743+ } else { /* NOT FLOATING POINT */
744+ if ( mode == 1 ){ /* Literal */
745+ fprintf( stream, "%d", reg );
746+ } else { /* Register */
747+ if ( spec == 0 ){
748+ fputs( reg_names[reg], stream );
749+ } else {
750+ fprintf( stream, "sf%d", reg );
751+ }
752+ }
753+ }
754+}
755+
756+/************************************************/
757+/* Register Instruction Destination Operand */
758+/************************************************/
759+static void
760+dstop( mode, reg, fp )
761+ int mode, reg, fp;
762+{
763+ /* 'dst' operand can't be a literal. On non-FP instructions, register
764+ * mode is assumed and "m3" acts as if were "s3"; on FP-instructions,
765+ * sf registers are not allowed so m3 acts normally.
766+ */
767+ if ( fp ){
768+ regop( mode, 0, reg, fp );
769+ } else {
770+ regop( 0, mode, reg, fp );
771+ }
772+}
773+
774+
775+static void
776+invalid( word1 )
777+ int word1;
778+{
779+ fprintf( stream, ".word\t0x%08x", (unsigned) word1 );
780+}
781+
782+static void
783+print_addr(a)
784+int a;
785+{
786+ fprintf( stream, "0x%x", (unsigned) a );
787+}
788+
789+static void
790+put_abs( word1, word2 )
791+ unsigned long word1, word2;
792+{
793+#ifdef IN_GDB
794+ return;
795+#else
796+ int len;
797+
798+ switch ( (word1 >> 28) & 0xf ){
799+ case 0x8:
800+ case 0x9:
801+ case 0xa:
802+ case 0xb:
803+ case 0xc:
804+ /* MEM format instruction */
805+ len = mem( 0, word1, word2, 1 );
806+ break;
807+ default:
808+ len = 4;
809+ break;
810+ }
811+
812+ if ( len == 8 ){
813+ fprintf( stream, "%08x %08x\t", word1, word2 );
814+ } else {
815+ fprintf( stream, "%08x \t", word1 );
816+ }
817+;
818+
819+#endif
820+}
--- /dev/null
+++ b/binutils/m68k-pinsn.c
@@ -0,0 +1,806 @@
1+/* Print m68k instructions for objdump
2+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3+
4+
5+This file is part of the binutils.
6+
7+The binutils are free software; you can redistribute it and/or modify
8+it under the terms of the GNU General Public License as published by
9+the Free Software Foundation; either version 1, or (at your option)
10+any later version.
11+
12+The binutils are distributed in the hope that they will be useful,
13+but WITHOUT ANY WARRANTY; without even the implied warranty of
14+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+GNU General Public License for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with the binutils; see the file COPYING. If not, write to
19+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+/* $Id$
22+ $Log$
23+ Revision 1.1 1991/03/21 21:26:45 gumby
24+ Initial revision
25+
26+ * Revision 1.1 1991/03/13 00:34:06 chrisb
27+ * Initial revision
28+ *
29+ * Revision 1.4 1991/03/09 04:36:34 rich
30+ * Modified Files:
31+ * sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
32+ * binutils.h
33+ *
34+ * Pulled sysdep.h out of bfd.h.
35+ *
36+ * Revision 1.3 1991/03/08 21:54:45 rich
37+ * Modified Files:
38+ * Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
39+ * i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
40+ * sparc-pinsn.c strip.c
41+ *
42+ * Verifying Portland tree with steve's last changes. Also, some partial
43+ * porting.
44+ *
45+ * Revision 1.2 1991/03/08 07:46:24 sac
46+ * Added -l option to disassembly - prints line numbers too.
47+ *
48+ * Revision 1.1 1991/02/22 16:48:02 sac
49+ * Initial revision
50+ *
51+*/
52+
53+#include <stdio.h>
54+#include "sysdep.h"
55+#include "bfd.h"
56+#include "m68k-opcode.h"
57+
58+extern int fputs();
59+extern void print_address();
60+
61+/* 68k instructions are never longer than this many bytes. */
62+#define MAXLEN 22
63+
64+/* Number of elements in the opcode table. */
65+#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
66+
67+extern char *reg_names[];
68+char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
69+ "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
70+
71+char *reg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc"};
72+static unsigned char *print_insn_arg ();
73+static unsigned char *print_indexed ();
74+static void print_base ();
75+static int fetch_arg ();
76+
77+#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
78+
79+#define NEXTWORD(p) \
80+ (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
81+
82+#define NEXTLONG(p) \
83+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
84+
85+#define NEXTSINGLE(p) \
86+ (p += 4, *((float *)(p - 4)))
87+
88+#define NEXTDOUBLE(p) \
89+ (p += 8, *((double *)(p - 8)))
90+
91+#define NEXTEXTEND(p) \
92+ (p += 12, 0.0) /* Need a function to convert from extended to double
93+ precision... */
94+
95+#define NEXTPACKED(p) \
96+ (p += 12, 0.0) /* Need a function to convert from packed to double
97+ precision. Actually, it's easier to print a
98+ packed number than a double anyway, so maybe
99+ there should be a special case to handle this... */
100+
101+/* Print the m68k instruction at address MEMADDR in debugged memory,
102+ on STREAM. Returns length of the instruction, in bytes. */
103+
104+int
105+print_insn_m68k(addr, buffer, stream)
106+ bfd_vma addr;
107+unsigned char *buffer;
108+ FILE *stream;
109+{
110+ register unsigned int i;
111+ register unsigned char *p;
112+ register char *d;
113+ register unsigned int bestmask;
114+ int best;
115+
116+
117+
118+ bestmask = 0;
119+ best = -1;
120+ for (i = 0; i < NOPCODES; i++)
121+ {
122+ register unsigned int opcode = m68k_opcodes[i].opcode;
123+ register unsigned int match = m68k_opcodes[i].match;
124+ if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
125+ && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
126+ && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
127+ && ((0xff & buffer[3] & match) == (0xff & opcode)))
128+ {
129+ /* Don't use for printout the variants of divul and divsl
130+ that have the same register number in two places.
131+ The more general variants will match instead. */
132+ for (d = m68k_opcodes[i].args; *d; d += 2)
133+ if (d[1] == 'D')
134+ break;
135+
136+ /* Don't use for printout the variants of most floating
137+ point coprocessor instructions which use the same
138+ register number in two places, as above. */
139+ if (*d == 0)
140+ for (d = m68k_opcodes[i].args; *d; d += 2)
141+ if (d[1] == 't')
142+ break;
143+
144+ if (*d == 0 && match > bestmask)
145+ {
146+ best = i;
147+ bestmask = match;
148+ }
149+ }
150+ }
151+
152+ /* Handle undefined instructions. */
153+ if (best < 0)
154+ {
155+ fprintf (stream, "0%o", (unsigned) (buffer[0] << 8) + buffer[1]);
156+ return 2;
157+ }
158+
159+ fprintf (stream, "%s", m68k_opcodes[best].name);
160+
161+ /* Point at first word of argument data,
162+ and at descriptor for first argument. */
163+ p = buffer + 2;
164+
165+ /* Why do this this way? -MelloN */
166+ for (d = m68k_opcodes[best].args; *d; d += 2)
167+ {
168+ if (d[0] == '#')
169+ {
170+ if (d[1] == 'l' && p - buffer < 6)
171+ p = buffer + 6;
172+ else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
173+ p = buffer + 4;
174+ }
175+ if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
176+ p = buffer + 4;
177+ if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
178+ p = buffer + 6;
179+ if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
180+ p = buffer + 4;
181+ }
182+
183+ d = m68k_opcodes[best].args;
184+
185+ if (*d)
186+ fputs (" ", stream);
187+
188+ while (*d)
189+ {
190+ p = print_insn_arg (d, buffer, p, addr + p - buffer, stream);
191+ d += 2;
192+ if (*d && *(d - 2) != 'I' && *d != 'k')
193+ fputs (",", stream);
194+ }
195+ return p - buffer;
196+}
197+
198+static unsigned char *
199+print_insn_arg (d, buffer, p, addr, stream)
200+ char *d;
201+ unsigned char *buffer;
202+ register unsigned char *p;
203+ bfd_vma addr; /* PC for this arg to be relative to */
204+ FILE *stream;
205+{
206+ register int val;
207+ register int place = d[1];
208+ int regno;
209+ register char *regname;
210+ register unsigned char *p1;
211+ register double flval;
212+ int flt_p;
213+
214+ switch (*d)
215+ {
216+ case 'C':
217+ fprintf (stream, "ccr");
218+ break;
219+
220+ case 'S':
221+ fprintf (stream, "sr");
222+ break;
223+
224+ case 'U':
225+ fprintf (stream, "usp");
226+ break;
227+
228+ case 'J':
229+ {
230+ static struct { char *name; int value; } names[]
231+ = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
232+ {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
233+ {"msp", 0x803}, {"isp", 0x804}};
234+
235+ val = fetch_arg (buffer, place, 12);
236+ for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
237+ if (names[regno].value == val)
238+ {
239+ fprintf (stream, names[regno].name);
240+ break;
241+ }
242+ if (regno < 0)
243+ fprintf (stream, "%d", val);
244+ }
245+ break;
246+
247+ case 'Q':
248+ val = fetch_arg (buffer, place, 3);
249+ if (val == 0) val = 8;
250+ fprintf (stream, "#%d", val);
251+ break;
252+
253+ case 'M':
254+ val = fetch_arg (buffer, place, 8);
255+ if (val & 0x80)
256+ val = val - 0x100;
257+ fprintf (stream, "#%d", val);
258+ break;
259+
260+ case 'T':
261+ val = fetch_arg (buffer, place, 4);
262+ fprintf (stream, "#%d", val);
263+ break;
264+
265+ case 'D':
266+ fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
267+ break;
268+
269+ case 'A':
270+ fprintf (stream, "%s",
271+ reg_names[fetch_arg (buffer, place, 3) + 010]);
272+ break;
273+
274+ case 'R':
275+ fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
276+ break;
277+
278+ case 'F':
279+ fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
280+ break;
281+
282+ case 'O':
283+ val = fetch_arg (buffer, place, 6);
284+ if (val & 0x20)
285+ fprintf (stream, "%s", reg_names [val & 7]);
286+ else
287+ fprintf (stream, "%d", val);
288+ break;
289+
290+ case '+':
291+ fprintf (stream, "%s@+",
292+ reg_names[fetch_arg (buffer, place, 3) + 8]);
293+ break;
294+
295+ case '-':
296+ fprintf (stream, "%s@-",
297+ reg_names[fetch_arg (buffer, place, 3) + 8]);
298+ break;
299+
300+ case 'k':
301+ if (place == 'k')
302+ fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
303+ else if (place == 'C')
304+ {
305+ val = fetch_arg (buffer, place, 7);
306+ if ( val > 63 ) /* This is a signed constant. */
307+ val -= 128;
308+ fprintf (stream, "{#%d}", val);
309+ }
310+ else
311+ fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
312+ *d, place);
313+ break;
314+
315+ case '#':
316+ case '^':
317+ p1 = buffer + (*d == '#' ? 2 : 4);
318+ if (place == 's')
319+ val = fetch_arg (buffer, place, 4);
320+ else if (place == 'C')
321+ val = fetch_arg (buffer, place, 7);
322+ else if (place == '8')
323+ val = fetch_arg (buffer, place, 3);
324+ else if (place == '3')
325+ val = fetch_arg (buffer, place, 8);
326+ else if (place == 'b')
327+ val = NEXTBYTE (p1);
328+ else if (place == 'w')
329+ val = NEXTWORD (p1);
330+ else if (place == 'l')
331+ val = NEXTLONG (p1);
332+ else
333+ fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
334+ *d, place);
335+ fprintf (stream, "#%d", val);
336+ break;
337+
338+ case 'B':
339+ if (place == 'b')
340+ val = NEXTBYTE (p);
341+ else if (place == 'w')
342+ val = NEXTWORD (p);
343+ else if (place == 'l')
344+ val = NEXTLONG (p);
345+ else if (place == 'g')
346+ {
347+ val = ((char *)buffer)[1];
348+ if (val == 0)
349+ val = NEXTWORD (p);
350+ else if (val == -1)
351+ val = NEXTLONG (p);
352+ }
353+ else if (place == 'c')
354+ {
355+ if (buffer[1] & 0x40) /* If bit six is one, long offset */
356+ val = NEXTLONG (p);
357+ else
358+ val = NEXTWORD (p);
359+ }
360+ else
361+ fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
362+ *d, place);
363+ print_address (addr + val, stream);
364+ break;
365+
366+ case 'd':
367+ val = NEXTWORD (p);
368+ fprintf (stream, "%s@(%d)",
369+ reg_names[fetch_arg (buffer, place, 3)], val);
370+ break;
371+
372+ case 's':
373+ fprintf (stream, "%s",
374+ fpcr_names[fetch_arg (buffer, place, 3)]);
375+ break;
376+
377+ case 'I':
378+ val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
379+ if (val != 1) /* Unusual coprocessor ID? */
380+ fprintf (stream, "(cpid=%d) ", val);
381+ if (place == 'i')
382+ p += 2; /* Skip coprocessor extended operands */
383+ break;
384+
385+ case '*':
386+ case '~':
387+ case '%':
388+ case ';':
389+ case '@':
390+ case '!':
391+ case '$':
392+ case '?':
393+ case '/':
394+ case '&':
395+
396+ if (place == 'd')
397+ {
398+ val = fetch_arg (buffer, 'x', 6);
399+ val = ((val & 7) << 3) + ((val >> 3) & 7);
400+ }
401+ else
402+ val = fetch_arg (buffer, 's', 6);
403+
404+ /* Get register number assuming address register. */
405+ regno = (val & 7) + 8;
406+ regname = reg_names[regno];
407+ switch (val >> 3)
408+ {
409+ case 0:
410+ fprintf (stream, "%s", reg_names[val]);
411+ break;
412+
413+ case 1:
414+ fprintf (stream, "%s", regname);
415+ break;
416+
417+ case 2:
418+ fprintf (stream, "%s@", regname);
419+ break;
420+
421+ case 3:
422+ fprintf (stream, "%s@+", regname);
423+ break;
424+
425+ case 4:
426+ fprintf (stream, "%s@-", regname);
427+ break;
428+
429+ case 5:
430+ val = NEXTWORD (p);
431+ fprintf (stream, "%s@(%d)", regname, val);
432+ break;
433+
434+ case 6:
435+ p = print_indexed (regno, p, addr, stream);
436+ break;
437+
438+ case 7:
439+ switch (val & 7)
440+ {
441+ case 0:
442+ val = NEXTWORD (p);
443+ fprintf (stream, "@#");
444+ print_address (val, stream);
445+ break;
446+
447+ case 1:
448+ val = NEXTLONG (p);
449+ fprintf (stream, "@#");
450+ print_address (val, stream);
451+ break;
452+
453+ case 2:
454+ val = NEXTWORD (p);
455+ print_address (addr + val, stream);
456+ break;
457+
458+ case 3:
459+ p = print_indexed (-1, p, addr, stream);
460+ break;
461+
462+ case 4:
463+ flt_p = 1; /* Assume it's a float... */
464+ switch( place )
465+ {
466+ case 'b':
467+ val = NEXTBYTE (p);
468+ flt_p = 0;
469+ break;
470+
471+ case 'w':
472+ val = NEXTWORD (p);
473+ flt_p = 0;
474+ break;
475+
476+ case 'l':
477+ val = NEXTLONG (p);
478+ flt_p = 0;
479+ break;
480+
481+ case 'f':
482+ flval = NEXTSINGLE(p);
483+ break;
484+
485+ case 'F':
486+ flval = NEXTDOUBLE(p);
487+ break;
488+
489+ case 'x':
490+ flval = NEXTEXTEND(p);
491+ break;
492+
493+ case 'p':
494+ flval = NEXTPACKED(p);
495+ break;
496+
497+ default:
498+ fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
499+ *d, place);
500+ }
501+ if ( flt_p ) /* Print a float? */
502+ fprintf (stream, "#%g", flval);
503+ else
504+ fprintf (stream, "#%d", val);
505+ break;
506+
507+ default:
508+ fprintf (stream, "<invalid address mode 0%o>", (unsigned) val);
509+ }
510+ }
511+ break;
512+
513+ case 'L':
514+ case 'l':
515+ if (place == 'w')
516+ {
517+ char doneany;
518+ p1 = buffer + 2;
519+ val = NEXTWORD (p1);
520+ /* Move the pointer ahead if this point is farther ahead
521+ than the last. */
522+ p = p1 > p ? p1 : p;
523+ if (val == 0)
524+ {
525+ fputs ("#0", stream);
526+ break;
527+ }
528+ if (*d == 'l')
529+ {
530+ register int newval = 0;
531+ for (regno = 0; regno < 16; ++regno)
532+ if (val & (0x8000 >> regno))
533+ newval |= 1 << regno;
534+ val = newval;
535+ }
536+ val &= 0xffff;
537+ doneany = 0;
538+ for (regno = 0; regno < 16; ++regno)
539+ if (val & (1 << regno))
540+ {
541+ int first_regno;
542+ if (doneany)
543+ fputs ("/", stream);
544+ doneany = 1;
545+ fprintf (stream, "%s", reg_names[regno]);
546+ first_regno = regno;
547+ while (val & (1 << (regno + 1)))
548+ ++regno;
549+ if (regno > first_regno)
550+ fprintf (stream, "-%s", reg_names[regno]);
551+ }
552+ }
553+ else if (place == '3')
554+ {
555+ /* `fmovem' insn. */
556+ char doneany;
557+ val = fetch_arg (buffer, place, 8);
558+ if (val == 0)
559+ {
560+ fputs ("#0", stream);
561+ break;
562+ }
563+ if (*d == 'l')
564+ {
565+ register int newval = 0;
566+ for (regno = 0; regno < 8; ++regno)
567+ if (val & (0x80 >> regno))
568+ newval |= 1 << regno;
569+ val = newval;
570+ }
571+ val &= 0xff;
572+ doneany = 0;
573+ for (regno = 0; regno < 8; ++regno)
574+ if (val & (1 << regno))
575+ {
576+ int first_regno;
577+ if (doneany)
578+ fputs ("/", stream);
579+ doneany = 1;
580+ fprintf (stream, "fp%d", regno);
581+ first_regno = regno;
582+ while (val & (1 << (regno + 1)))
583+ ++regno;
584+ if (regno > first_regno)
585+ fprintf (stream, "-fp%d", regno);
586+ }
587+ }
588+ else
589+ abort ();
590+ break;
591+
592+ default:
593+ fprintf(stderr, "Invalid arg format in opcode table: \"%c\".", *d);
594+ }
595+
596+ return (unsigned char *) p;
597+}
598+
599+/* Fetch BITS bits from a position in the instruction specified by CODE.
600+ CODE is a "place to put an argument", or 'x' for a destination
601+ that is a general address (mode and register).
602+ BUFFER contains the instruction. */
603+
604+static int
605+fetch_arg (buffer, code, bits)
606+ unsigned char *buffer;
607+ char code;
608+ int bits;
609+{
610+ register int val;
611+ switch (code)
612+ {
613+ case 's':
614+ val = buffer[1];
615+ break;
616+
617+ case 'd': /* Destination, for register or quick. */
618+ val = (buffer[0] << 8) + buffer[1];
619+ val >>= 9;
620+ break;
621+
622+ case 'x': /* Destination, for general arg */
623+ val = (buffer[0] << 8) + buffer[1];
624+ val >>= 6;
625+ break;
626+
627+ case 'k':
628+ val = (buffer[3] >> 4);
629+ break;
630+
631+ case 'C':
632+ val = buffer[3];
633+ break;
634+
635+ case '1':
636+ val = (buffer[2] << 8) + buffer[3];
637+ val >>= 12;
638+ break;
639+
640+ case '2':
641+ val = (buffer[2] << 8) + buffer[3];
642+ val >>= 6;
643+ break;
644+
645+ case '3':
646+ case 'j':
647+ val = (buffer[2] << 8) + buffer[3];
648+ break;
649+
650+ case '4':
651+ val = (buffer[4] << 8) + buffer[5];
652+ val >>= 12;
653+ break;
654+
655+ case '5':
656+ val = (buffer[4] << 8) + buffer[5];
657+ val >>= 6;
658+ break;
659+
660+ case '6':
661+ val = (buffer[4] << 8) + buffer[5];
662+ break;
663+
664+ case '7':
665+ val = (buffer[2] << 8) + buffer[3];
666+ val >>= 7;
667+ break;
668+
669+ case '8':
670+ val = (buffer[2] << 8) + buffer[3];
671+ val >>= 10;
672+ break;
673+
674+ default:
675+ abort ();
676+ }
677+
678+ switch (bits)
679+ {
680+ case 3:
681+ return val & 7;
682+ case 4:
683+ return val & 017;
684+ case 5:
685+ return val & 037;
686+ case 6:
687+ return val & 077;
688+ case 7:
689+ return val & 0177;
690+ case 8:
691+ return val & 0377;
692+ case 12:
693+ return val & 07777;
694+ default:
695+ abort ();
696+ return(0);
697+ }
698+} /* fetch_arg() */
699+
700+/* Print an indexed argument. The base register is BASEREG (-1 for pc).
701+ P points to extension word, in buffer.
702+ ADDR is the nominal core address of that extension word. */
703+
704+static unsigned char *
705+print_indexed (basereg, p, addr, stream)
706+ int basereg;
707+ unsigned char *p;
708+ FILE *stream;
709+bfd_vma addr;
710+{
711+ register int word;
712+ static char *scales[] = {"", "*2", "*4", "*8"};
713+ register int base_disp;
714+ register int outer_disp;
715+ char buf[40];
716+
717+ word = NEXTWORD (p);
718+
719+ /* Generate the text for the index register.
720+ Where this will be output is not yet determined. */
721+ sprintf (buf, "[%s.%c%s]",
722+ reg_names[(word >> 12) & 0xf],
723+ (word & 0x800) ? 'l' : 'w',
724+ scales[(word >> 9) & 3]);
725+
726+ /* Handle the 68000 style of indexing. */
727+
728+ if ((word & 0x100) == 0)
729+ {
730+ print_base (basereg,
731+ ((word & 0x80) ? word | 0xff00 : word & 0xff)
732+ + ((basereg == -1) ? addr : 0),
733+ stream);
734+ fputs (buf, stream);
735+ return p;
736+ }
737+
738+ /* Handle the generalized kind. */
739+ /* First, compute the displacement to add to the base register. */
740+
741+ if (word & 0200)
742+ basereg = -2;
743+ if (word & 0100)
744+ buf[0] = 0;
745+ base_disp = 0;
746+ switch ((word >> 4) & 3)
747+ {
748+ case 2:
749+ base_disp = NEXTWORD (p);
750+ break;
751+ case 3:
752+ base_disp = NEXTLONG (p);
753+ }
754+ if (basereg == -1)
755+ base_disp += addr;
756+
757+ /* Handle single-level case (not indirect) */
758+
759+ if ((word & 7) == 0)
760+ {
761+ print_base (basereg, base_disp, stream);
762+ fputs (buf, stream);
763+ return p;
764+ }
765+
766+ /* Two level. Compute displacement to add after indirection. */
767+
768+ outer_disp = 0;
769+ switch (word & 3)
770+ {
771+ case 2:
772+ outer_disp = NEXTWORD (p);
773+ break;
774+ case 3:
775+ outer_disp = NEXTLONG (p);
776+ }
777+
778+ fprintf (stream, "%d(", outer_disp);
779+ print_base (basereg, base_disp, stream);
780+
781+ /* If postindexed, print the closeparen before the index. */
782+ if (word & 4)
783+ fprintf (stream, ")%s", buf);
784+ /* If preindexed, print the closeparen after the index. */
785+ else
786+ fprintf (stream, "%s)", buf);
787+
788+ return p;
789+}
790+
791+/* Print a base register REGNO and displacement DISP, on STREAM.
792+ REGNO = -1 for pc, -2 for none (suppressed). */
793+
794+static void
795+print_base (regno, disp, stream)
796+ int regno;
797+ int disp;
798+ FILE *stream;
799+{
800+ if (regno == -2)
801+ fprintf (stream, "%d", disp);
802+ else if (regno == -1)
803+ fprintf (stream, "0x%x", (unsigned) disp);
804+ else
805+ fprintf (stream, "%d(%s)", disp, reg_names[regno]);
806+}
--- /dev/null
+++ b/binutils/nm.c
@@ -0,0 +1,387 @@
1+/*** nm.c -- Describe symbol table of a rel file. */
2+#include "sysdep.h"
3+#include "bfd.h"
4+#include "getopt.h"
5+#include "stab.gnu.h"
6+#include <ranlib.h>
7+
8+
9+
10+PROTO(static boolean, display_file, (char *filename));
11+PROTO(static boolean, do_one_rel_file, (bfd *file));
12+PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms,
13+ unsigned long symcount));
14+
15+PROTO(static void, print_symbols, (bfd *file, asymbol **syms,
16+ unsigned long symcount));
17+extern PROTO(int, (*sorters[2][2]), (char *x, char *y));
18+PROTO(static void, print_symdef_entry, (bfd * abfd));
19+
20+/* Command options. */
21+
22+int external_only = 0; /* print external symbols only */
23+int file_on_each_line = 0; /* print file name on each line */
24+int no_sort = 0; /* don't sort; print syms in order found */
25+int print_debug_syms = 0; /* print debugger-only symbols too */
26+int print_armap = 0; /* describe __.SYMDEF data in archive files. */
27+int reverse_sort = 0; /* sort in downward(alpha or numeric) order */
28+int sort_numerically = 0; /* sort in numeric rather than alpha order */
29+int undefined_only = 0; /* print undefined symbols only */
30+
31+boolean print_each_filename = false; /* Ick. Used in archives. */
32+
33+/* IMPORT */
34+extern char *program_name;
35+extern char *program_version;
36+extern char *target;
37+
38+struct option long_options[] = {
39+ {"debug-syms", 0, &print_debug_syms, 1},
40+ {"extern-only", 0, &external_only, 1},
41+ {"no-sort", 0, &no_sort, 1},
42+ {"numeric-sort", 0, &sort_numerically, 1},
43+ {"print-armap", 0, &print_armap, 1},
44+ {"print-file-name", 0, &file_on_each_line, 1},
45+ {"reverse-sort", 0, &reverse_sort, 1},
46+ {"target", 2, NULL, NULL},
47+ {"undefined-only", 0, &undefined_only, 1},
48+ {0, 0, 0, 0}
49+};
50+
51+/* Some error-reporting functions */
52+
53+void
54+usage ()
55+{
56+ fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
57+ program_version, program_name);
58+ exit(0);
59+}
60+
61+int
62+main (argc, argv)
63+ int argc;
64+ char **argv;
65+{
66+ int c; /* sez which option char */
67+ int ind = 0; /* used by getopt and ignored by us */
68+ extern int optind; /* steps thru options */
69+
70+ program_name = *argv;
71+
72+ while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &ind)) != EOF) {
73+ switch (c) {
74+ case 'a': print_debug_syms = 1; break;
75+ case 'g': external_only = 1; break;
76+ case 'n': sort_numerically = 1; break;
77+ case 'o': file_on_each_line = 1; break;
78+ case 'p': no_sort = 1; break;
79+ case 'r': reverse_sort = 1; break;
80+ case 's': print_armap = 1; break;
81+ case 'u': undefined_only = 1; break;
82+
83+ case 0:
84+ if (!strcmp("target",(long_options[option_index]).name)) {
85+ target = optarg;
86+ }
87+
88+ break; /* we've been given a long option */
89+
90+ default:
91+ usage ();
92+ }
93+ }
94+
95+ /* Strangely, for the shell you should return only a nonzero value
96+ on sucess -- the inverse of the C sense. */
97+
98+ /* OK, all options now parsed. If no filename specified, do a.out. */
99+ if (optind == argc) return !display_file ("a.out");
100+
101+ /* We were given several filenames to do: */
102+ while (optind < argc)
103+ if (!display_file (argv[optind++])) return 1;
104+
105+ return 0;
106+}
107+
108+/** Display a file's stats */
109+
110+/* goto here is marginally cleaner than the nested if syntax */
111+
112+static boolean
113+display_file (filename)
114+ char *filename;
115+{
116+ boolean retval = false;
117+ bfd *file;
118+ bfd *arfile = NULL;
119+
120+ file = bfd_openr(filename, target);
121+ if (file == NULL) {
122+ bfd_fatal (filename);
123+ }
124+
125+ if (bfd_check_format(file, bfd_object)) {
126+ retval = do_one_rel_file (file);
127+ goto closer;
128+ }
129+
130+ if (!bfd_check_format (file, bfd_archive)) {
131+ fprintf (stderr, "%s: %s: unknown format.\n", program_name, filename);
132+ retval = false;
133+ goto closer;
134+ }
135+
136+ printf("In archive %s:\n", filename);
137+ if (print_armap) print_symdef_entry (file);
138+ for (;;) {
139+ arfile = bfd_openr_next_archived_file (file, arfile);
140+
141+ if (arfile == NULL) {
142+ if (bfd_error != no_more_archived_files)
143+ bfd_fatal (filename);
144+ goto closer;
145+ }
146+
147+ if (!bfd_check_format(arfile, bfd_object))
148+ printf("%s: not an object file\n", arfile->filename);
149+ else {
150+ printf ("\n%s:\n", arfile->filename);
151+ if (!do_one_rel_file (arfile)) return false;
152+ }
153+ }
154+
155+ closer:
156+ if (bfd_close(file) == false)
157+ bfd_fatal (filename);
158+
159+ return retval;
160+}
161+
162+
163+static boolean
164+do_one_rel_file (abfd)
165+ bfd *abfd;
166+{
167+ unsigned int storage;
168+ asymbol **syms;
169+ unsigned int symcount = 0;
170+
171+ if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
172+ (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
173+ return true;
174+ }
175+
176+
177+ storage = get_symtab_upper_bound (abfd);
178+ if (storage == 0) {
179+ nosymz:
180+ fprintf (stderr, "%s: Symflags set but there are none?\n",
181+ bfd_get_filename (abfd));
182+ exit (1);
183+ }
184+
185+ syms = (asymbol **) xmalloc (storage);
186+
187+ symcount = bfd_canonicalize_symtab (abfd, syms);
188+ if (symcount == 0) goto nosymz;
189+
190+ /* Discard the symbols we don't want to print.
191+ It's OK to do this in place; we'll free the storage anyway
192+ (after printing) */
193+
194+ symcount = filter_symbols (abfd, syms, symcount);
195+
196+ if (!no_sort)
197+ qsort((char *) syms, symcount, sizeof (asymbol *),
198+ sorters[sort_numerically][reverse_sort]);
199+
200+ if (print_each_filename && !file_on_each_line)
201+ printf("\n%s:\n", bfd_get_filename(abfd));
202+
203+ print_symbols (abfd, syms, symcount);
204+ free (syms);
205+ return true;
206+}
207+
208+/* Symbol-sorting predicates */
209+#define valueof(x) ((x)->section ? (x)->section->vma + (x)->value : (x)->value)
210+int
211+numeric_forward (x, y)
212+ char *x;
213+ char *y;
214+{
215+
216+ return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));;
217+}
218+
219+int
220+numeric_reverse (x, y)
221+ char *x;
222+ char *y;
223+{
224+ return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
225+
226+}
227+
228+int
229+non_numeric_forward (x, y)
230+ char *x;
231+ char *y;
232+{
233+ char *xn = (*(asymbol **) x)->name;
234+ char *yn = (*(asymbol **) y)->name;
235+
236+ return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
237+ ((yn == NULL) ? 1 : strcmp (xn, yn)));
238+}
239+
240+int
241+non_numeric_reverse (x, y)
242+ char *x;
243+ char *y;
244+{
245+ return -(non_numeric_forward (x, y));
246+}
247+
248+int (*sorters[2][2])() = {
249+ {non_numeric_forward, non_numeric_reverse},
250+ {numeric_forward, numeric_reverse},
251+};
252+
253+
254+/* Choose which symbol entries to print;
255+ compact them downward to get rid of the rest.
256+ Return the number of symbols to be printed. */
257+static unsigned int
258+filter_symbols (abfd, syms, symcount)
259+ bfd *abfd;
260+ asymbol **syms;
261+ unsigned long symcount;
262+{
263+ asymbol **from, **to;
264+ unsigned int dst_count = 0;
265+ unsigned int src_count;
266+ for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
267+ int keep = 0;
268+ flagword flags = (from[src_count])->flags;
269+
270+ if (undefined_only) {
271+ keep = (flags & BSF_UNDEFINED);
272+ } else if (external_only) {
273+ keep = ((flags & BSF_GLOBAL) || (flags & BSF_UNDEFINED) ||
274+ (flags & BSF_FORT_COMM));
275+ } else {
276+ keep = 1;
277+ }
278+
279+ if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
280+ keep = 0;
281+ }
282+
283+ if (keep) {
284+ to[dst_count++] = from[src_count];
285+ }
286+ }
287+
288+ return dst_count;
289+}
290+
291+
292+/* Return a lower-case character corresponding to the symbol class of sym */
293+char
294+decode_symclass (sym)
295+ asymbol *sym;
296+{
297+ flagword flags = sym->flags;
298+
299+ if ((sym->value == 0) && (sym->section != NULL))
300+ /* Huh? All section names don't begin with "." */
301+ return (sym->section->name)[1];
302+
303+ if (flags & BSF_FORT_COMM) return 'C';
304+ if (flags & BSF_UNDEFINED) return 'U';
305+ if (flags & BSF_ABSOLUTE) return 'a';
306+
307+
308+ if ( (flags & BSF_GLOBAL) || (flags & BSF_LOCAL) ){
309+ if ( !strcmp(sym->section->name, ".text") ){
310+ return 't';
311+ } else if ( !strcmp(sym->section->name, ".data") ){
312+ return 'd';
313+ } else if ( !strcmp(sym->section->name, ".bss") ){
314+ return 'b';
315+ } else {
316+ return 'o';
317+ }
318+ }
319+
320+ /* We don't have to handle these cases just yet, but we will soon:
321+ N_SETV: 'v';
322+ N_SETA: 'l';
323+ N_SETT: 'x';
324+ N_SETD: 'z';
325+ N_SETB: 's';
326+ N_INDR: 'i';
327+ */
328+
329+ return '?';
330+}
331+
332+static void
333+print_symbols (abfd, syms, symcount)
334+ bfd *abfd;
335+ asymbol **syms;
336+ unsigned long symcount;
337+{
338+ asymbol **sym = syms, **end = syms + symcount;
339+ char class;
340+
341+ for (; sym < end; ++sym) {
342+ if (file_on_each_line) printf("%s:", bfd_get_filename(abfd));
343+
344+ if (undefined_only) {
345+ if ((*sym)->flags & BSF_UNDEFINED)
346+ puts ((*sym)->name);
347+ }
348+ else {
349+ asymbol *p = *sym;
350+ if (p) {
351+ class = decode_symclass (p);
352+
353+ if (p->flags & BSF_GLOBAL)
354+ class = toupper (class);
355+
356+ if (p->value || ((p->flags & BSF_UNDEFINED) != BSF_UNDEFINED))
357+ printf ("%08lx ", (p->section ? p->value + p->section->vma : p->value));
358+ else fputs (" ", stdout);
359+
360+ printf ("%c %s\n", class, p->name);
361+ }
362+ }
363+ }
364+}
365+
366+static void
367+print_symdef_entry (abfd)
368+ bfd * abfd;
369+{
370+ symindex idx = BFD_NO_MORE_SYMBOLS;
371+ carsym *thesym;
372+ boolean everprinted = false;
373+
374+ for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
375+ idx != BFD_NO_MORE_SYMBOLS;
376+ idx = bfd_get_next_mapent (abfd, idx, &thesym)) {
377+ bfd *elt;
378+ if (!everprinted) {
379+ printf ("\nArchive index:\n");
380+ everprinted = true;
381+ }
382+ elt = bfd_get_elt_at_index (abfd, idx);
383+ if (thesym->name != (char *)NULL) {
384+ printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
385+}
386+ }
387+}
--- /dev/null
+++ b/binutils/objdump.c
@@ -0,0 +1,714 @@
1+/*** objdump.c -- dump information about an object file. */
2+
3+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
4+
5+This file is part of BFD, the Binary File Diddler.
6+
7+BFD is free software; you can redistribute it and/or modify
8+it under the terms of the GNU General Public License as published by
9+the Free Software Foundation; either version 1, or (at your option)
10+any later version.
11+
12+BFD is distributed in the hope that it will be useful,
13+but WITHOUT ANY WARRANTY; without even the implied warranty of
14+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+GNU General Public License for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with BFD; see the file COPYING. If not, write to
19+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+/*
22+ $Id$
23+ $Log$
24+ Revision 1.1 1991/03/21 21:26:48 gumby
25+ Initial revision
26+
27+ * Revision 1.2 1991/03/15 18:34:14 rich
28+ * foo
29+ *
30+ * Revision 1.1 1991/03/13 00:34:19 chrisb
31+ * Initial revision
32+ *
33+ * Revision 1.9 1991/03/09 04:36:33 rich
34+ * Modified Files:
35+ * sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
36+ * binutils.h
37+ *
38+ * Pulled sysdep.h out of bfd.h.
39+ *
40+ * Revision 1.8 1991/03/09 03:42:01 rich
41+ * Modified Files:
42+ * Makefile alloca.c ar.c i960-pinsn.c nm.c objdump.c ostrip.c
43+ * strip.c
44+ *
45+ * Ports for intel960 group Portland.
46+ *
47+ * Revision 1.7 1991/03/08 21:54:47 rich
48+ * Modified Files:
49+ * Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
50+ * i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
51+ * sparc-pinsn.c strip.c
52+ *
53+ * Verifying Portland tree with steve's last changes. Also, some partial
54+ * porting.
55+ *
56+ * Revision 1.6 1991/03/08 07:46:26 sac
57+ * Added -l option to disassembly - prints line numbers too.
58+ *
59+ * Revision 1.5 1991/03/07 21:50:24 sac
60+ * More intelligent reloc printing
61+ *
62+ * Revision 1.4 1991/03/05 16:36:54 sac
63+ * Fixed bug where empty symbols would print (null) on suns and crash elsewhere.
64+ *
65+*/
66+/*
67+ * Until there is other documentation, refer to the manual page dump(1) in
68+ * the system 5 program's reference manual
69+ */
70+
71+#include "sysdep.h"
72+#include "bfd.h"
73+#include "getopt.h"
74+#include <stdio.h>
75+#include <ctype.h>
76+
77+char *malloc();
78+char *realloc();
79+char *xmalloc();
80+
81+char *default_target = NULL; /* default at runtime */
82+
83+char *program_name = NULL;
84+
85+int dump_section_contents; /* -s */
86+int dump_section_headers; /* -h */
87+boolean dump_file_header; /* -f */
88+int dump_symtab; /* -t */
89+int dump_reloc_info; /* -r */
90+int dump_ar_hdrs; /* -a */
91+int with_line_numbers; /* -l */
92+boolean disassemble; /* -d */
93+char *only;
94+
95+PROTO (void, display_file, (char *filename, char *target));
96+PROTO (void, dump_data, (bfd *abfd));
97+PROTO (void, dump_relocs, (bfd *abfd));
98+PROTO (void, dump_symbols, (bfd *abfd));
99+PROTO (void, print_arelt_descr, (bfd *abfd, boolean verbose));
100+
101+
102+
103+
104+
105+
106+
107+char *machine = (char *)NULL;
108+ asymbol **syms;
109+ asymbol **syms2;
110+
111+
112+unsigned int storage;
113+
114+unsigned int symcount = 0;
115+
116+void
117+usage ()
118+{
119+ fprintf (stderr,
120+ "usage: %s [-ahfdrtxsl] [-m machine] [-j section_name] obj ...\n",
121+ program_name);
122+ exit (1);
123+}
124+
125+static struct option long_options[] =
126+ {{"syms", 0, &dump_symtab, 1},
127+ {"reloc", 0, &dump_reloc_info, 1},
128+ {"header", 0, &dump_section_headers, 1},
129+ {0, 0, 0, 0}};
130+
131+
132+
133+static void
134+dump_headers(abfd)
135+bfd *abfd;
136+{
137+ asection *section;
138+ for (section = abfd->sections;
139+ section != (asection *) NULL;
140+ section = section->next)
141+ {
142+ char *comma = "";
143+#define PF(x,y) \
144+ if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; }
145+
146+ printf("SECTION %d [%s]\t: size %08x",
147+ section->index,
148+ section->name,
149+(unsigned) section->size);
150+ printf(" vma %08lx align 2**%2u\n ",
151+ section->vma,
152+ section->alignment_power);
153+ PF(SEC_ALLOC,"ALLOC");
154+ PF(SEC_LOAD,"LOAD");
155+ PF(SEC_RELOC,"RELOC");
156+ PF(SEC_BALIGN,"BALIGN");
157+ PF(SEC_READONLY,"READONLY");
158+ PF(SEC_CODE,"CODE");
159+ PF(SEC_DATA,"DATA");
160+ PF(SEC_ROM,"ROM");
161+ printf("\n");
162+#undef PF
163+ }
164+}
165+
166+static asymbol **
167+slurp_symtab(abfd)
168+bfd *abfd;
169+{
170+ asymbol **sy;
171+ if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
172+ (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
173+ return(NULL);
174+ }
175+
176+ storage = get_symtab_upper_bound (abfd);
177+ if (storage) {
178+ sy = (asymbol **) malloc (storage);
179+ if (sy == NULL) {
180+ fprintf (stderr, "%s: out of memory.\n", program_name);
181+ exit (1);
182+ }
183+ }
184+ symcount = bfd_canonicalize_symtab (abfd, sy);
185+return sy;
186+}
187+/* Sort symbols into value order */
188+static int comp(ap,bp)
189+asymbol **ap;
190+asymbol **bp;
191+{
192+ asymbol *a = *ap;
193+ asymbol *b = *bp;
194+ int diff;
195+
196+ if ( a->name== (char *)NULL || (a->flags &( BSF_DEBUGGING| BSF_UNDEFINED) ))
197+ a->the_bfd = 0;
198+ if ( b->name== (char *)NULL || (b->flags &( BSF_DEBUGGING|BSF_UNDEFINED)))
199+ b->the_bfd =0;
200+
201+ diff = a->the_bfd - b->the_bfd;
202+ if (diff) {
203+ return -diff;
204+ }
205+ diff = a->value - b->value;
206+ if (diff) {
207+ return diff;
208+ }
209+ return a->section - b->section;
210+}
211+
212+/* Print the supplied address symbolically if possible */
213+void
214+print_address(vma, stream)
215+bfd_vma vma;
216+FILE *stream;
217+{
218+ /* Perform a binary search looking for the closest symbol to
219+ the required value */
220+
221+ unsigned int min = 0;
222+ unsigned int max = symcount;
223+
224+ unsigned int thisplace = 1;
225+ unsigned int oldthisplace ;
226+
227+ int vardiff;
228+ if (symcount == 0)
229+ fprintf(stream,"%08lx", vma);
230+ else {
231+ while (true) {
232+ oldthisplace = thisplace;
233+ thisplace = (max + min )/2 ;
234+ if (thisplace == oldthisplace) break;
235+
236+
237+ vardiff = syms[thisplace]->value - vma;
238+
239+ if (vardiff) {
240+ if (vardiff > 0) {
241+ max = thisplace;
242+ }
243+ else {
244+ min = thisplace;
245+ }
246+ }
247+ else {
248+ /* Totally awesome! the exact right symbol */
249+ fprintf(stream,"%08lx (%s)", vma, syms[thisplace]->name);
250+ return;
251+ }
252+ }
253+ /* We've run out of places to look, print the symbol before this one */
254+ /* see if this or the symbol before describes this location the best */
255+
256+ if (thisplace != 0) {
257+ if (syms[thisplace-1]->value - vma >
258+ syms[thisplace]->value-vma) {
259+ /* Previous symbol is in correct section and is closer */
260+ thisplace --;
261+ }
262+ }
263+
264+ {
265+ char *section_name;
266+ asection *sec = syms[thisplace]->section;
267+ if (sec) {
268+ section_name = sec->name;
269+ }
270+ else {
271+ section_name = "abs";
272+ }
273+ }
274+ if (syms[thisplace]->value > vma) {
275+ fprintf(stream,"%08lx (%s-%lx)", vma, syms[thisplace]->name,
276+ syms[thisplace]->value - vma);
277+
278+ }
279+ else {
280+ fprintf(stream,"%08lx (%s+%lx)", vma,
281+ syms[thisplace]->name,
282+ vma - syms[thisplace]->value);
283+ }
284+ }
285+}
286+
287+void
288+disassemble_data(abfd)
289+bfd *abfd;
290+{
291+ bfd_byte *data = NULL;
292+ unsigned int datasize = 0;
293+ unsigned int i;
294+ int (*print)() ;
295+ int print_insn_m68k();
296+ int print_insn_i960();
297+ int print_insn_sparc();
298+ enum bfd_architecture a;
299+ unsigned long m;
300+ asection *section;
301+ /* Replace symbol section relative values with abs values */
302+
303+
304+ for (i = 0; i < symcount; i++) {
305+ if (syms[i]->section != (asection *)NULL) {
306+ syms[i]->value += syms[i]->section->vma;
307+ }
308+ }
309+
310+ /* We keep a copy of the symbols in the original order */
311+ syms2 = slurp_symtab(abfd);
312+
313+ /* Sort the symbols into section and symbol order */
314+ (void) qsort(syms, symcount, sizeof(asymbol *), comp);
315+
316+ /* Find the first useless symbol */
317+ { unsigned int i;
318+ for (i =0; i < symcount; i++) {
319+ if (syms[i]->the_bfd == 0) {
320+ symcount =i;
321+ break;
322+ }
323+ }
324+ }
325+
326+
327+ if (machine!= (char *)NULL) {
328+ if (bfd_scan_arch_mach(machine, &a, &m) == false) {
329+ fprintf(stderr,"%s: Can't use supplied machine %s\n",
330+ program_name,
331+ machine);
332+ exit(1);
333+ }
334+ }
335+ else {
336+ a = bfd_get_architecture(abfd);
337+ }
338+ switch (a) {
339+
340+ case bfd_arch_sparc:
341+ print = print_insn_sparc;
342+ break;
343+ case bfd_arch_m68k:
344+ print = print_insn_m68k;
345+ break;
346+ case bfd_arch_i960:
347+ print = print_insn_i960;
348+ break;
349+ default:
350+ fprintf(stderr,"%s: Can't disassemble for architecture %s\n",
351+ program_name,
352+ bfd_printable_arch_mach(bfd_get_architecture(abfd),0));
353+ exit(1);
354+ }
355+
356+
357+ for (section = abfd->sections;
358+ section != (asection *)NULL;
359+ section = section->next) {
360+
361+ if (only == (char *)NULL || strcmp(only,section->name) == 0){
362+ printf("Disassembly of section %s:\n", section->name);
363+
364+ if (section->size == 0) continue;
365+
366+ data = (bfd_byte *)malloc(section->size);
367+
368+ if (data == (bfd_byte *)NULL) {
369+ fprintf (stderr, "%s: memory exhausted.\n", program_name);
370+ exit (1);
371+ }
372+ datasize = section->size;
373+
374+
375+ bfd_get_section_contents (abfd, section, data, 0, section->size);
376+
377+ i = 0;
378+ while ((size_t)i <section->size) {
379+ if (with_line_numbers) {
380+ static prevline;
381+ char *filename;
382+ char *functionname;
383+ int line;
384+ bfd_find_nearest_line(abfd,
385+ section,
386+ syms,
387+ section->vma + i,
388+ &filename,
389+ &functionname,
390+ &line);
391+
392+ if (filename && functionname && line && line != prevline) {
393+ printf("%s:%d\n", filename, line);
394+ prevline = line;
395+ }
396+ }
397+ print_address(section->vma + i, stdout);
398+ printf(" ");
399+
400+ i += print(section->vma + i,
401+ data + i,
402+ stdout);
403+ putchar ('\n') ;
404+ }
405+
406+
407+
408+
409+ free(data);
410+ }
411+ }
412+}
413+
414+void
415+display_bfd (abfd)
416+ bfd *abfd;
417+{
418+
419+ if (!bfd_check_format (abfd, bfd_object)) {
420+ fprintf (stderr,"%s: %s not an object file\n", program_name,
421+ abfd->filename);
422+ return;
423+ }
424+ printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name);
425+ if (dump_ar_hdrs) print_arelt_descr (abfd, true);
426+
427+ if (dump_file_header) {
428+ char *comma = "";
429+
430+ printf("architecture: %s, ",
431+ bfd_printable_arch_mach (bfd_get_architecture (abfd),
432+ bfd_get_machine (abfd)));
433+ printf("flags 0x%08x:\n", abfd->flags);
434+
435+#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
436+ PF(HAS_RELOC, "HAS_RELOC");
437+ PF(EXEC_P, "EXEC_P");
438+ PF(HAS_LINENO, "HAS_LINENO");
439+ PF(HAS_DEBUG, "HAS_DEBUG");
440+ PF(HAS_SYMS, "HAS_SYMS");
441+ PF(HAS_LOCALS, "HAS_LOCALS");
442+ PF(DYNAMIC, "DYNAMIC");
443+ PF(WP_TEXT, "WP_TEXT");
444+ PF(D_PAGED, "D_PAGED");
445+ printf("\nstart address 0x%08lx", abfd->start_address);
446+ }
447+ printf("\n");
448+
449+ if (dump_section_headers)
450+ dump_headers(abfd);
451+ if (dump_symtab || dump_reloc_info || disassemble) {
452+syms = slurp_symtab(abfd);
453+ }
454+ if (dump_symtab) dump_symbols (abfd);
455+ if (dump_reloc_info) dump_relocs(abfd);
456+ if (dump_section_contents) dump_data (abfd);
457+ if (disassemble) disassemble_data(abfd);
458+}
459+
460+void
461+display_file (filename, target)
462+ char *filename;
463+ char *target;
464+{
465+ bfd *file, *arfile = (bfd *) NULL;
466+
467+ file = bfd_openr (filename, target);
468+ if (file == NULL) {
469+ bfd_perror (filename);
470+ return;
471+ }
472+
473+ if (bfd_check_format (file, bfd_archive) == true) {
474+ printf ("In archive %s:\n", bfd_get_filename (file));
475+ for(;;) {
476+ bfd_error = no_error;
477+
478+ arfile = bfd_openr_next_archived_file (file, arfile);
479+ if (arfile == NULL) {
480+ if (bfd_error != no_more_archived_files)
481+ bfd_perror (bfd_get_filename(file));
482+ return;
483+ }
484+
485+ display_bfd (arfile);
486+ /* Don't close the archive elements; we need them for next_archive */
487+ }
488+ }
489+ else
490+ display_bfd(file);
491+
492+ bfd_close(file);
493+}
494+
495+/* Actually display the various requested regions */
496+
497+
498+
499+
500+
501+
502+
503+
504+
505+
506+void
507+dump_data (abfd)
508+ bfd *abfd;
509+{
510+ asection *section;
511+ bfd_byte *data ;
512+ unsigned int datasize = 0;
513+ size_t i;
514+
515+ for (section = abfd->sections; section != NULL; section =
516+ section->next) {
517+ int onaline = 16;
518+
519+ if (only == (char *)NULL ||
520+ strcmp(only,section->name) == 0){
521+
522+
523+
524+ printf("Contents of section %s:\n", section->name);
525+
526+ if (section->size == 0) continue;
527+ data = (bfd_byte *)malloc(section->size);
528+ if (data == (bfd_byte *)NULL) {
529+ fprintf (stderr, "%s: memory exhausted.\n", program_name);
530+ exit (1);
531+ }
532+ datasize = section->size;
533+
534+
535+ bfd_get_section_contents (abfd, section, data, 0, section->size);
536+
537+ for (i= 0; i < section->size; i += onaline) {
538+ size_t j;
539+ printf(" %04lx ", i + section->vma);
540+ for (j = i; j < i+ onaline; j++) {
541+ if (j < section->size)
542+ printf("%02x", (unsigned)(data[j]));
543+ else
544+ printf(" ");
545+ if ((j & 3 ) == 3) printf(" ");
546+ }
547+
548+ printf(" ");
549+ for (j = i; j < i+onaline ; j++) {
550+ if (j >= section->size)
551+ printf(" ");
552+ else
553+ printf("%c", isprint(data[j]) ?data[j] : '.');
554+ }
555+ putchar ('\n');
556+ }
557+ }
558+
559+ free (data);
560+ }
561+}
562+
563+
564+
565+/* Should perhaps share code and display with nm? */
566+void
567+dump_symbols (abfd)
568+ bfd *abfd;
569+{
570+
571+ unsigned int count;
572+ asymbol **current = syms;
573+ printf("SYMBOL TABLE:\n");
574+
575+ for (count = 0; count < symcount; count++) {
576+ if ((*current)->the_bfd) {
577+ bfd_print_symbol((*current)->the_bfd,
578+ stdout,
579+ *current, bfd_print_symbol_all_enum);
580+
581+ printf("\n");
582+ }
583+ current++;
584+ }
585+ printf("\n");
586+ printf("\n");
587+}
588+
589+
590+void
591+dump_relocs(abfd)
592+bfd *abfd;
593+{
594+ arelent **relpp;
595+ unsigned int relcount;
596+ asection *a;
597+ for (a = abfd->sections; a != (asection *)NULL; a = a->next) {
598+ printf("RELOCATION RECORDS FOR [%s]:",a->name);
599+
600+ if (get_reloc_upper_bound(abfd, a) == 0) {
601+ printf(" (none)\n\n");
602+ }
603+ else {
604+ arelent **p;
605+
606+ relpp = (arelent **) xmalloc( get_reloc_upper_bound(abfd,a) );
607+ relcount = bfd_canonicalize_reloc(abfd,a,relpp, syms);
608+ if (relcount == 0) {
609+ printf(" (none)\n\n");
610+ }
611+ else {
612+ printf("\n");
613+ printf("OFFSET TYPE VALUE \n");
614+
615+ for (p =relpp; *p != (arelent *)NULL; p++) {
616+ arelent *q = *p;
617+ char *sym_name;
618+ char *section_name = q->section == (asection *)NULL ? "*abs" :
619+ q->section->name;
620+ if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
621+ sym_name = (*(q->sym_ptr_ptr))->name ;
622+ }
623+ else {
624+ sym_name = 0;
625+ }
626+ if (sym_name) {
627+ printf("%08lx %-8s %s",
628+ q->address,
629+ q->howto->name,
630+ sym_name);
631+ }
632+ else {
633+ printf("%08lx %-8s [%s]",
634+ q->address,
635+ q->howto->name,
636+ section_name);
637+ }
638+ if (q->addend) {
639+ printf("+0x%lx(%ld)", q->addend, (long) q->addend);
640+ }
641+ printf("\n");
642+ }
643+ printf("\n\n");
644+ free(relpp);
645+ }
646+ }
647+
648+ }
649+}
650+
651+
652+/** main and like trivia */
653+int
654+main (argc, argv)
655+ int argc;
656+ char **argv;
657+{
658+ int c;
659+ extern int optind;
660+ extern char *optarg;
661+ char *target = default_target;
662+ boolean seenflag = false;
663+ int ind = 0;
664+
665+ program_name = *argv;
666+
667+ while ((c = getopt_long (argc, argv, "b:m:dlfahrtxsj:", long_options, &ind))
668+ != EOF) {
669+ seenflag = true;
670+ switch (c) {
671+ case 'm':
672+ machine = optarg;
673+ break;
674+ case 'j':
675+ only = optarg;
676+ break;
677+ case 'l':
678+ with_line_numbers = 1;
679+ break;
680+ case 'b':
681+ target = optarg;
682+ break;
683+ case 'f':
684+ dump_file_header = true;
685+ break;
686+ case 'x':
687+ dump_symtab = 1;
688+ dump_reloc_info = 1;
689+ dump_file_header = true;
690+ dump_ar_hdrs = 1;
691+ dump_section_headers = 1;
692+ break;
693+ case 0 : break; /* we've been given a long option */
694+ case 't': dump_symtab = 1; break;
695+ case 'd': disassemble = true ; break;
696+ case 's': dump_section_contents = 1; break;
697+ case 'r': dump_reloc_info = 1; break;
698+ case 'a': dump_ar_hdrs = 1; break;
699+ case 'h': dump_section_headers = 1; break;
700+ default:
701+ usage ();
702+ }
703+ }
704+
705+ if (seenflag == false)
706+ usage ();
707+
708+ if (optind == argc)
709+ display_file ("a.out", target);
710+ else
711+ for (; optind < argc;)
712+ display_file (argv[optind++], target);
713+ return 0;
714+}
--- /dev/null
+++ b/binutils/size.c
@@ -0,0 +1,320 @@
1+/*** size.c -- report size of various sections of an executable file */
2+/* Extensions/incompatibilities:
3+ o - BSD output has filenames at the end.
4+ o - BSD output can appear in different radicies.
5+ o - SysV output has less redundant whitespace. Filename comes at end.
6+ o - SysV output doesn't show VMA which is always the same as the PMA.
7+ o - We also handle core files.
8+ o - We also handle archives.
9+ If you write shell scripts which manipulate this info then you may be
10+ out of luck; there's no +predantic switch.
11+*/
12+#include "sysdep.h"
13+#include "bfd.h"
14+#include "getopt.h"
15+
16+
17+#ifndef BSD_DEFAULT
18+#define BSD_DEFAULT 1
19+#endif
20+
21+PROTO(void, display_file, (char *filename));
22+PROTO(void, print_sizes, (bfd *file));
23+
24+/* Various program options */
25+
26+enum {decimal, octal, hex} radix = decimal;
27+int berkeley_format = BSD_DEFAULT; /* 0 means use AT&T-style output */
28+int show_version = 0;
29+int show_help = 0;
30+
31+/* IMPORTS */
32+extern char *program_version;
33+extern char *program_name;
34+extern char *target;
35+
36+/** main and like trivia */
37+
38+void
39+usage ()
40+{
41+ fprintf (stderr, "size %s\nUsage: %s -{dox}{AB}V files ...\n",
42+ program_version, program_name);
43+ fputs("\t+radix={8|10|16} -- select appropriate output radix.\n\
44+\t-d -- output in decimal\n\
45+\t-o -- output in octal\n\
46+\t-x -- output in hex", stderr);
47+ fputs("\t+format={Berkeley|SysV} -- select display format.\n\
48+\t-A -- SysV(AT&T) format\n\
49+\t-B -- BSD format", stderr);
50+#if BSD_DEFAULT
51+ fputs("\t (Default is +format=Berkeley)", stderr);
52+#else
53+ fputs("\t (Default is +format=SysV)", stderr);
54+#endif
55+ fputs("\t-V, +version -- display program version, etc.\n\
56+\t+help -- this message\n", stderr);
57+ exit(1);
58+}
59+
60+struct option long_options[] = {{"radix", 1, 0, 0},
61+ {"format", 1, 0, 0},
62+ {"version", 0, &show_version, 1},
63+ {"target", 2, NULL, NULL},
64+ {"help", 0, &show_help, 1},
65+ {0, 0, 0, 0}};
66+
67+int
68+main (argc, argv)
69+ int argc;
70+ char **argv;
71+{
72+ int temp;
73+ int c; /* sez which option char */
74+ int option_index = 0;
75+ extern int optind; /* steps thru options */
76+ program_name = *argv;
77+
78+ while ((c = getopt_long(argc, argv, "ABVdox", long_options,
79+ &option_index)) != EOF)
80+ switch(c) {
81+ case 0:
82+ if (!strcmp("format",(long_options[option_index]).name)) {
83+ switch(*optarg) {
84+ case 'B': case 'b': berkeley_format = 1; break;
85+ case 'S': case 's': berkeley_format = 0; break;
86+ default: printf("Unknown option to +format: %s\n", optarg);
87+ usage();
88+ }
89+ break;
90+ }
91+
92+ if (!strcmp("target",(long_options[option_index]).name)) {
93+ target = optarg;
94+ break;
95+ }
96+
97+ if (!strcmp("radix",(long_options[option_index]).name)) {
98+#ifdef ANSI_LIBRARIES
99+ temp = strtol(optarg, NULL, 10);
100+#else
101+ temp = atol(optarg);
102+#endif
103+ switch(temp) {
104+ case 10: radix = decimal; break;
105+ case 8: radix = octal; break;
106+ case 16: radix = hex; break;
107+ default: printf("Unknown radix: %s\n", optarg);
108+ usage();
109+ }
110+ }
111+ break;
112+ case 'A': berkeley_format = 0; break;
113+ case 'B': berkeley_format = 1; break;
114+ case 'V': show_version = 1; break;
115+ case 'd': radix = decimal; break;
116+ case 'x': radix = hex; break;
117+ case 'o': radix = octal; break;
118+ case '?': usage();
119+ }
120+
121+ if (show_version) printf("%s version %s\n", program_name, program_version);
122+ if (show_help) usage();
123+
124+ if (berkeley_format)
125+#if 0 /* intel doesn't like bss/stk b/c they don't gave core files */
126+ puts((radix == octal) ? "text\tdata\tbss/stk\toct\thex\tfilename" :
127+ "text\tdata\tbss/stk\tdec\thex\tfilename");
128+#else
129+ puts((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" :
130+ "text\tdata\tbss\tdec\thex\tfilename");
131+#endif
132+ if (optind == argc)
133+ display_file ("a.out");
134+ else
135+ for (; optind < argc;)
136+ display_file (argv[optind++]);
137+
138+ return 0;
139+}
140+
141+/** Display a file's stats */
142+
143+void
144+display_bfd (abfd)
145+ bfd *abfd;
146+{
147+ char *core_cmd;
148+
149+ if (bfd_check_format(abfd, bfd_archive)) return;
150+
151+ if (bfd_check_format(abfd, bfd_object)) {
152+ print_sizes(abfd);
153+ goto done;
154+ }
155+
156+ if (bfd_check_format(abfd, bfd_core)) {
157+ print_sizes(abfd);
158+ fputs(" (core file", stdout);
159+
160+ core_cmd = bfd_core_file_failing_command(abfd);
161+ if (core_cmd) printf(" invoked as %s", core_cmd);
162+
163+ puts(")");
164+ goto done;
165+ }
166+
167+ printf("Unknown file format: %s.", bfd_get_filename(abfd));
168+
169+ done:
170+
171+
172+ printf("\n");
173+ return;
174+}
175+
176+void
177+display_file(filename)
178+ char *filename;
179+{
180+ bfd *file, *arfile = (bfd *) NULL;
181+
182+ file = bfd_openr (filename, target);
183+ if (file == NULL) {
184+ bfd_perror (filename);
185+ return;
186+ }
187+
188+ if (bfd_check_format(file, bfd_archive) == true) {
189+ for(;;) {
190+
191+ bfd_error = no_error;
192+
193+ arfile = bfd_openr_next_archived_file (file, arfile);
194+ if (arfile == NULL) {
195+ if (bfd_error != no_more_archived_files)
196+ bfd_perror (bfd_get_filename (file));
197+ return;
198+ }
199+
200+ display_bfd (arfile);
201+ /* Don't close the archive elements; we need them for next_archive */
202+ }
203+ }
204+ else
205+ display_bfd (file);
206+
207+ bfd_close (file);
208+}
209+
210+/* This is what lexical functions are for */
211+void
212+lprint_number (width, num)
213+ int width, num;
214+{
215+ printf ((radix == decimal ? "%-*d\t" :
216+ ((radix == octal) ? "%-*o\t" : "%-*x\t")), width, num);
217+}
218+
219+void
220+rprint_number(width, num)
221+ int width, num;
222+{
223+ printf ((radix == decimal ? "%*d\t" :
224+ ((radix == octal) ? "%*o\t" : "%*x\t")), width, num);
225+}
226+
227+static char *bss_section_name = ".bss";
228+static char *data_section_name = ".data";
229+static char *stack_section_name = ".stack";
230+static char *text_section_name = ".text";
231+
232+void print_berkeley_format(abfd)
233+bfd *abfd;
234+{
235+ sec_ptr bsssection = NULL;
236+ sec_ptr datasection = NULL;
237+ sec_ptr textsection = NULL;
238+ unsigned long bsssize = 0;
239+ unsigned long datasize = 0;
240+ unsigned long textsize = 0;
241+ unsigned long total = 0;
242+
243+
244+ if ((textsection = bfd_get_section_by_name (abfd, text_section_name))
245+ != NULL) {
246+ textsize = bfd_section_size (abfd, textsection);
247+ }
248+
249+ if ((datasection = bfd_get_section_by_name (abfd, data_section_name))
250+ != NULL) {
251+ datasize = bfd_section_size(abfd, datasection);
252+ }
253+
254+ if (bfd_get_format (abfd) == bfd_object) {
255+ if ((bsssection = bfd_get_section_by_name (abfd, bss_section_name))
256+ != NULL) {
257+ bsssize = bfd_section_size(abfd, bsssection);
258+ }
259+ } else {
260+ if ((bsssection = bfd_get_section_by_name (abfd, stack_section_name))
261+ != NULL) {
262+ bsssize = bfd_section_size(abfd, bsssection);
263+ }
264+ }
265+
266+ total = textsize + datasize + bsssize;
267+
268+ lprint_number (7, textsize);
269+ lprint_number (7, datasize);
270+ lprint_number (7, bsssize);
271+ printf (((radix == octal) ? "%-7o\t%-7x\t" : "%-7d\t%-7x\t"), total, total);
272+
273+ fputs(bfd_get_filename(abfd), stdout);
274+ if (abfd->my_archive) printf (" (ex %s)", abfd->my_archive->filename);
275+}
276+
277+/* I REALLY miss lexical functions! */
278+int svi_total = 0;
279+
280+void
281+sysv_internal_printer(file, sec)
282+ bfd *file;
283+ sec_ptr sec;
284+{
285+ int size = bfd_section_size (file, sec);
286+
287+ svi_total += size;
288+
289+ printf ("%-12s", bfd_section_name(file, sec));
290+ rprint_number (8, size);
291+ printf(" ");
292+ rprint_number (8, bfd_section_vma(file, sec));
293+ printf ("\n");
294+}
295+
296+void
297+print_sysv_format(file)
298+ bfd *file;
299+{
300+ svi_total = 0;
301+
302+ printf ("%s ", bfd_get_filename (file));
303+ if (file->my_archive) printf (" (ex %s)", file->my_archive->filename);
304+
305+ puts(":\nsection\t\tsize\t addr");
306+ bfd_map_over_sections (file, sysv_internal_printer, NULL);
307+
308+ printf("Total ");
309+ rprint_number(8, svi_total);
310+ printf("\n"); printf("\n");
311+}
312+
313+void
314+print_sizes(file)
315+ bfd *file;
316+{
317+ if (berkeley_format)
318+ print_berkeley_format(file);
319+ else print_sysv_format(file);
320+}
--- /dev/null
+++ b/binutils/sparc-pinsn.c
@@ -0,0 +1,490 @@
1+/* disassemble sparc instructions for objdump
2+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3+
4+
5+This file is part of the binutils.
6+
7+The binutils are free software; you can redistribute it and/or modify
8+it under the terms of the GNU General Public License as published by
9+the Free Software Foundation; either version 1, or (at your option)
10+any later version.
11+
12+The binutils are distributed in the hope that they will be useful,
13+but WITHOUT ANY WARRANTY; without even the implied warranty of
14+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+GNU General Public License for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with the binutils; see the file COPYING. If not, write to
19+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+/* $Id$
22+ $Log$
23+ Revision 1.1 1991/03/21 21:26:55 gumby
24+ Initial revision
25+
26+ * Revision 1.1 1991/03/13 00:34:40 chrisb
27+ * Initial revision
28+ *
29+ * Revision 1.3 1991/03/09 04:36:31 rich
30+ * Modified Files:
31+ * sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
32+ * binutils.h
33+ *
34+ * Pulled sysdep.h out of bfd.h.
35+ *
36+ * Revision 1.2 1991/03/08 21:54:53 rich
37+ * Modified Files:
38+ * Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
39+ * i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
40+ * sparc-pinsn.c strip.c
41+ *
42+ * Verifying Portland tree with steve's last changes. Also, some partial
43+ * porting.
44+ *
45+ * Revision 1.1 1991/02/22 16:48:04 sac
46+ * Initial revision
47+ *
48+*/
49+
50+#include <stdio.h>
51+#include "sysdep.h"
52+#include "bfd.h"
53+#include "sparc-opcode.h"
54+
55+extern int fputs();
56+extern int print_address();
57+
58+static char *reg_names[] =
59+ { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
60+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
61+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
62+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
63+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
64+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
65+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
66+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
67+ "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
68+
69+#define freg_names (&reg_names[4 * 8])
70+
71+union sparc_insn
72+ {
73+ unsigned long int code;
74+ struct
75+ {
76+ unsigned int OP:2;
77+#define op ldst.OP
78+ unsigned int RD:5;
79+#define rd ldst.RD
80+ unsigned int op3:6;
81+ unsigned int RS1:5;
82+#define rs1 ldst.RS1
83+ unsigned int i:1;
84+ unsigned int ASI:8;
85+#define asi ldst.ASI
86+ unsigned int RS2:5;
87+#define rs2 ldst.RS2
88+#define shcnt rs2
89+ } ldst;
90+ struct
91+ {
92+ unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
93+ unsigned int IMM13:13;
94+#define imm13 IMM13.IMM13
95+ } IMM13;
96+ struct
97+ {
98+ unsigned int OP:2;
99+ unsigned int a:1;
100+ unsigned int cond:4;
101+ unsigned int op2:3;
102+ unsigned int DISP22:22;
103+#define disp22 branch.DISP22
104+ } branch;
105+#define imm22 disp22
106+ struct
107+ {
108+ unsigned int OP:2;
109+ unsigned int DISP30:30;
110+#define disp30 call.DISP30
111+ } call;
112+ };
113+
114+/* Nonzero if INSN is the opcode for a delayed branch. */
115+static int
116+is_delayed_branch (insn)
117+ union sparc_insn insn;
118+{
119+ unsigned int i;
120+
121+ for (i = 0; i < NUMOPCODES; ++i)
122+ {
123+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
124+ if ((opcode->match & insn.code) == opcode->match
125+ && (opcode->lose & insn.code) == 0
126+ && (opcode->delayed))
127+ return 1;
128+ }
129+ return 0;
130+}
131+
132+static int opcodes_sorted = 0;
133+
134+/* Print one instruction from MEMADDR on STREAM. */
135+int
136+print_insn_sparc (memaddr, buffer, stream)
137+ bfd_vma memaddr;
138+ bfd_byte *buffer;
139+ FILE *stream;
140+
141+{
142+ union sparc_insn insn;
143+
144+ register unsigned int i;
145+
146+ if (!opcodes_sorted)
147+ {
148+ static int compare_opcodes ();
149+ qsort ((char *) sparc_opcodes, NUMOPCODES,
150+ sizeof (sparc_opcodes[0]), compare_opcodes);
151+ opcodes_sorted = 1;
152+ }
153+
154+memcpy(&insn,buffer, sizeof (insn));
155+
156+ for (i = 0; i < NUMOPCODES; ++i)
157+ {
158+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
159+ if ((opcode->match & insn.code) == opcode->match
160+ && (opcode->lose & insn.code) == 0)
161+ {
162+ /* Nonzero means that we have found an instruction which has
163+ the effect of adding or or'ing the imm13 field to rs1. */
164+ int imm_added_to_rs1 = 0;
165+
166+ /* Nonzero means that we have found a plus sign in the args
167+ field of the opcode table. */
168+ int found_plus = 0;
169+
170+ /* Do we have an 'or' instruction where rs1 is the same
171+ as rsd, and which has the i bit set? */
172+ if (opcode->match == 0x80102000
173+ && insn.rs1 == insn.rd)
174+ imm_added_to_rs1 = 1;
175+
176+ if (index (opcode->args, 'S') != 0)
177+ /* Reject the special case for `set'.
178+ The real `sethi' will match. */
179+ continue;
180+ if (insn.rs1 != insn.rd
181+ && index (opcode->args, 'r') != 0)
182+ /* Can't do simple format if source and dest are different. */
183+ continue;
184+
185+ fputs (opcode->name, stream);
186+
187+ {
188+ register const char *s;
189+
190+ if (opcode->args[0] != ',')
191+ fputs (" ", stream);
192+ for (s = opcode->args; *s != '\0'; ++s)
193+ {
194+ if (*s == ',')
195+ {
196+ fputs (",", stream);
197+ ++s;
198+ if (*s == 'a')
199+ {
200+ fputs ("a", stream);
201+ ++s;
202+ }
203+ fputs (" ", stream);
204+ }
205+
206+ switch (*s)
207+ {
208+ case '+':
209+ found_plus = 1;
210+
211+ /* note fall-through */
212+ default:
213+ fprintf (stream, "%c", *s);
214+ break;
215+
216+ case '#':
217+ fputs ("0", stream);
218+ break;
219+
220+#define reg(n) fprintf (stream, "%%%s", reg_names[n])
221+ case '1':
222+ case 'r':
223+ reg (insn.rs1);
224+ break;
225+
226+ case '2':
227+ reg (insn.rs2);
228+ break;
229+
230+ case 'd':
231+ reg (insn.rd);
232+ break;
233+#undef reg
234+
235+#define freg(n) fprintf (stream, "%%%s", freg_names[n])
236+ case 'e':
237+ freg (insn.rs1);
238+ break;
239+
240+ case 'f':
241+ freg (insn.rs2);
242+ break;
243+
244+ case 'g':
245+ freg (insn.rd);
246+ break;
247+#undef freg
248+
249+#define creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
250+ case 'b':
251+ creg (insn.rs1);
252+ break;
253+
254+ case 'c':
255+ creg (insn.rs2);
256+ break;
257+
258+ case 'D':
259+ creg (insn.rd);
260+ break;
261+#undef creg
262+
263+ case 'h':
264+ fprintf (stream, "%%hi(%#x)",
265+ (unsigned int) insn.imm22 << 10);
266+ break;
267+
268+ case 'i':
269+ {
270+ /* We cannot trust the compiler to sign-extend
271+ when extracting the bitfield, hence the shifts. */
272+ int imm = ((int) insn.imm13 << 19) >> 19;
273+
274+ /* Check to see whether we have a 1+i, and take
275+ note of that fact.
276+
277+ Note: because of the way we sort the table,
278+ we will be matching 1+i rather than i+1,
279+ so it is OK to assume that i is after +,
280+ not before it. */
281+ if (found_plus)
282+ imm_added_to_rs1 = 1;
283+
284+ if (imm <= 9)
285+ fprintf (stream, "%d", imm);
286+ else
287+ fprintf (stream, "%#x", (unsigned) imm);
288+ }
289+ break;
290+
291+ case 'L':
292+ print_address ((bfd_vma) memaddr + insn.disp30 * 4,
293+ stream);
294+ break;
295+
296+ case 'l':
297+ if ((insn.code >> 22) == 0)
298+ /* Special case for `unimp'. Don't try to turn
299+ it's operand into a function offset. */
300+ fprintf (stream, "%#x",
301+ (unsigned) (((int) insn.disp22 << 10) >> 10));
302+ else
303+ /* We cannot trust the compiler to sign-extend
304+ when extracting the bitfield, hence the shifts. */
305+ print_address ((bfd_vma)
306+ (memaddr
307+ + (((int) insn.disp22 << 10) >> 10) * 4),
308+ stream);
309+ break;
310+
311+ case 'A':
312+ fprintf (stream, "(%d)", (int) insn.asi);
313+ break;
314+
315+ case 'C':
316+ fputs ("%csr", stream);
317+ break;
318+
319+ case 'F':
320+ fputs ("%fsr", stream);
321+ break;
322+
323+ case 'p':
324+ fputs ("%psr", stream);
325+ break;
326+
327+ case 'q':
328+ fputs ("%fq", stream);
329+ break;
330+
331+ case 'Q':
332+ fputs ("%cq", stream);
333+ break;
334+
335+ case 't':
336+ fputs ("%tbr", stream);
337+ break;
338+
339+ case 'w':
340+ fputs ("%wim", stream);
341+ break;
342+
343+ case 'y':
344+ fputs ("%y", stream);
345+ break;
346+ }
347+ }
348+ }
349+
350+ /* If we are adding or or'ing something to rs1, then
351+ check to see whether the previous instruction was
352+ a sethi to the same register as in the sethi.
353+ If so, attempt to print the result of the add or
354+ or (in this context add and or do the same thing)
355+ and its symbolic value. */
356+ if (imm_added_to_rs1)
357+ {
358+ union sparc_insn prev_insn;
359+ int errcode;
360+
361+ memcpy(&prev_insn, buffer -4, sizeof (prev_insn));
362+
363+ if (errcode == 0)
364+ {
365+ /* If it is a delayed branch, we need to look at the
366+ instruction before the delayed branch. This handles
367+ sequences such as
368+
369+ sethi %o1, %hi(_foo), %o1
370+ call _printf
371+ or %o1, %lo(_foo), %o1
372+ */
373+
374+ if (is_delayed_branch (prev_insn))
375+ memcpy(&prev_insn, buffer - 8, sizeof(prev_insn));
376+
377+ }
378+
379+ /* If there was a problem reading memory, then assume
380+ the previous instruction was not sethi. */
381+ if (errcode == 0)
382+ {
383+ /* Is it sethi to the same register? */
384+ if ((prev_insn.code & 0xc1c00000) == 0x01000000
385+ && prev_insn.rd == insn.rs1)
386+ {
387+ fprintf (stream, "\t! ");
388+ /* We cannot trust the compiler to sign-extend
389+ when extracting the bitfield, hence the shifts. */
390+ print_address (((int) prev_insn.imm22 << 10)
391+ | (insn.imm13 << 19) >> 19, stream);
392+ }
393+ }
394+ }
395+
396+ return sizeof (insn);
397+ }
398+ }
399+
400+ fprintf ("%#8x", insn.code);
401+ return sizeof (insn);
402+}
403+
404+
405+/* Compare opcodes A and B. */
406+
407+static int
408+compare_opcodes (a, b)
409+ char *a, *b;
410+{
411+ struct sparc_opcode *op0 = (struct sparc_opcode *) a;
412+ struct sparc_opcode *op1 = (struct sparc_opcode *) b;
413+ unsigned long int match0 = op0->match, match1 = op1->match;
414+ unsigned long int lose0 = op0->lose, lose1 = op1->lose;
415+ register unsigned int i;
416+
417+ /* If a bit is set in both match and lose, there is something
418+ wrong with the opcode table. */
419+ if (match0 & lose0)
420+ {
421+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
422+ op0->name, match0, lose0);
423+ op0->lose &= ~op0->match;
424+ lose0 = op0->lose;
425+ }
426+
427+ if (match1 & lose1)
428+ {
429+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
430+ op1->name, match1, lose1);
431+ op1->lose &= ~op1->match;
432+ lose1 = op1->lose;
433+ }
434+
435+ /* Because the bits that are variable in one opcode are constant in
436+ another, it is important to order the opcodes in the right order. */
437+ for (i = 0; i < 32; ++i)
438+ {
439+ unsigned long int x = 1 << i;
440+ int x0 = (match0 & x) != 0;
441+ int x1 = (match1 & x) != 0;
442+
443+ if (x0 != x1)
444+ return x1 - x0;
445+ }
446+
447+ for (i = 0; i < 32; ++i)
448+ {
449+ unsigned long int x = 1 << i;
450+ int x0 = (lose0 & x) != 0;
451+ int x1 = (lose1 & x) != 0;
452+
453+ if (x0 != x1)
454+ return x1 - x0;
455+ }
456+
457+ /* They are functionally equal. So as long as the opcode table is
458+ valid, we can put whichever one first we want, on aesthetic grounds. */
459+ {
460+ int length_diff = strlen (op0->args) - strlen (op1->args);
461+ if (length_diff != 0)
462+ /* Put the one with fewer arguments first. */
463+ return length_diff;
464+ }
465+
466+ /* Put 1+i before i+1. */
467+ {
468+ char *p0 = (char *) index(op0->args, '+');
469+ char *p1 = (char *) index(op1->args, '+');
470+
471+ if (p0 && p1)
472+ {
473+ /* There is a plus in both operands. Note that a plus
474+ sign cannot be the first character in args,
475+ so the following [-1]'s are valid. */
476+ if (p0[-1] == 'i' && p1[1] == 'i')
477+ /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
478+ return 1;
479+ if (p0[1] == 'i' && p1[-1] == 'i')
480+ /* op0 is 1+i and op1 is i+1, so op0 goes first. */
481+ return -1;
482+ }
483+ }
484+
485+ /* They are, as far as we can tell, identical.
486+ Since qsort may have rearranged the table partially, there is
487+ no way to tell which one was first in the opcode table as
488+ written, so just say there are equal. */
489+ return 0;
490+}
--- /dev/null
+++ b/binutils/version.c
@@ -0,0 +1,5 @@
1+/*** version.c -- version number for binutils.
2+ They all change in lockstep -- it's easier that way
3+*/
4+
5+char *program_version = "1.10 (Cygnus BFD)";
--- /dev/null
+++ b/ld/Makefile
@@ -0,0 +1,182 @@
1+#
2+# Makefile for ld version 2
3+#
4+# $Id$
5+#
6+srcdir = .
7+BASEDIR = ../..
8+
9+INCLUDE = $(srcdir)/$(BASEDIR)/include-cygnus
10+INCLUDES = -I$(srcdir) -I$(INCLUDE)
11+DEBUG = -g
12+CFLAGS = $(INCLUDES) $(DEBUG)
13+
14+# go directly to ld.new in case this ld isn't capable of
15+# linking native object on this host. It can be renamed on
16+# install.
17+PROGS = ld.new
18+
19+# for self hosting
20+GNUTARGET=a.out-generic-big
21+LDEMULATION=gld
22+bfdlib=$(srcdir)/$(BASEDIR)/bfd/$(HOST)/libbfd.a
23+
24+OBJS= ldgram.o ldlex.o ldlang.o ldmain.o ldwrite.o ldexp.o ld-lnk960.o \
25+ ld-gld.o ld-gld960.o ld-emul.o ldversion.o ldmisc.o ldsym.o ldfile.o
26+
27+HEADERS=config.h ldmain.h ldmain.h ldmisc.h ldsym.h ldlang.h ldexp.h \
28+ ldlex.h ldwrite.h ldversion.h ld-emul.h ldfile.h ldgram.h ld.h
29+
30+MANSOURCES=ld.tex
31+
32+LDCSOURCES=ldlang.c ldmain.c ldwrite.c ld-lnk960.c ld-gld.c \
33+ ld-gld960.c ld-emul.c ldversion.c ldmisc.c ldexp.c ldsym.c ldfile.c
34+
35+GENERATED_SOURCES=ldgram.tab.c ldlex.c
36+GENERATED_HEADERS=ldgram.tab.h
37+
38+LDSOURCES=$(LDCSOURCES) ldgram.y ldlex.l
39+
40+#BFDSOURCES=../bfd/libbfd.c ../bfd/bfd.c ../bfd/sunos.c ../bfd/icoff.c ../bfd/b.out.c ../bfd/archive.c ../bfd/srec.c
41+
42+SOURCES= $(LDSOURCES) $(BFDSOURCES)
43+LINTSOURCES= $(LDCSOURCES) $(BFDSOURCES) $(GENERATED_SOURCES)
44+
45+all: $(PROGS)
46+
47+$(PROGS): $(OBJS)
48+# (cd ../bfd; make)
49+# LDEMULATION=gld; export LDEMULATION; GNUTARGET=a.out-generic-big;./ldok -format a.out-generic-big -o ld /lib/crt0.o $(OBJS) $(bfdlib) -lc /usr/local/lib/gcc/sparc/1.91/gnulib
50+# gld -o ld /lib/crt0.o $(OBJS) $(bfdlib) -lc /usr/local/lib/gcc/sparc/1.91/gnulib
51+ $(CC) -Bstatic -o ld.new $(OBJS) $(bfdlib)
52+
53+
54+ld1: ld
55+ gcc -v -B./ -o ld1 $(OBJS) $(bfdlib)
56+
57+ld2: ld1
58+ mv ld1 ld
59+ gcc -v -B./ -o ld2 $(OBJS) $(bfdlib)
60+
61+ld3: ld2
62+ mv ld2 ld
63+ gcc -v -B./ -o ld3 $(OBJS) $(bfdlib)
64+
65+ld.dvi:ld.tex
66+ tex ld.tex
67+
68+ldgram.o:ldgram.y
69+ yacc -d ldgram.y
70+ mv y.tab.c ldgram.tab.c
71+ $(CC) -c $(CFLAGS) ldgram.tab.c
72+ mv ldgram.tab.o ldgram.o
73+
74+ldgram.tab.h:ldgram.o
75+ cp y.tab.h ldgram.tab.h
76+
77+ldlex.c: ldlex.l ldgram.tab.h
78+ldlex.o: ldlex.c ldgram.tab.h
79+
80+ldmain.o: ldmain.c
81+ldversion.o: ldversion.c
82+ldfile.o: ldfile.c
83+ldwrite.o: ldwrite.c
84+ldlang.o: ldlang.c ldgram.tab.h
85+ld-gld.o: ld-gld.c
86+ld-gld960.o: ld-gld960.c
87+ld-emul.o:ld-emul.c
88+ld-lnk960.o:ld-lnk960.c
89+ldexp.o:ldexp.c ldgram.tab.h
90+ldmisc.o:ldmisc.c
91+ldsym.o:ldsym.c
92+
93+clean:
94+ - rm -f $(OBJS) $(GENERATED_SOURCES) $(GENERATED_HEADERS)
95+ - rm -f ld ld1 ld2
96+
97+lintlog:$(SOURCES) Makefile
98+ $(LINT) -abhxzn $(CFLAGS) $(LINTSOURCES) \
99+| grep -v "pointer casts may be troublesome" \
100+| grep -v "possible pointer alignment problem" \
101+| grep -v "ignore" \
102+| grep -v "conversion from long may lose accuracy" \
103+| grep -v "warning: constant argument to NOT" \
104+| grep -v "enumeration type clash, operator CAST" \
105+| grep -v "warning: constant in conditional context"\
106+| grep -v "archive\.c"
107+
108+
109+tags TAGS:$(SOURCES) $(HEADERS)
110+ etags -t $(SOURCES) $(HEADERS)
111+
112+release:
113+ (cd /4/steve/ld; tar cf - $(LDSOURCES) $(HEADERS) $(MANSOURCES)) | tar xf -
114+
115+objdump:objdump.c
116+
117+install: $(PROGS)
118+ rm -f $G960BASE/bin/$(PROGS)
119+ cp $(PROGS) $$G960BASE/bin/gld960c
120+
121+#-----------------------------------------------------------------------------
122+# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT
123+#
124+# 'VERSION' file must be present and contain a string of the form "x.y"
125+#-----------------------------------------------------------------------------
126+
127+ver960.c: FORCE
128+ rm -f ver960.c
129+ echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
130+
131+
132+# This target should be invoked before building a new release.
133+# 'VERSION' file must be present and contain a string of the form "x.y"
134+#
135+roll:
136+ @V=`cat VERSION` ; \
137+ MAJ=`sed 's/\..*//' VERSION` ; \
138+ MIN=`sed 's/.*\.//' VERSION` ; \
139+ V=$$MAJ.`expr $$MIN + 1` ; \
140+ rm -f VERSION ; \
141+ echo $$V >VERSION ; \
142+ echo Version $$V
143+
144+# Dummy target to force execution of dependent targets.
145+#
146+.force:
147+FORCE:
148+
149+# Target to uncomment host-specific lines in this makefile. Such lines must
150+# have the following string beginning in column 1: #__<hostname>__#
151+# Original Makefile is backed up as 'Makefile.old'.
152+#
153+# Invoke with: make make HOST=xxx
154+#
155+make:
156+ -@if test $(HOST)x = x ; then \
157+ echo 'Specify "make make HOST=???"'; \
158+ exit 1; \
159+ fi ; \
160+ grep -s "^#The next line was generated by 'make make'" Makefile; \
161+ if test $$? = 0 ; then \
162+ echo "Makefile has already been processed with 'make make'";\
163+ exit 1; \
164+ fi ; \
165+ mv -f Makefile Makefile.old; \
166+ echo "#The next line was generated by 'make make'" >Makefile ; \
167+ echo "HOST=$(HOST)" >>Makefile ; \
168+ echo >>Makefile ; \
169+ sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile
170+
171+#
172+
173+Makefile: ../common/Makefile
174+ mv Makefile Makefile.backup
175+ cp ../common/Makefile .
176+ $(MAKE) "HOST=$(HOST)" make
177+
178+### Local Variables: ***
179+### mode:fundamental ***
180+### page-delimiter: "^# " ***
181+### End: ***
182+### end of file
--- /dev/null
+++ b/ld/ld-emul.c
@@ -0,0 +1,144 @@
1+
2+
3+/* Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+This file is part of GLD, the Gnu Linker.
6+
7+GLD is free software; you can redistribute it and/or modify
8+it under the terms of the GNU General Public License as published by
9+the Free Software Foundation; either version 1, or (at your option)
10+any later version.
11+
12+GLD is distributed in the hope that it will be useful,
13+but WITHOUT ANY WARRANTY; without even the implied warranty of
14+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+GNU General Public License for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with GLD; see the file COPYING. If not, write to
19+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+/*
22+ $Id$
23+
24+ $Log$
25+ Revision 1.1 1991/03/21 21:28:19 gumby
26+ Initial revision
27+
28+ * Revision 1.1 1991/03/13 00:48:09 chrisb
29+ * Initial revision
30+ *
31+ * Revision 1.4 1991/03/10 09:31:16 rich
32+ * Modified Files:
33+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
34+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
35+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
36+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
37+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
38+ *
39+ * As of this round of changes, ld now builds on all hosts of (Intel960)
40+ * interest and copy passes my copy test on big endian hosts again.
41+ *
42+ * Revision 1.3 1991/02/22 17:14:55 sac
43+ * Added RCS keywords and copyrights
44+ *
45+*/
46+/*
47+ * clearing house for ld emulation states
48+ */
49+
50+#include "sysdep.h"
51+#include "bfd.h"
52+
53+#include "config.h"
54+#include "ld.h"
55+#include "ld-emul.h"
56+#include "ldmisc.h"
57+
58+extern ld_emulation_xfer_type ld_lnk960_emulation;
59+extern ld_emulation_xfer_type ld_gld_emulation;
60+extern ld_emulation_xfer_type ld_gld960_emulation;
61+
62+
63+
64+ld_emulation_xfer_type *ld_emulation;
65+
66+void
67+ldemul_hll(name)
68+char *name;
69+{
70+ ld_emulation->hll(name);
71+}
72+
73+
74+void ldemul_syslib(name)
75+char *name;
76+{
77+ ld_emulation->syslib(name);
78+}
79+
80+void
81+ldemul_after_parse()
82+{
83+ ld_emulation->after_parse();
84+}
85+
86+void
87+ldemul_before_parse()
88+{
89+ ld_emulation->before_parse();
90+}
91+
92+void
93+ldemul_after_allocation()
94+{
95+ ld_emulation->after_allocation();
96+}
97+
98+void
99+ldemul_before_allocation()
100+{
101+ if (ld_emulation->before_allocation) {
102+ ld_emulation->before_allocation();
103+ }
104+}
105+
106+
107+void
108+ldemul_set_output_arch()
109+{
110+ ld_emulation->set_output_arch();
111+}
112+
113+char *
114+ldemul_choose_target()
115+{
116+ return ld_emulation->choose_target();
117+}
118+
119+char *
120+ldemul_get_script()
121+{
122+ return ld_emulation->get_script();
123+}
124+
125+void
126+ldemul_choose_mode(target)
127+char *target;
128+{
129+ if (strcmp(target,LNK960_EMULATION_NAME)==0) {
130+ ld_emulation = &ld_lnk960_emulation;
131+ }
132+ else if (strcmp(target,GLD_EMULATION_NAME)==0) {
133+ ld_emulation = &ld_gld_emulation;
134+ }
135+ else if (strcmp(target,GLD960_EMULATION_NAME)==0) {
136+ ld_emulation = &ld_gld960_emulation;
137+ }
138+ else {
139+ info("%P%F unrecognised emulation mode: %s",target);
140+ }
141+}
142+
143+
144+
--- /dev/null
+++ b/ld/ld-gld.c
@@ -0,0 +1,258 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ * $Id$
21+ *
22+ * $Log$
23+ * Revision 1.1 1991/03/21 21:28:24 gumby
24+ * Initial revision
25+ *
26+ * Revision 1.2 1991/03/15 18:45:55 rich
27+ * foo
28+ *
29+ * Revision 1.1 1991/03/13 00:48:11 chrisb
30+ * Initial revision
31+ *
32+ * Revision 1.7 1991/03/10 09:31:18 rich
33+ * Modified Files:
34+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
35+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
36+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
37+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
38+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
39+ *
40+ * As of this round of changes, ld now builds on all hosts of (Intel960)
41+ * interest and copy passes my copy test on big endian hosts again.
42+ *
43+ * Revision 1.6 1991/03/09 03:23:12 sac
44+ * Added -Ur loader script.
45+ *
46+ * Revision 1.5 1991/03/06 21:59:29 sac
47+ * Completed G++ support
48+ *
49+ * Revision 1.4 1991/03/06 02:23:34 sac
50+ * Added support for partial linking.
51+ *
52+ * Revision 1.3 1991/02/22 17:14:56 sac
53+ * Added RCS keywords and copyrights
54+ *
55+*/
56+
57+/*
58+ * emulate the original gld
59+ *
60+ * Written by Steve Chamberlain steve@cygnus.com
61+ */
62+
63+
64+#include "sysdep.h"
65+#include "bfd.h"
66+
67+
68+#include "ld.h"
69+#include "config.h"
70+#include "ld-emul.h"
71+#include "ldfile.h"
72+#include "ldmisc.h"
73+
74+extern boolean lang_float_flag;
75+
76+
77+extern enum bfd_architecture ldfile_output_architecture;
78+extern unsigned long ldfile_output_machine;
79+extern char *ldfile_output_machine_name;
80+
81+extern bfd *output_bfd;
82+
83+
84+
85+static void gld_before_parse()
86+{
87+ ldfile_add_library_path("/lib");
88+ ldfile_add_library_path("/usr/lib");
89+ ldfile_add_library_path("/usr/local/lib/lib");
90+ ldfile_output_architecture = bfd_arch_sparc;
91+}
92+
93+
94+static void
95+gld_after_parse()
96+{
97+
98+}
99+
100+static void
101+gld_after_allocation()
102+{
103+
104+}
105+
106+static void
107+gld_before_allocation()
108+{
109+
110+}
111+
112+
113+static void
114+gld_set_output_arch()
115+{
116+ /* Set the output architecture and machine if possible */
117+ unsigned long machine = 0;
118+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
119+}
120+
121+static char *
122+gld_choose_target()
123+{
124+ char *from_outside = getenv(TARGET_ENVIRON);
125+ if (from_outside != (char *)NULL)
126+ return from_outside;
127+ return GLD_TARGET;
128+}
129+
130+static void
131+gld_syslib()
132+{
133+ info("%S SYSLIB ignored\n");
134+}
135+
136+static void
137+gld_hll(ignore)
138+char *ignore;
139+{
140+ info("%S HLL ignored\n");
141+}
142+
143+static char *gld_script = " \
144+SEARCH_DIR(/lib) \
145+SEARCH_DIR(/usr/lib) \
146+SEARCH_DIR(/usr/local/lib) \
147+__DYNAMIC = 0; \
148+SECTIONS \
149+{ \
150+ .text 0x2020 BLOCK(0x2000): \
151+ { \
152+ CREATE_OBJECT_SYMBOLS \
153+ *(.text) \
154+ _etext = ALIGN( 0x2000); \
155+ } \
156+ .data ALIGN(0x2000) : \
157+ { \
158+ *(.data) \
159+ ___DTOR_LIST__=. ; \
160+ LONG((___CTOR_LIST__ - .)/4 -2) \
161+ *(___DTOR_LIST__) \
162+ LONG(0) \
163+ ___CTOR_LIST__=. ; \
164+ LONG((_edata - .)/4 -2) \
165+ *(___CTOR_LIST__) \
166+ LONG(0) \
167+ _edata = .; \
168+ } \
169+ .bss SIZEOF(.data) + ADDR(.data) : \
170+ { \
171+ *(.bss) \
172+ [COMMON] \
173+ _end=.; \
174+ } \
175+}";
176+
177+
178+static char *gld_script_option_Ur = "\
179+SEARCH_DIR(/lib) \
180+SEARCH_DIR(/usr/lib) \
181+SEARCH_DIR(/usr/local/lib) \
182+SECTIONS \
183+{ \
184+ .text 0: \
185+ { \
186+ CREATE_OBJECT_SYMBOLS \
187+ *(.text) \
188+ } \
189+ .data SIZEOF(.text) + ADDR(.text) : \
190+ { \
191+ *(.data) \
192+ ___DTOR_LIST__=. ; \
193+ LONG((___CTOR_LIST__ - .)/4 -2) \
194+ *(___DTOR_LIST__) \
195+ LONG(0) \
196+ ___CTOR_LIST__=. ; \
197+ LONG((___end_list__ - .)/4 -2) \
198+ *(___CTOR_LIST__) \
199+ LONG(0) \
200+ ___end_list__ = . ; \
201+ } \
202+ .bss SIZEOF(.data) + ADDR(.data) : \
203+ { \
204+ *(.bss) \
205+ [COMMON] \
206+ } \
207+} \
208+";
209+
210+static char *gld_script_option_r = "\
211+SEARCH_DIR(/lib) \
212+SEARCH_DIR(/usr/lib) \
213+SEARCH_DIR(/usr/local/lib) \
214+SECTIONS \
215+{ \
216+ .text 0: \
217+ { \
218+ CREATE_OBJECT_SYMBOLS \
219+ *(.text) \
220+ } \
221+ .data SIZEOF(.text) + ADDR(.text) : \
222+ { \
223+ *(.data) \
224+ } \
225+ .bss SIZEOF(.data) + ADDR(.data) : \
226+ { \
227+ *(.bss) \
228+ [COMMON] \
229+ } \
230+} \
231+";
232+
233+static char *gld_get_script()
234+{
235+ extern ld_config_type config;
236+ if (config.relocateable_output == true &&
237+ config.build_constructors == true) {
238+ return gld_script_option_Ur;
239+ }
240+ if (config.relocateable_output) {
241+ return gld_script_option_r;
242+ }
243+
244+ return gld_script;
245+}
246+struct ld_emulation_xfer_struct ld_gld_emulation =
247+{
248+ gld_before_parse,
249+ gld_syslib,
250+ gld_hll,
251+ gld_after_parse,
252+ gld_after_allocation,
253+ gld_set_output_arch,
254+ gld_choose_target,
255+ gld_before_allocation,
256+ gld_get_script,
257+};
258+
--- /dev/null
+++ b/ld/ld-gld960.c
@@ -0,0 +1,189 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ $Id$
21+
22+ $Log$
23+ Revision 1.1 1991/03/21 21:28:26 gumby
24+ Initial revision
25+
26+ * Revision 1.3 1991/03/16 22:27:24 rich
27+ * fish
28+ *
29+ * Revision 1.2 1991/03/15 18:45:55 rich
30+ * foo
31+ *
32+ * Revision 1.1 1991/03/13 00:48:12 chrisb
33+ * Initial revision
34+ *
35+ * Revision 1.4 1991/03/10 09:31:19 rich
36+ * Modified Files:
37+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
38+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
39+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
40+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
41+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
42+ *
43+ * As of this round of changes, ld now builds on all hosts of (Intel960)
44+ * interest and copy passes my copy test on big endian hosts again.
45+ *
46+ * Revision 1.3 1991/02/22 17:14:57 sac
47+ * Added RCS keywords and copyrights
48+ *
49+*/
50+
51+/*
52+ * emulate the Intels port of gld
53+ */
54+
55+
56+#include "sysdep.h"
57+#include "bfd.h"
58+
59+
60+#include "ld.h"
61+#include "config.h"
62+#include "ld-emul.h"
63+#include "ldfile.h"
64+#include "ldmisc.h"
65+
66+
67+/* IMPORTS */
68+extern char *output_filename;
69+extern boolean lang_float_flag;
70+
71+
72+extern enum bfd_architecture ldfile_output_architecture;
73+extern unsigned long ldfile_output_machine;
74+extern char *ldfile_output_machine_name;
75+
76+extern bfd *output_bfd;
77+
78+
79+
80+static void gld960_before_parse()
81+{
82+ char *env ;
83+ env = getenv("G960LIB");
84+ if (env) {
85+ ldfile_add_library_path(env);
86+ }
87+ env = getenv("G960BASE");
88+ if (env) {
89+ ldfile_add_library_path(concat(env,"/lib",""));
90+ }
91+ ldfile_output_architecture = bfd_arch_i960;
92+}
93+
94+
95+static void
96+gld960_after_parse()
97+{
98+
99+}
100+
101+static void
102+gld960_after_allocation()
103+{
104+
105+}
106+
107+static void
108+gld960_before_allocation()
109+{
110+
111+}
112+
113+
114+static void
115+gld960_set_output_arch()
116+{
117+ /* Set the output architecture and machine if possible */
118+ unsigned long machine = 0;
119+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
120+}
121+
122+static char *
123+gld960_choose_target()
124+{
125+ char *from_outside = getenv(TARGET_ENVIRON);
126+ output_filename = "b.out";
127+
128+ if (from_outside != (char *)NULL)
129+ return from_outside;
130+ return GLD960_TARGET;
131+}
132+
133+static void
134+gld960_syslib()
135+{
136+ info("%S SYSLIB ignored\n");
137+}
138+
139+static void
140+gld960_hll()
141+{
142+ info("%S HLL ignored\n");
143+}
144+
145+
146+static char *script = "\
147+ \
148+SECTIONS \
149+{ \
150+ .text : \
151+ { \
152+ CREATE_OBJECT_SYMBOLS \
153+ *(.text) \
154+ _etext =.;\
155+ } \
156+ \
157+ .data SIZEOF(.text) + ADDR(.text):\
158+ { \
159+ \
160+ *(.data) \
161+ _edata = .; \
162+ } \
163+ .bss SIZEOF(.data) + ADDR(.data) : \
164+ { _bss_start = .;\
165+ *(.bss) \
166+ [COMMON] \
167+ _end = . ; \
168+ } \
169+} \
170+";
171+
172+static char *
173+gld960_get_script()
174+{
175+return script;
176+}
177+
178+struct ld_emulation_xfer_struct ld_gld960_emulation =
179+{
180+ gld960_before_parse,
181+ gld960_syslib,
182+ gld960_hll,
183+ gld960_after_parse,
184+ gld960_after_allocation,
185+ gld960_set_output_arch,
186+ gld960_choose_target,
187+ gld960_before_allocation,
188+ gld960_get_script,
189+};
--- /dev/null
+++ b/ld/ld-lnk960.c
@@ -0,0 +1,321 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ $Id$
21+
22+ $Log$
23+ Revision 1.1 1991/03/21 21:28:28 gumby
24+ Initial revision
25+
26+ * Revision 1.2 1991/03/15 18:45:55 rich
27+ * foo
28+ *
29+ * Revision 1.1 1991/03/13 00:48:13 chrisb
30+ * Initial revision
31+ *
32+ * Revision 1.6 1991/03/10 09:31:20 rich
33+ * Modified Files:
34+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
35+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
36+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
37+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
38+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
39+ *
40+ * As of this round of changes, ld now builds on all hosts of (Intel960)
41+ * interest and copy passes my copy test on big endian hosts again.
42+ *
43+ * Revision 1.5 1991/03/09 03:23:47 sac
44+ * Now looks in G960BASE if I960BASE isn't defined.
45+ *
46+ * Revision 1.4 1991/03/06 02:23:35 sac
47+ * Added support for partial linking.
48+ *
49+ * Revision 1.3 1991/02/22 17:14:58 sac
50+ * Added RCS keywords and copyrights
51+ *
52+*/
53+
54+/*
55+
56+ Written by Steve Chamberlain steve@cygnus.com
57+
58+ * intel coff loader emulation specific stuff
59+ */
60+
61+#include "sysdep.h"
62+#include "bfd.h"
63+
64+/*#include "archures.h"*/
65+#include "ld.h"
66+#include "config.h"
67+#include "ld-emul.h"
68+#include "ldmisc.h"
69+#include "ldlang.h"
70+#include "ldfile.h"
71+
72+extern boolean lang_float_flag;
73+extern bfd *output_bfd;
74+
75+
76+
77+extern enum bfd_architecture ldfile_output_architecture;
78+extern unsigned long ldfile_output_machine;
79+extern char *ldfile_output_machine_name;
80+
81+
82+typedef struct lib_list {
83+ char *name;
84+ struct lib_list *next;
85+} lib_list_type;
86+
87+static lib_list_type *hll_list;
88+static lib_list_type **hll_list_tail = &hll_list;
89+
90+static lib_list_type *syslib_list;
91+static lib_list_type **syslib_list_tail = &syslib_list;
92+
93+
94+static void
95+append(list, name)
96+lib_list_type ***list;
97+char *name;
98+{
99+ lib_list_type *element =
100+ (lib_list_type *)(ldmalloc(sizeof(lib_list_type)));
101+
102+ element->name = name;
103+ element->next = (lib_list_type *)NULL;
104+ **list = element;
105+ *list = &element->next;
106+
107+}
108+
109+static boolean had_hll = false;
110+static boolean had_hll_name = false;
111+static void
112+lnk960_hll(name)
113+char *name;
114+{
115+ had_hll = true;
116+ if (name != (char *)NULL) {
117+ had_hll_name = true;
118+ append(&hll_list_tail, name);
119+ }
120+}
121+
122+static void
123+lnk960_syslib(name)
124+char *name;
125+{
126+ append(&syslib_list_tail,name);
127+}
128+
129+
130+
131+static void
132+lnk960_before_parse()
133+{
134+ char *name = getenv("I960BASE");
135+
136+ if (name == (char *)NULL) {
137+ name = getenv("G960BASE");
138+ if (name == (char *)NULL) {
139+ info("%P%F I960BASE and G960BASE not set\n");
140+ }
141+ }
142+
143+
144+ ldfile_add_library_path(concat(name,"/lib",""));
145+ ldfile_output_architecture = bfd_arch_i960;
146+ ldfile_output_machine = bfd_mach_i960_core;
147+}
148+
149+static void
150+add_on(list, search)
151+lib_list_type *list;
152+lang_input_file_enum_type search;
153+{
154+ while (list) {
155+ lang_add_input_file(list->name,
156+ search,
157+ (char *)NULL);
158+ list = list->next;
159+ }
160+}
161+static void lnk960_after_parse()
162+{
163+
164+ /* If there has been no arch, default to -KB */
165+ if (ldfile_output_machine_name[0] ==0) {
166+ ldfile_add_arch("kb");
167+ }
168+
169+ /* if there has been no hll list then add our own */
170+
171+ if(had_hll && !had_hll_name) {
172+ append(&hll_list_tail,"c");
173+ if (lang_float_flag == true) {
174+ append(&hll_list_tail,"m");
175+ }
176+ else {
177+ append(&hll_list_tail,"mstub");
178+ }
179+ if (ldfile_output_machine == bfd_mach_i960_ka_sa ||
180+ ldfile_output_machine == bfd_mach_i960_ca) {
181+ {
182+ append(&hll_list_tail,"f");
183+ }
184+ }
185+ }
186+
187+
188+
189+ add_on(hll_list, lang_input_file_is_l_enum);
190+ add_on(syslib_list, lang_input_file_is_search_file_enum);
191+
192+
193+}
194+
195+static void
196+lnk960_before_allocation()
197+{
198+}
199+static void
200+lnk960_after_allocation()
201+{
202+ lang_abs_symbol_at_end_of(".text","_etext");
203+ lang_abs_symbol_at_end_of(".data","_edata");
204+ lang_abs_symbol_at_end_of(".bss","_end");
205+}
206+
207+static struct
208+ {
209+ unsigned long number;
210+ char *name;
211+ }
212+machine_table[] = {
213+ bfd_mach_i960_core ,"CORE",
214+ bfd_mach_i960_kb_sb ,"KB",
215+ bfd_mach_i960_kb_sb ,"SB",
216+ bfd_mach_i960_mc ,"MC",
217+ bfd_mach_i960_xa ,"XA",
218+ bfd_mach_i960_ca ,"CA",
219+ bfd_mach_i960_ka_sa ,"KA",
220+ bfd_mach_i960_ka_sa ,"SA",
221+
222+ bfd_mach_i960_core ,"core",
223+ bfd_mach_i960_kb_sb ,"kb",
224+ bfd_mach_i960_kb_sb ,"sb",
225+ bfd_mach_i960_mc ,"mc",
226+ bfd_mach_i960_xa ,"xa",
227+ bfd_mach_i960_ca ,"ca",
228+ bfd_mach_i960_ka_sa ,"ka",
229+ bfd_mach_i960_ka_sa ,"sa",
230+ 0,(char *)NULL
231+};
232+
233+static void
234+lnk960_set_output_arch()
235+{
236+ /* Set the output architecture and machine if possible */
237+ unsigned int i;
238+ ldfile_output_machine = bfd_mach_i960_core;
239+ for (i= 0; machine_table[i].name != (char*)NULL; i++) {
240+ if (strcmp(ldfile_output_machine_name,machine_table[i].name)==0) {
241+ ldfile_output_machine = machine_table[i].number;
242+ break;
243+ }
244+ }
245+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, ldfile_output_machine);
246+}
247+
248+static char *
249+lnk960_choose_target()
250+{
251+ char *from_outside = getenv(TARGET_ENVIRON);
252+ if (from_outside != (char *)NULL)
253+ return from_outside;
254+ return LNK960_TARGET;
255+}
256+
257+/* The default script if none is offered */
258+static char *lnk960_script = "\
259+SECTIONS \
260+{ \
261+ .text : \
262+ { \
263+ *(.text) \
264+ } \
265+_etext = .;\
266+ .data SIZEOF(.text) + ADDR(.text):\
267+ { \
268+ *(.data) \
269+ } \
270+_edata = .; \
271+ .bss SIZEOF(.data) + ADDR(.data) : \
272+ { \
273+ _bss_start = . ;\
274+ *(.bss) \
275+ [COMMON] \
276+ } \
277+_end = . ; \
278+} \
279+";
280+
281+static char *lnk960_script_relocateable = "\
282+SECTIONS \
283+{ \
284+ .text 0x40000000: \
285+ { \
286+ *(.text) \
287+ } \
288+ .data 0:\
289+ { \
290+ *(.data) \
291+ } \
292+ .bss SIZEOF(.data) + ADDR(.data) : \
293+ { \
294+ *(.bss) \
295+ [COMMON] \
296+ } \
297+} \
298+";
299+
300+static char *lnk960_get_script()
301+{
302+extern ld_config_type config;
303+if (config.relocateable_output) {
304+ return lnk960_script_relocateable;
305+}
306+return lnk960_script;
307+
308+
309+}
310+struct ld_emulation_xfer_struct ld_lnk960_emulation =
311+{
312+ lnk960_before_parse,
313+ lnk960_syslib,
314+ lnk960_hll,
315+ lnk960_after_parse,
316+ lnk960_after_allocation,
317+ lnk960_set_output_arch,
318+ lnk960_choose_target,
319+ lnk960_before_allocation,
320+ lnk960_get_script,
321+};
--- /dev/null
+++ b/ld/ld.h
@@ -0,0 +1,132 @@
1+/* ld.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+#define flag_is_not_at_end(x) ((x) & BSF_NOT_AT_END)
23+#define flag_is_ordinary_local(x) (((x) & (BSF_LOCAL))&!((x) & (BSF_DEBUGGING)))
24+#define flag_is_debugger(x) ((x) & BSF_DEBUGGING)
25+#define flag_is_undefined_or_global(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL))
26+#define flag_is_defined(x) (!((x) & (BSF_UNDEFINED)))
27+#define flag_is_global_or_common(x) ((x) & (BSF_GLOBAL | BSF_FORT_COMM))
28+#define flag_is_undefined_or_global_or_common(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM))
29+#define flag_is_common(x) ((x) & BSF_FORT_COMM)
30+#define flag_is_global(x) ((x) & (BSF_GLOBAL))
31+#define flag_is_undefined(x) ((x) & BSF_UNDEFINED)
32+#define flag_set(x,y) (x = y)
33+#define flag_is_fort_comm(x) ((x) & BSF_FORT_COMM)
34+#define flag_is_absolute(x) ((x) & BSF_ABSOLUTE)
35+/* Extra information we hold on sections */
36+typedef struct user_section_struct {
37+ /* Pointer to the section where this data will go */
38+ struct lang_input_statement_struct *file;
39+} section_userdata_type;
40+
41+
42+#define get_userdata(x) ((x)->userdata)
43+#define as_output_section_statement(x) ((x)->otheruserdata)
44+
45+#if 0
46+/*
47+ * Structure for communication between do_file_warnings and it's
48+ * helper routines. Will in practice be an array of three of these:
49+ * 0) Current line, 1) Next line, 2) Source file info.
50+ */
51+struct line_debug_entry
52+{
53+ int line;
54+ char *filename;
55+ struct nlist *sym;
56+};
57+
58+#endif
59+
60+
61+/* Which symbols should be stripped (omitted from the output):
62+ none, all, or debugger symbols. */
63+enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER } strip_symbols;
64+
65+
66+
67+
68+/* Which local symbols should be omitted:
69+ none, all, or those starting with L.
70+ This is irrelevant if STRIP_NONE. */
71+enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals;
72+
73+
74+
75+
76+
77+
78+#define ALIGN(this, boundary) ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
79+#if 0
80+#define FOREACHGLOBALSYMBOL(x) ldsym_type *x; for (x = symbol_head; x; x=x->next)
81+
82+
83+
84+
85+#define SECTIONLOOP(abfd, ptr) \
86+ asection *ptr; for(ptr = abfd->sections; ptr;ptr=ptr->next)
87+
88+
89+#endif
90+typedef struct {
91+
92+ /* 1 => assign space to common symbols even if `relocatable_output'. */
93+ boolean force_common_definition;
94+
95+} args_type;
96+
97+typedef int token_code_type;
98+
99+typedef struct
100+{
101+ unsigned int specified_data_size;
102+ boolean magic_demand_paged;
103+ boolean make_executable;
104+ /* 1 => write relocation into output file so can re-input it later. */
105+ boolean relocateable_output;
106+
107+ /* Will we build contstructors, or leave alone ? */
108+ boolean build_constructors;
109+ /* 1 => write relocation such that a UNIX linker can understand it.
110+ This is used mainly to finish of sets that were built. */
111+ boolean unix_relocate;
112+
113+
114+} ld_config_type;
115+#define set_asymbol_chain(x,y) ((x)->udata = (void *)y)
116+#define get_asymbol_chain(x) ((asymbol **)((x)->udata))
117+#define get_loader_symbol(x) ((loader_global_asymbol *)((x)->udata))
118+#define set_loader_symbol(x,y) ((x)->udata = (void *)y)
119+
120+
121+
122+
123+
124+
125+typedef enum {
126+ lang_first_phase_enum,
127+ lang_allocating_phase_enum,
128+ lang_final_phase_enum } lang_phase_type;
129+
130+
131+
132+
--- /dev/null
+++ b/ld/ldexp.c
@@ -0,0 +1,770 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ $Id$
21+
22+ $Log$
23+ Revision 1.1 1991/03/21 21:28:34 gumby
24+ Initial revision
25+
26+ * Revision 1.1 1991/03/13 00:48:16 chrisb
27+ * Initial revision
28+ *
29+ * Revision 1.6 1991/03/10 09:31:22 rich
30+ * Modified Files:
31+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
32+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
33+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
34+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
35+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
36+ *
37+ * As of this round of changes, ld now builds on all hosts of (Intel960)
38+ * interest and copy passes my copy test on big endian hosts again.
39+ *
40+ * Revision 1.5 1991/03/09 03:25:04 sac
41+ * Added support for LONG, SHORT and BYTE keywords in scripts
42+ *
43+ * Revision 1.4 1991/03/06 02:27:15 sac
44+ * Added LONG, SHORT and BYTE keywords
45+ *
46+ * Revision 1.3 1991/02/22 17:14:59 sac
47+ * Added RCS keywords and copyrights
48+ *
49+*/
50+
51+/*
52+ * Written by Steve Chamberlain
53+ * steve@cygnus.com
54+ *
55+ * This module handles expression trees.
56+ */
57+
58+
59+#include "sysdep.h"
60+#include "bfd.h"
61+
62+#include "ld.h"
63+#include "ldmain.h"
64+#include "ldmisc.h"
65+#include "ldexp.h"
66+#include "ldgram.tab.h"
67+#include "ldsym.h"
68+#include "ldlang.h"
69+
70+extern char *output_filename;
71+extern unsigned int undefined_global_sym_count;
72+extern unsigned int defined_global_sym_count;
73+extern bfd *output_bfd;
74+extern size_t largest_section;
75+extern lang_statement_list_type file_chain;
76+extern args_type command_line;
77+extern ld_config_type config;
78+
79+extern lang_input_statement_type *script_file;
80+extern unsigned int defined_global_sym_count;
81+
82+extern bfd_vma print_dot;
83+
84+
85+static void
86+exp_print_token(outfile, code)
87+FILE *outfile;
88+token_code_type code;
89+{
90+ static struct {
91+ token_code_type code;
92+ char *name;
93+ } table[] =
94+ {
95+ INT, "int",
96+ CHAR,"char",
97+ NAME,"NAME",
98+ PLUSEQ,"+=",
99+ MINUSEQ,"-=",
100+ MULTEQ,"*=",
101+ DIVEQ,"/=",
102+ LSHIFTEQ,"<<=",
103+ RSHIFTEQ,">>=",
104+ ANDEQ,"&=",
105+ OREQ,"|=",
106+ OROR,"||",
107+ ANDAND,"&&",
108+ EQ,"==",
109+ NE,"!=",
110+ LE,"<=",
111+ GE,">=",
112+ LSHIFT,"<<",
113+ RSHIFT,">>=",
114+ ALIGN_K,"ALIGN",
115+ BLOCK,"BLOCK",
116+ SECTIONS,"SECTIONS",
117+ ALIGNMENT,"ALIGNMENT",
118+ SIZEOF_HEADERS,"SIZEOF_HEADERS",
119+ NEXT,"NEXT",
120+ SIZEOF,"SIZEOF",
121+ ADDR,"ADDR",
122+ MEMORY,"MEMORY",
123+ DSECT,"DSECT",
124+ NOLOAD,"NOLOAD",
125+ COPY,"COPY",
126+ INFO,"INFO",
127+ OVERLAY,"OVERLAY",
128+ DEFINED,"DEFINED",
129+ TARGET_K,"TARGET",
130+ SEARCH_DIR,"SEARCH_DIR",
131+ MAP,"MAP",
132+ LONG,"LONG",
133+ SHORT,"SHORT",
134+ BYTE,"BYTE",
135+ ENTRY,"ENTRY",
136+ 0,(char *)NULL} ;
137+
138+
139+
140+ unsigned int idx;
141+ for (idx = 0; table[idx].name != (char*)NULL; idx++) {
142+ if (table[idx].code == code) {
143+ fprintf(outfile, "%s", table[idx].name);
144+ return;
145+ }
146+ }
147+ /* Not in table, just print it alone */
148+ fprintf(outfile, "%c",code);
149+}
150+
151+static void
152+make_abs(ptr)
153+etree_value_type *ptr;
154+{
155+ if (ptr->section != (lang_output_section_statement_type *)NULL) {
156+ asection *s = ptr->section->bfd_section;
157+ ptr->value += s->vma;
158+ ptr->section = (lang_output_section_statement_type *)NULL;
159+ }
160+
161+}
162+static
163+etree_value_type new_abs(value)
164+bfd_vma value;
165+{
166+ etree_value_type new;
167+ new.valid = true;
168+ new.section = (lang_output_section_statement_type *)NULL;
169+ new.value = value;
170+ return new;
171+}
172+
173+static void check(os)
174+lang_output_section_statement_type *os;
175+{
176+ if (os == (lang_output_section_statement_type *)NULL) {
177+ info("%F%P undefined section");
178+ }
179+ if (os->processed == false) {
180+ info("%F%P forward reference of section");
181+ }
182+}
183+
184+etree_type *exp_intop(value)
185+bfd_vma value;
186+{
187+ etree_type *new = (etree_type *)ldmalloc(sizeof(new->value));
188+ new->type.node_code = INT;
189+ new->value.value = value;
190+ new->type.node_class = etree_value;
191+ return new;
192+
193+}
194+
195+
196+static
197+etree_value_type new_rel(value, section)
198+bfd_vma value;
199+lang_output_section_statement_type *section;
200+{
201+ etree_value_type new;
202+ new.valid = true;
203+ new.value = value;
204+ new.section = section;
205+ return new;
206+}
207+
208+static
209+etree_value_type new_rel_from_section(value, section)
210+bfd_vma value;
211+lang_output_section_statement_type *section;
212+{
213+ etree_value_type new;
214+ new.valid = true;
215+ new.value = value;
216+ new.section = section;
217+ if (new.section != (lang_output_section_statement_type *)NULL) {
218+ new.value -= section->bfd_section->vma;
219+ }
220+ return new;
221+}
222+
223+static etree_value_type
224+fold_binary(tree, current_section, allocation_done, dot, dotp)
225+etree_type *tree;
226+lang_output_section_statement_type *current_section;
227+lang_phase_type allocation_done;
228+bfd_vma dot;
229+bfd_vma *dotp;
230+{
231+ etree_value_type result;
232+
233+ result = exp_fold_tree(tree->binary.lhs, current_section,
234+ allocation_done, dot, dotp);
235+ if (result.valid) {
236+ etree_value_type other;
237+ other = exp_fold_tree(tree->binary.rhs,
238+ current_section,
239+ allocation_done, dot,dotp) ;
240+ if (other.valid) {
241+ /* If values are from different sections, or this is an */
242+ /* absolute expression, make both source args absolute */
243+ if (result.section != other.section ||
244+ current_section == (lang_output_section_statement_type *)NULL) {
245+
246+ make_abs(&result);
247+ make_abs(&other);
248+ }
249+
250+ switch (tree->type.node_code)
251+ {
252+ case '%':
253+ /* Mod, both absolule*/
254+
255+ if (other.value == 0) {
256+ info("%F%S % by zero\n");
257+ }
258+ result.value %= other.value;
259+ break;
260+ case '/':
261+ if (other.value == 0) {
262+ info("%F%S / by zero\n");
263+ }
264+ result.value /= other.value;
265+ break;
266+#define BOP(x,y) case x : result.value = result.value y other.value;break;
267+ BOP('+',+);
268+ BOP('*',*);
269+ BOP('-',-);
270+ BOP(LSHIFT,<<);
271+ BOP(RSHIFT,>>);
272+ BOP(EQ,==);
273+ BOP(NE,!=);
274+ BOP('<',<);
275+ BOP('>',>);
276+ BOP(LE,<=);
277+ BOP(GE,>=);
278+ BOP('&',&);
279+ BOP('^',^);
280+ BOP('|',|);
281+ BOP(ANDAND,&&);
282+ BOP(OROR,||);
283+ default:
284+ FAIL();
285+ }
286+ }
287+ }
288+ return result;
289+}
290+etree_value_type invalid()
291+{
292+ etree_value_type new;
293+ new.valid = false;
294+ return new;
295+}
296+
297+etree_value_type fold_name(tree, current_section, allocation_done, dot)
298+etree_type *tree;
299+lang_output_section_statement_type *current_section;
300+lang_phase_type allocation_done;
301+bfd_vma dot;
302+
303+{
304+ etree_value_type result;
305+ switch (tree->type.node_code)
306+ {
307+ case DEFINED:
308+ result.value =
309+ ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
310+ result.section = 0;
311+ result.valid = true;
312+ break;
313+ case NAME:
314+ result.valid = false;
315+ if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
316+
317+ if (allocation_done != lang_first_phase_enum) {
318+ result = new_rel_from_section(dot, current_section);
319+ }
320+ else {
321+ result = invalid();
322+ }
323+ }
324+ else {
325+ if (allocation_done == lang_final_phase_enum) {
326+ ldsym_type *sy = ldsym_get_soft(tree->name.name);
327+
328+ if (sy) {
329+ asymbol **sdefp = sy->sdefs_chain;
330+
331+ if (sdefp) {
332+ asymbol *sdef = *sdefp;
333+ if (sdef->section == (asection *)NULL) {
334+ /* This is an absolute symbol */
335+ result = new_abs(sdef->value);
336+ }
337+ else {
338+ lang_output_section_statement_type *os =
339+ lang_output_section_statement_lookup( sdef->section->output_section->name);
340+ result = new_rel(sdef->value, os);
341+ }
342+ }
343+ }
344+ if (result.valid == false) {
345+ info("%F%S: undefined symbol `%s' referenced in expression.\n",
346+ tree->name.name);
347+ }
348+
349+ }
350+ }
351+
352+ break;
353+
354+ case ADDR:
355+
356+ if (allocation_done != lang_first_phase_enum) {
357+ lang_output_section_statement_type *os =
358+ lang_output_section_find(tree->name.name);
359+ check(os);
360+ result = new_rel((bfd_vma)0, os);
361+ }
362+ else {
363+ result = invalid();
364+ }
365+ break;
366+ case SIZEOF:
367+ if(allocation_done != lang_first_phase_enum) {
368+ lang_output_section_statement_type *os =
369+ lang_output_section_find(tree->name.name);
370+ check(os);
371+ result = new_abs((bfd_vma)(os->bfd_section->size));
372+ }
373+ else {
374+ result = invalid();
375+ }
376+ break;
377+
378+ default:
379+ FAIL();
380+ break;
381+ }
382+
383+ return result;
384+}
385+etree_value_type exp_fold_tree(tree, current_section, allocation_done,
386+ dot, dotp)
387+etree_type *tree;
388+lang_output_section_statement_type *current_section;
389+lang_phase_type allocation_done;
390+bfd_vma dot;
391+bfd_vma *dotp;
392+{
393+ etree_value_type result;
394+
395+ if (tree == (etree_type *)NULL) {
396+ result.valid = false;
397+ }
398+ else {
399+ switch (tree->type.node_class)
400+ {
401+ case etree_value:
402+ result = new_rel(tree->value.value, current_section);
403+ break;
404+ case etree_unary:
405+ result = exp_fold_tree(tree->unary.child,
406+ current_section,
407+ allocation_done, dot, dotp);
408+ if (result.valid == true)
409+ {
410+ switch(tree->type.node_code)
411+ {
412+ case ALIGN_K:
413+ if (allocation_done != lang_first_phase_enum) {
414+ result = new_rel_from_section(ALIGN(dot,
415+ result.value) ,
416+ current_section);
417+
418+ }
419+ else {
420+ result.valid = false;
421+ }
422+ break;
423+ case '-':
424+ result.value = -result.value;
425+ break;
426+ case NEXT:
427+ result.valid = false;
428+ break;
429+ default:
430+ FAIL();
431+ }
432+ }
433+
434+ break;
435+ case etree_trinary:
436+
437+ result = exp_fold_tree(tree->trinary.cond,
438+ current_section,
439+ allocation_done, dot, dotp);
440+ if (result.valid) {
441+ result = exp_fold_tree(result.value ?
442+ tree->trinary.lhs:tree->trinary.rhs,
443+ current_section,
444+ allocation_done, dot, dotp);
445+ }
446+
447+ break;
448+ case etree_binary:
449+ result = fold_binary(tree, current_section, allocation_done,
450+ dot, dotp);
451+ break;
452+ case etree_assign:
453+ if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
454+ /* Assignment to dot can only be done during allocation */
455+ if (allocation_done == lang_allocating_phase_enum) {
456+ result = exp_fold_tree(tree->assign.src,
457+ current_section,
458+ lang_allocating_phase_enum, dot, dotp);
459+ if (result.valid == false) {
460+ info("%F%S invalid assignment to location counter\n");
461+ }
462+ else {
463+ if (current_section ==
464+ (lang_output_section_statement_type *)NULL) {
465+ info("%F%S assignment to location counter invalid outside of SECTION\n");
466+ }
467+ else {
468+ unsigned long nextdot =result.value +
469+ current_section->bfd_section->vma;
470+ if (nextdot < dot) {
471+ info("%F%S cannot move location counter backwards");
472+ }
473+ else {
474+ *dotp = nextdot;
475+ }
476+ }
477+ }
478+ }
479+ }
480+ else {
481+ ldsym_type *sy = ldsym_get(tree->assign.dst);
482+
483+ /* If this symbol has just been created then we'll place it into
484+ * a section of our choice
485+ */
486+ result = exp_fold_tree(tree->assign.src,
487+ current_section, allocation_done,
488+ dot, dotp);
489+ if (result.valid)
490+ {
491+ asymbol *def;
492+ asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
493+ /* Add this definition to script file */
494+ def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
495+ *def_ptr = def;
496+
497+
498+ def->value = result.value;
499+ if (result.section !=
500+ (lang_output_section_statement_type *)NULL) {
501+ if (current_section !=
502+ (lang_output_section_statement_type *)NULL) {
503+
504+ def->section = result.section->bfd_section;
505+ def->flags = BSF_GLOBAL | BSF_EXPORT;
506+ }
507+ else {
508+ /* Force to absolute */
509+ def->value += result.section->bfd_section->vma;
510+ def->section = (asection *)NULL;
511+ def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
512+ }
513+
514+
515+ }
516+ else {
517+ def->section = (asection *)NULL;
518+ def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
519+ }
520+
521+
522+ def->udata = (void *)NULL;
523+ def->name = sy->name;
524+ Q_enter_global_ref(def_ptr);
525+ }
526+
527+ }
528+
529+
530+ break;
531+ case etree_name:
532+ result = fold_name(tree, current_section, allocation_done, dot);
533+ break;
534+ default:
535+ info("%F%S Need more of these %d",tree->type.node_class );
536+
537+ }
538+ }
539+
540+ return result;
541+}
542+
543+
544+etree_value_type exp_fold_tree_no_dot(tree, current_section, allocation_done)
545+etree_type *tree;
546+lang_output_section_statement_type *current_section;
547+lang_phase_type allocation_done;
548+{
549+return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
550+ 0, (bfd_vma *)NULL);
551+}
552+
553+etree_type *
554+exp_binop(code, lhs, rhs)
555+int code;
556+etree_type *lhs;
557+etree_type *rhs;
558+{
559+ etree_type value, *new;
560+ etree_value_type r;
561+
562+ value.type.node_code = code;
563+ value.binary.lhs = lhs;
564+ value.binary.rhs = rhs;
565+ value.type.node_class = etree_binary;
566+ r = exp_fold_tree_no_dot(&value, (lang_output_section_statement_type *)NULL,
567+ lang_first_phase_enum );
568+ if (r.valid)
569+ {
570+ return exp_intop(r.value);
571+ }
572+ new = (etree_type *)ldmalloc(sizeof(new->binary));
573+ memcpy((char *)new, (char *)&value, sizeof(new->binary));
574+ return new;
575+}
576+
577+etree_type *
578+exp_trinop(code, cond, lhs, rhs)
579+int code;
580+etree_type *cond;
581+etree_type *lhs;
582+etree_type *rhs;
583+{
584+ etree_type value, *new;
585+ etree_value_type r;
586+ value.type.node_code = code;
587+ value.trinary.lhs = lhs;
588+ value.trinary.cond = cond;
589+ value.trinary.rhs = rhs;
590+ value.type.node_class = etree_trinary;
591+ r= exp_fold_tree_no_dot(&value, (lang_output_section_statement_type
592+ *)NULL,lang_first_phase_enum);
593+ if (r.valid) {
594+ return exp_intop(r.value);
595+ }
596+ new = (etree_type *)ldmalloc(sizeof(new->trinary));
597+ memcpy((char *)new,(char *) &value, sizeof(new->trinary));
598+ return new;
599+}
600+
601+
602+etree_type *
603+exp_unop(code, child)
604+int code;
605+etree_type *child;
606+{
607+ etree_type value, *new;
608+
609+ etree_value_type r;
610+ value.unary.type.node_code = code;
611+ value.unary.child = child;
612+ value.unary.type.node_class = etree_unary;
613+r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
614+ lang_first_phase_enum);
615+if (r.valid) {
616+ return exp_intop(r.value);
617+ }
618+ new = (etree_type *)ldmalloc(sizeof(new->unary));
619+ memcpy((char *)new, (char *)&value, sizeof(new->unary));
620+ return new;
621+}
622+
623+
624+etree_type *
625+exp_nameop(code, name)
626+int code;
627+char *name;
628+{
629+
630+ etree_type value, *new;
631+
632+ etree_value_type r;
633+ value.name.type.node_code = code;
634+ value.name.name = name;
635+ value.name.type.node_class = etree_name;
636+
637+
638+ r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
639+ lang_first_phase_enum);
640+ if (r.valid) {
641+ return exp_intop(r.value);
642+ }
643+ new = (etree_type *)ldmalloc(sizeof(new->name));
644+ memcpy((char *)new, (char *)&value, sizeof(new->name));
645+ return new;
646+
647+}
648+
649+
650+
651+
652+etree_type *
653+exp_assop(code, dst, src)
654+int code;
655+char *dst;
656+etree_type *src;
657+{
658+ etree_type value, *new;
659+
660+ value.assign.type.node_code = code;
661+
662+
663+ value.assign.src = src;
664+ value.assign.dst = dst;
665+ value.assign.type.node_class = etree_assign;
666+
667+#if 0
668+ if (exp_fold_tree_no_dot(&value, &result)) {
669+ return exp_intop(result);
670+ }
671+#endif
672+ new = (etree_type*)ldmalloc(sizeof(new->assign));
673+ memcpy((char *)new, (char *)&value, sizeof(new->assign));
674+ return new;
675+}
676+
677+void
678+exp_print_tree(outfile, tree)
679+FILE *outfile;
680+etree_type *tree;
681+{
682+ switch (tree->type.node_class) {
683+ case etree_value:
684+ fprintf(outfile,"0x%08lx",(bfd_vma)(tree->value.value));
685+ return;
686+ case etree_assign:
687+#if 0
688+ if (tree->assign.dst->sdefs != (asymbol *)NULL){
689+ fprintf(outfile,"%s (%x) ",tree->assign.dst->name,
690+ tree->assign.dst->sdefs->value);
691+ }
692+ else {
693+ fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name);
694+ }
695+#endif
696+ fprintf(outfile,"%s ",tree->assign.dst);
697+ exp_print_token(outfile,tree->type.node_code);
698+ exp_print_tree(outfile,tree->assign.src);
699+ break;
700+ case etree_binary:
701+ exp_print_tree(outfile,tree->binary.lhs);
702+ exp_print_token(outfile,tree->type.node_code);
703+ exp_print_tree(outfile,tree->binary.rhs);
704+ break;
705+ case etree_trinary:
706+ exp_print_tree(outfile,tree->trinary.cond);
707+ fprintf(outfile,"?");
708+ exp_print_tree(outfile,tree->trinary.lhs);
709+ fprintf(outfile,":");
710+ exp_print_tree(outfile,tree->trinary.rhs);
711+ break;
712+ case etree_unary:
713+ exp_print_token(outfile,tree->unary.type.node_code);
714+ fprintf(outfile,"(");
715+ exp_print_tree(outfile,tree->unary.child);
716+ fprintf(outfile,")");
717+ break;
718+ case etree_undef:
719+ fprintf(outfile,"????????");
720+ break;
721+ case etree_name:
722+ if (tree->type.node_code == NAME) {
723+ fprintf(outfile,"%s", tree->name.name);
724+ }
725+ else {
726+ exp_print_token(outfile,tree->type.node_code);
727+ fprintf(outfile,"(%s)", tree->name.name);
728+ }
729+ break;
730+ default:
731+ FAIL();
732+ break;
733+ }
734+}
735+
736+
737+
738+
739+bfd_vma
740+exp_get_vma(tree, def, name, allocation_done)
741+etree_type *tree;
742+bfd_vma def;
743+char *name;
744+lang_phase_type allocation_done;
745+{
746+ etree_value_type r;
747+
748+ if (tree != (etree_type *)NULL) {
749+ r = exp_fold_tree_no_dot(tree,
750+ (lang_output_section_statement_type *)NULL,
751+ allocation_done);
752+ if (r.valid == false && name) {
753+ info("%F%S Nonconstant expression for %s\n",name);
754+ }
755+ return r.value;
756+ }
757+ else {
758+ return def;
759+ }
760+}
761+
762+int
763+exp_get_value_int(tree,def,name, allocation_done)
764+etree_type *tree;
765+int def;
766+char *name;
767+lang_phase_type allocation_done;
768+{
769+ return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
770+}
--- /dev/null
+++ b/ld/ldexp.h
@@ -0,0 +1,99 @@
1+/* ldexp.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+
23+
24+/* The result of an expression tree */
25+typedef struct
26+{
27+ bfd_vma value;
28+ struct lang_output_section_statement_struct *section;
29+ boolean valid;
30+} etree_value_type;
31+
32+
33+
34+typedef struct
35+{
36+ int node_code;
37+ enum { etree_binary,
38+ etree_trinary,
39+ etree_unary,
40+ etree_name,
41+ etree_assign,
42+ etree_undef,
43+ etree_unspec,
44+ etree_value } node_class;
45+} node_type;
46+
47+
48+
49+typedef union etree_union
50+{
51+ node_type type;
52+ struct {
53+ node_type type;
54+ union etree_union *lhs;
55+ union etree_union *rhs;
56+ } binary;
57+ struct {
58+ node_type type;
59+ union etree_union *cond;
60+ union etree_union *lhs;
61+ union etree_union *rhs;
62+ } trinary;
63+ struct {
64+ node_type type;
65+ char *dst;
66+ union etree_union *src;
67+ } assign;
68+
69+ struct {
70+ node_type type;
71+ union etree_union *child;
72+ } unary;
73+ struct {
74+ node_type type;
75+ char *name;
76+ } name;
77+ struct {
78+ node_type type;
79+ bfd_vma value;
80+ } value;
81+
82+} etree_type;
83+
84+
85+PROTO(etree_type *,exp_intop,(bfd_vma));
86+
87+PROTO(etree_value_type, invalid,(void));
88+PROTO(etree_value_type, exp_fold_tree,(etree_type *, struct
89+ lang_output_section_statement_struct *, lang_phase_type,
90+ bfd_vma, bfd_vma *));
91+
92+PROTO(etree_type *, exp_binop,(int, etree_type *, etree_type *));
93+PROTO(etree_type *,exp_trinop,(int,etree_type *, etree_type *, etree_type *));
94+PROTO(etree_type *,exp_unop,(int, etree_type *));
95+PROTO(etree_type *,exp_nameop,(int, char *));
96+PROTO(etree_type *,exp_assop,(int, char *, etree_type *));
97+PROTO(void, exp_print_tree,(struct _iobuf *, etree_type *));
98+PROTO(bfd_vma, exp_get_vma,(etree_type *, bfd_vma, char *, enum boolean));
99+PROTO(int, exp_get_value_int,(etree_type *, int, char *, enum boolean));
--- /dev/null
+++ b/ld/ldfile.c
@@ -0,0 +1,284 @@
1+
2+/* Copyright (C) 1991 Free Software Foundation, Inc.
3+
4+This file is part of GLD, the Gnu Linker.
5+
6+GLD is free software; you can redistribute it and/or modify
7+it under the terms of the GNU General Public License as published by
8+the Free Software Foundation; either version 1, or (at your option)
9+any later version.
10+
11+GLD is distributed in the hope that it will be useful,
12+but WITHOUT ANY WARRANTY; without even the implied warranty of
13+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+GNU General Public License for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GLD; see the file COPYING. If not, write to
18+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19+
20+/*
21+ $Id$
22+
23+ $Log$
24+ Revision 1.1 1991/03/21 21:28:37 gumby
25+ Initial revision
26+
27+ * Revision 1.2 1991/03/15 18:45:55 rich
28+ * foo
29+ *
30+ * Revision 1.1 1991/03/13 00:48:18 chrisb
31+ * Initial revision
32+ *
33+ * Revision 1.4 1991/03/10 09:31:24 rich
34+ * Modified Files:
35+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
36+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
37+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
38+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
39+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
40+ *
41+ * As of this round of changes, ld now builds on all hosts of (Intel960)
42+ * interest and copy passes my copy test on big endian hosts again.
43+ *
44+ * Revision 1.3 1991/02/22 17:15:00 sac
45+ * Added RCS keywords and copyrights
46+ *
47+*/
48+
49+/*
50+ ldfile.c
51+
52+ look after all the file stuff
53+
54+ */
55+
56+#include "sysdep.h"
57+#include "bfd.h"
58+
59+#include "ldmisc.h"
60+#include "ldlang.h"
61+#include "ldfile.h"
62+
63+#include <ctype.h>
64+
65+/* EXPORT */
66+char *ldfile_input_filename;
67+char *ldfile_output_machine_name;
68+unsigned long ldfile_output_machine;
69+enum bfd_architecture ldfile_output_architecture;
70+boolean had_script;
71+
72+/* IMPORT */
73+
74+extern boolean option_v;
75+
76+
77+
78+
79+
80+/* LOACL */
81+typedef struct search_dirs_struct
82+{
83+ char *name;
84+ struct search_dirs_struct *next;
85+} search_dirs_type;
86+
87+static search_dirs_type *search_head;
88+static search_dirs_type **search_tail_ptr = &search_head;
89+
90+typedef struct search_arch_struct
91+{
92+ char *name;
93+ struct search_arch_struct *next;
94+} search_arch_type;
95+
96+static search_arch_type *search_arch_head;
97+static search_arch_type **search_arch_tail_ptr = &search_arch_head;
98+
99+void
100+ldfile_add_library_path(name)
101+char *name;
102+{
103+ search_dirs_type *new =
104+ (search_dirs_type *)ldmalloc(sizeof(search_dirs_type));
105+ new->name = name;
106+ new->next = (search_dirs_type*)NULL;
107+ *search_tail_ptr = new;
108+ search_tail_ptr = &new->next;
109+}
110+
111+
112+static bfd*
113+cached_bfd_openr(attempt,entry)
114+char *attempt;
115+lang_input_statement_type *entry;
116+{
117+ entry->the_bfd = bfd_openr(attempt, entry->target);
118+
119+
120+ return entry->the_bfd;
121+}
122+
123+static bfd *
124+open_a(arch, entry, lib, suffix)
125+char *arch;
126+lang_input_statement_type *entry;
127+char *lib;
128+char *suffix;
129+{
130+ bfd*desc;
131+ search_dirs_type *search ;
132+ for (search = search_head;
133+ search != (search_dirs_type *)NULL;
134+ search = search->next)
135+ {
136+ char buffer[1000];
137+ char *string;
138+ if (entry->is_archive == true) {
139+ sprintf(buffer,
140+ "%s/%s%s%s%s",
141+ search->name,
142+ lib,
143+ entry->filename, arch, suffix);
144+ }
145+ else {
146+ if (entry->filename[0] == '/') {
147+ strcpy(buffer, entry->filename);
148+ } else {
149+ sprintf(buffer,"%s/%s",search->name, entry->filename);
150+ } /* */
151+ }
152+ string = buystring(buffer);
153+ desc = cached_bfd_openr (string, entry);
154+ if (desc)
155+ {
156+ entry->filename = string;
157+ entry->search_dirs_flag = false;
158+ entry->the_bfd = desc;
159+ return desc;
160+ }
161+ free(string);
162+ }
163+ return (bfd *)NULL;
164+}
165+
166+/* Open the input file specified by 'entry', and return a descriptor.
167+ The open file is remembered; if the same file is opened twice in a row,
168+ a new open is not actually done. */
169+
170+void
171+ldfile_open_file (entry)
172+lang_input_statement_type *entry;
173+{
174+
175+ if (entry->superfile)
176+ ldfile_open_file (entry->superfile);
177+
178+ if (entry->search_dirs_flag)
179+ {
180+ search_arch_type *arch;
181+ for (arch = search_arch_head;
182+ arch != (search_arch_type *)NULL;
183+ arch = arch->next) {
184+ if (open_a(arch->name,entry,"","") != (bfd *)NULL) {
185+ return;
186+ }
187+ if (open_a(arch->name,entry,"lib",".a") != (bfd *)NULL) {
188+ return;
189+ }
190+
191+ }
192+
193+
194+ }
195+ else {
196+ entry->the_bfd = cached_bfd_openr (entry->filename, entry);
197+
198+ }
199+ if (!entry->the_bfd) info("%F%P: %E %I\n", entry);
200+
201+}
202+
203+
204+
205+
206+
207+
208+static FILE *
209+try_open(name, exten)
210+char *name;
211+char *exten;
212+{
213+ FILE *result;
214+ char buff[1000];
215+ result = fopen(name, "r");
216+ if (result && option_v == true) {
217+ info("%s\n",name);
218+ return result;
219+ }
220+ sprintf(buff, "%s%s", name, exten);
221+ result = fopen(buff, "r");
222+
223+ if (result && option_v == true) {
224+ info("%s\n", buff);
225+ }
226+ return result;
227+}
228+static FILE *
229+find_a_name(name, extend)
230+char *name;
231+char *extend;
232+{
233+ search_dirs_type *search;
234+ FILE *result;
235+ char buffer[1000];
236+ /* First try raw name */
237+ result = try_open(name,"");
238+ if (result == (FILE *)NULL) {
239+ /* Try now prefixes */
240+ for (search = search_head;
241+ search != (search_dirs_type *)NULL;
242+ search = search->next) {
243+ sprintf(buffer,"%s/%s", search->name, name);
244+ result = try_open(buffer, extend);
245+ if (result)break;
246+ }
247+ }
248+ return result;
249+}
250+
251+void ldfile_open_command_file(name)
252+char *name;
253+{
254+ extern FILE *ldlex_input_stack;
255+ ldlex_input_stack = find_a_name(name, ".ld");
256+
257+ if (ldlex_input_stack == (FILE *)NULL) {
258+ info("%P%F cannot open load script file %s\n",name);
259+ }
260+ ldfile_input_filename = name;
261+ had_script = true;
262+}
263+
264+
265+
266+
267+void
268+ldfile_add_arch(name)
269+char *name;
270+{
271+ search_arch_type *new =
272+ (search_arch_type *)ldmalloc(sizeof(search_arch_type));
273+ ldfile_output_machine_name = name;
274+
275+ new->name = name;
276+ new->next = (search_arch_type*)NULL;
277+ while (*name) {
278+ if (isupper(*name)) *name = tolower(*name);
279+ name++;
280+ }
281+ *search_arch_tail_ptr = new;
282+ search_arch_tail_ptr = &new->next;
283+
284+}
--- /dev/null
+++ b/ld/ldfile.h
@@ -0,0 +1,27 @@
1+/* ldfile.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+
23+PROTO(void,ldfile_add_arch,(char *));
24+PROTO(void,ldfile_add_library_path,(char *));
25+PROTO(void,ldfile_open_command_file,(char *name));
26+PROTO(void,ldfile_open_file,(struct lang_input_statement_struct *));
27+
--- /dev/null
+++ b/ld/ldgram.y
@@ -0,0 +1,693 @@
1+%{
2+/* Copyright (C) 1991 Free Software Foundation, Inc.
3+
4+This file is part of GLD, the Gnu Linker.
5+
6+GLD is free software; you can redistribute it and/or modify
7+it under the terms of the GNU General Public License as published by
8+the Free Software Foundation; either version 1, or (at your option)
9+any later version.
10+
11+GLD is distributed in the hope that it will be useful,
12+but WITHOUT ANY WARRANTY; without even the implied warranty of
13+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+GNU General Public License for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GLD; see the file COPYING. If not, write to
18+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19+
20+/*
21+ * $Id$
22+ *
23+ * $Log$
24+ * Revision 1.1 1991/03/21 21:28:41 gumby
25+ * Initial revision
26+ *
27+ * Revision 1.2 1991/03/16 22:27:24 rich
28+ * fish
29+ *
30+ * Revision 1.1 1991/03/13 00:48:21 chrisb
31+ * Initial revision
32+ *
33+ * Revision 1.6 1991/03/10 09:31:26 rich
34+ * Modified Files:
35+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
36+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
37+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
38+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
39+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
40+ *
41+ * As of this round of changes, ld now builds on all hosts of (Intel960)
42+ * interest and copy passes my copy test on big endian hosts again.
43+ *
44+ * Revision 1.5 1991/03/09 03:25:48 sac
45+ * Can now parse the -Ur flag
46+ *
47+ * Revision 1.4 1991/03/06 02:26:01 sac
48+ * Added support for constructor sections.
49+ * Remove parsing ambiguity.
50+ * Lint
51+ *
52+ * Revision 1.3 1991/02/22 17:15:13 sac
53+ * Added RCS keywords and copyrights
54+ *
55+*/
56+
57+/*
58+ This is a YACC grammer intended to parse a superset of the AT&T
59+ linker scripting languaue.
60+
61+
62+ Written by Steve Chamberlain steve@cygnus.com
63+*/
64+
65+
66+/*SUPPRESS 166*/
67+/*SUPPRESS 112*/
68+
69+#include "sysdep.h"
70+#include "bfd.h"
71+
72+#include "ld.h"
73+#include "ldexp.h"
74+#include "ldversion.h"
75+#include "ldlang.h"
76+#include "ld-emul.h"
77+#include "ldfile.h"
78+#include "ldmisc.h"
79+#define YYDEBUG 1
80+
81+boolean option_v;
82+
83+
84+extern unsigned int lineno;
85+extern boolean trace_files;
86+extern boolean write_map;
87+
88+boolean hex_mode;
89+
90+
91+
92+
93+lang_memory_region_type *region;
94+
95+
96+lang_memory_region_type *lang_memory_region_lookup();
97+lang_output_section_statement_type *lang_output_section_statement_lookup();
98+
99+#ifdef __STDC__
100+
101+void lang_add_data(int type, union etree_union *exp);
102+void lang_enter_output_section_statement(char *output_section_statement_name, etree_type *address_exp, bfd_vma block_value);
103+
104+#else
105+
106+void lang_add_data();
107+void lang_enter_output_section_statement();
108+
109+#endif /* __STDC__ */
110+
111+extern args_type command_line;
112+char *current_file;
113+boolean ldgram_want_filename = true;
114+boolean had_script = false;
115+boolean force_make_executable = false;
116+boolean ldgram_mustbe_filename = false;
117+boolean ldgram_mustbe_symbolname = false;
118+boolean ldgram_has_inputfile = false;
119+
120+/* LOCALS */
121+
122+
123+
124+
125+%}
126+%union {
127+ bfd_vma integer;
128+ int voidval;
129+ char *name;
130+ int token;
131+ union etree_union *etree;
132+ asection *section;
133+ struct lang_output_section_statement_struct *output_section_statement;
134+ union lang_statement_union **statement_ptr;
135+ int lineno;
136+ struct {
137+ FILE *file;
138+ char *name;
139+ unsigned int lineno;
140+ } state;
141+
142+
143+}
144+
145+%type <etree> exp opt_exp exp_head
146+%type <integer> fill_opt opt_block
147+%type <name> memspec_opt
148+%token <integer> INT CHAR
149+%token <name> NAME
150+%type <integer> length
151+
152+%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
153+%right <token> '?' ':'
154+%left <token> OROR
155+%left <token> ANDAND
156+%left <token> '|'
157+%left <token> '^'
158+%left <token> '&'
159+%left <token> EQ NE
160+%left <token> '<' '>' LE GE
161+%left <token> LSHIFT RSHIFT
162+%left <token> '+' '-'
163+%left <token> '*' '/' '%'
164+%right UNARY
165+%left <token> '('
166+%token <token> ALIGN_K BLOCK LONG SHORT BYTE
167+%token SECTIONS
168+%token '{' '}'
169+%token ALIGNMENT SIZEOF_HEADERS
170+%token NEXT SIZEOF ADDR
171+%token MEMORY
172+%token DSECT NOLOAD COPY INFO OVERLAY
173+%token NAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
174+%token OPTION_e OPTION_c OPTION_noinhibit_exec OPTION_s OPTION_S OPTION_format
175+%token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X
176+%token OPTION_v OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT OPTION_defsym
177+%token OPTION_n OPTION_r OPTION_o OPTION_b OPTION_A
178+%token <name> OPTION_l OPTION_L OPTION_T OPTION_Aarch OPTION_Tfile OPTION_Texp
179+%token OPTION_Ur
180+%token ORIGIN FILL OPTION_g
181+%token LENGTH BIND SUBSECTION_ALIGN CREATE_OBJECT_SYMBOLS INPUT OUTPUT
182+%type <token> assign_op SIZEOF NEXT ADDR
183+%type <etree> assignment
184+%type <name> filename
185+
186+%{
187+ld_config_type config;
188+%}
189+
190+%%
191+
192+
193+
194+file: command_line { lang_final(); };
195+
196+
197+filename:
198+ {
199+ ldgram_mustbe_filename =true;
200+ }
201+ NAME
202+ {
203+ ldgram_mustbe_filename = false;
204+ $$ = $2;
205+ }
206+
207+command_line:
208+ command_line command_line_option
209+ |
210+ ;
211+
212+command_line_option:
213+ OPTION_v
214+ {
215+ ldversion();
216+ option_v = true;
217+ }
218+ | OPTION_t {
219+ trace_files = true;
220+ }
221+ | OPTION_M {
222+ write_map = true;
223+ }
224+ | OPTION_n {
225+ config.magic_demand_paged = false;
226+ config.make_executable = false;
227+ }
228+ | OPTION_s {
229+ strip_symbols = STRIP_ALL;
230+ }
231+ | OPTION_S {
232+ strip_symbols = STRIP_DEBUGGER;
233+ }
234+
235+ | OPTION_r {
236+ config.relocateable_output = true;
237+ config.build_constructors = false;
238+ config.magic_demand_paged = false;
239+ }
240+ | OPTION_Ur {
241+ config.relocateable_output = true;
242+ config.build_constructors = true;
243+ config.magic_demand_paged = false;
244+ }
245+ | OPTION_o filename
246+ {
247+ lang_add_output($2);
248+ }
249+ | OPTION_e NAME
250+ { lang_add_entry($2);
251+ }
252+ | OPTION_X {
253+ discard_locals = DISCARD_L;
254+ }
255+ | OPTION_x {
256+ discard_locals = DISCARD_ALL;
257+ }
258+
259+ | OPTION_noinhibit_exec
260+ {
261+ force_make_executable = true;
262+ }
263+ | OPTION_d {
264+ command_line.force_common_definition = true;
265+ }
266+ | OPTION_dc
267+ {
268+ command_line.force_common_definition = true;
269+ }
270+ | OPTION_g
271+ {
272+ /* Ignored */
273+ }
274+ | OPTION_dp
275+ {
276+ command_line.force_common_definition = true;
277+ }
278+ | OPTION_format NAME
279+ {
280+ lang_add_target($2);
281+ }
282+
283+ | OPTION_Texp { hex_mode =true; }
284+ exp_head
285+ { lang_section_start($1, $3);
286+ hex_mode = false; }
287+
288+ | OPTION_Aarch
289+ { ldfile_add_arch($1); }
290+ | OPTION_b NAME
291+ {
292+ lang_add_target($2);
293+ }
294+ | OPTION_L
295+ {
296+ ldfile_add_library_path($1);
297+ }
298+ | ifile_p1
299+ | input_list
300+ | OPTION_c filename
301+ { ldfile_open_command_file($2); }
302+ | OPTION_Tfile
303+ { ldfile_open_command_file($1); }
304+
305+ | OPTION_T filename
306+ { ldfile_open_command_file($2); }
307+
308+ | OPTION_l
309+ {
310+ lang_add_input_file($1,
311+ lang_input_file_is_l_enum,
312+ (char *)NULL);
313+ }
314+ | OPTION_A filename
315+ {
316+ lang_add_input_file($2,
317+ lang_input_file_is_symbols_only_enum,
318+ (char *)NULL);
319+ }
320+ | OPTION_defsym assignment_with_nospaces
321+ ;
322+
323+
324+input_section_spec:
325+ NAME
326+ {
327+ lang_add_wild((char *)NULL, $1);
328+ }
329+ | '['
330+ {
331+ current_file = (char *)NULL;
332+ }
333+ file_NAME_list
334+ ']'
335+ | NAME
336+ {
337+ current_file =$1;
338+ }
339+ '(' file_NAME_list ')'
340+ | '*'
341+ {
342+ current_file = (char *)NULL;
343+ }
344+ '(' file_NAME_list ')'
345+ ;
346+
347+
348+
349+file_NAME_list:
350+ NAME
351+ { lang_add_wild($1, current_file); }
352+ | file_NAME_list opt_comma NAME
353+ { lang_add_wild($3, current_file); }
354+ ;
355+
356+
357+
358+ifile_p1:
359+ memory
360+ | sections
361+ | startup
362+ | high_level_library
363+ | low_level_library
364+ | floating_point_support
365+ | assignment end
366+ | TARGET_K '(' NAME ')'
367+ { lang_add_target($3); }
368+ | SEARCH_DIR '(' filename ')'
369+ { ldfile_add_library_path($3); }
370+ | OUTPUT '(' filename ')'
371+ { lang_add_output($3); }
372+ | INPUT '(' input_list ')'
373+ | MAP '(' filename ')'
374+ { lang_add_map($3); }
375+ ;
376+
377+input_list:
378+ NAME
379+ { lang_add_input_file($1,lang_input_file_is_file_enum,
380+ (char *)NULL); }
381+ | input_list ',' NAME
382+ { lang_add_input_file($3,lang_input_file_is_file_enum,
383+ (char *)NULL); }
384+ | input_list NAME
385+ { lang_add_input_file($2, lang_input_file_is_file_enum,
386+ (char *)NULL); }
387+ ;
388+
389+sections:
390+ SECTIONS '{'sec_or_group_p1 '}'
391+ ;
392+
393+sec_or_group_p1:
394+ sec_or_group_p1 section
395+ | sec_or_group_p1 statement_anywhere
396+ |
397+ ;
398+
399+statement_anywhere:
400+ ENTRY '(' NAME ')'
401+ { lang_add_entry($3); }
402+ | assignment end
403+ ;
404+
405+statement:
406+ statement assignment end
407+ | statement CREATE_OBJECT_SYMBOLS
408+ { lang_add_attribute(lang_object_symbols_statement_enum); }
409+ | statement input_section_spec
410+ | statement length '(' exp_head ')'
411+ {
412+ lang_add_data($2,$4);
413+ }
414+
415+ | statement FILL '(' exp_head ')'
416+ {
417+ lang_add_fill
418+ (exp_get_value_int($4,
419+ 0,
420+ "fill value",
421+ lang_first_phase_enum));
422+ }
423+ |
424+ ;
425+
426+length:
427+ LONG
428+ { $$ = $1; }
429+ | SHORT
430+ { $$ = $1; }
431+ | BYTE
432+ { $$ = $1; }
433+ ;
434+
435+fill_opt:
436+ '=' exp_head
437+ {
438+ $$ = exp_get_value_int($2,
439+ 0,
440+ "fill value",
441+ lang_first_phase_enum);
442+ }
443+ | { $$ = 0; }
444+ ;
445+
446+
447+
448+assign_op:
449+ PLUSEQ
450+ { $$ = '+'; }
451+ | MINUSEQ
452+ { $$ = '-'; }
453+ | MULTEQ
454+ { $$ = '*'; }
455+ | DIVEQ
456+ { $$ = '/'; }
457+ | LSHIFTEQ
458+ { $$ = LSHIFT; }
459+ | RSHIFTEQ
460+ { $$ = RSHIFT; }
461+ | ANDEQ
462+ { $$ = '&'; }
463+ | OREQ
464+ { $$ = '|'; }
465+
466+ ;
467+
468+end: ';' | ','
469+ ;
470+
471+assignment_with_nospaces:
472+ { ldgram_want_filename = false; }
473+ assignment
474+ { ldgram_want_filename = true; }
475+ ;
476+
477+assignment:
478+
479+ NAME '=' exp_head
480+ {
481+ lang_add_assignment(exp_assop($2,$1,$3));
482+ }
483+ | NAME assign_op exp_head
484+ {
485+ lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3)));
486+ }
487+
488+ ;
489+
490+
491+opt_comma:
492+ ',' | ;
493+
494+
495+memory:
496+ MEMORY '{' memory_spec memory_spec_list '}'
497+ ;
498+
499+memory_spec_list:
500+ memory_spec_list memory_spec
501+ | memory_spec_list ',' memory_spec
502+ |
503+ ;
504+
505+
506+memory_spec:
507+ NAME
508+ { region = lang_memory_region_lookup($1); }
509+ attributes_opt ':' origin_spec opt_comma length_spec
510+
511+ {
512+
513+
514+ }
515+ ;
516+origin_spec:
517+ ORIGIN '=' exp
518+ { region->current =
519+ region->origin =
520+ exp_get_vma($3, 0L,"origin", lang_first_phase_enum); }
521+ ;
522+length_spec:
523+ LENGTH '=' exp
524+ { region->length = exp_get_vma($3,
525+ ~((bfd_vma)0),
526+ "length",
527+ lang_first_phase_enum);
528+ }
529+
530+
531+attributes_opt:
532+ '(' NAME ')'
533+ {
534+ lang_set_flags(&region->flags, $2);
535+ }
536+ |
537+
538+ ;
539+
540+startup:
541+ STARTUP '(' filename ')'
542+ { lang_startup($3); }
543+ ;
544+
545+high_level_library:
546+ HLL '(' high_level_library_NAME_list ')'
547+ | HLL '(' ')'
548+ { ldemul_hll((char *)NULL); }
549+ ;
550+
551+high_level_library_NAME_list:
552+ high_level_library_NAME_list opt_comma filename
553+ { ldemul_hll($3); }
554+ | filename
555+ { ldemul_hll($1); }
556+
557+ ;
558+
559+low_level_library:
560+ SYSLIB '(' low_level_library_NAME_list ')'
561+ ;
562+low_level_library_NAME_list:
563+ low_level_library_NAME_list opt_comma filename
564+ { ldemul_syslib($3); }
565+ |
566+ ;
567+
568+floating_point_support:
569+ FLOAT
570+ { lang_float(true); }
571+ | NOFLOAT
572+ { lang_float(false); }
573+ ;
574+
575+
576+
577+
578+exp :
579+ '-' exp %prec UNARY
580+ { $$ = exp_unop('-', $2); }
581+ | '(' exp ')'
582+ { $$ = $2; }
583+ | NEXT '(' exp ')' %prec UNARY
584+ { $$ = exp_unop($1,$3); }
585+ | '!' exp %prec UNARY
586+ { $$ = exp_unop('!', $2); }
587+ | '+' exp %prec UNARY
588+ { $$ = $2; }
589+ | '~' exp %prec UNARY
590+ { $$ = exp_unop('~', $2);}
591+
592+ | exp '*' exp
593+ { $$ = exp_binop('*', $1, $3); }
594+ | exp '/' exp
595+ { $$ = exp_binop('/', $1, $3); }
596+ | exp '%' exp
597+ { $$ = exp_binop('%', $1, $3); }
598+ | exp '+' exp
599+ { $$ = exp_binop('+', $1, $3); }
600+ | exp '-' exp
601+ { $$ = exp_binop('-' , $1, $3); }
602+ | exp LSHIFT exp
603+ { $$ = exp_binop(LSHIFT , $1, $3); }
604+ | exp RSHIFT exp
605+ { $$ = exp_binop(RSHIFT , $1, $3); }
606+ | exp EQ exp
607+ { $$ = exp_binop(EQ , $1, $3); }
608+ | exp NE exp
609+ { $$ = exp_binop(NE , $1, $3); }
610+ | exp LE exp
611+ { $$ = exp_binop(LE , $1, $3); }
612+ | exp GE exp
613+ { $$ = exp_binop(GE , $1, $3); }
614+ | exp '<' exp
615+ { $$ = exp_binop('<' , $1, $3); }
616+ | exp '>' exp
617+ { $$ = exp_binop('>' , $1, $3); }
618+ | exp '&' exp
619+ { $$ = exp_binop('&' , $1, $3); }
620+ | exp '^' exp
621+ { $$ = exp_binop('^' , $1, $3); }
622+ | exp '|' exp
623+ { $$ = exp_binop('|' , $1, $3); }
624+ | exp '?' exp ':' exp
625+ { $$ = exp_trinop('?' , $1, $3, $5); }
626+ | exp ANDAND exp
627+ { $$ = exp_binop(ANDAND , $1, $3); }
628+ | exp OROR exp
629+ { $$ = exp_binop(OROR , $1, $3); }
630+ | DEFINED '(' NAME ')'
631+ { $$ = exp_nameop(DEFINED, $3); }
632+ | INT
633+ { $$ = exp_intop($1); }
634+
635+ | SIZEOF '(' NAME ')'
636+ { $$ = exp_nameop($1,$3); }
637+ | ADDR '(' NAME ')'
638+ { $$ = exp_nameop($1,$3); }
639+ | ALIGN_K '(' exp ')'
640+ { $$ = exp_unop($1,$3); }
641+ | NAME
642+ { $$ = exp_nameop(NAME,$1); }
643+ ;
644+
645+
646+
647+
648+section: NAME opt_exp opt_block ':' opt_things'{'
649+ {
650+ lang_enter_output_section_statement($1,$2,$3);
651+ }
652+ statement '}' fill_opt memspec_opt
653+ {
654+ lang_leave_output_section_statement($10, $11);
655+ }
656+
657+ ;
658+
659+opt_things:
660+ {
661+
662+ }
663+ ;
664+
665+exp_head:
666+ { ldgram_mustbe_symbolname = true; }
667+ exp
668+ { ldgram_mustbe_symbolname = false;
669+ $$ = $2;
670+ }
671+
672+opt_exp:
673+ exp
674+ { $$ = $1; }
675+ | { $$= (etree_type *)NULL; }
676+ ;
677+
678+opt_block:
679+ BLOCK '(' exp_head ')'
680+ { $$ = exp_get_value_int($3,
681+ 1L,
682+ "block",
683+ lang_first_phase_enum);
684+ }
685+ | { $$ = 1; }
686+ ;
687+
688+memspec_opt:
689+ '>' NAME
690+ { $$ = $2; }
691+ | { $$ = "*default*"; }
692+ ;
693+
--- /dev/null
+++ b/ld/ldlang.c
@@ -0,0 +1,2231 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/* $Id$
20+ *
21+ * $Log$
22+ * Revision 1.1 1991/03/21 21:28:45 gumby
23+ * Initial revision
24+ *
25+ * Revision 1.3 1991/03/16 22:19:21 rich
26+ * pop
27+ *
28+ * Revision 1.2 1991/03/15 18:52:42 rich
29+ * pop
30+ *
31+ * Revision 1.1 1991/03/13 00:48:23 chrisb
32+ * Initial revision
33+ *
34+ * Revision 1.8 1991/03/10 09:31:28 rich
35+ * Modified Files:
36+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
37+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
38+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
39+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
40+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
41+ *
42+ * As of this round of changes, ld now builds on all hosts of (Intel960)
43+ * interest and copy passes my copy test on big endian hosts again.
44+ *
45+ * Revision 1.7 1991/03/09 03:31:03 sac
46+ * After a fatal info message, the output file is deleted.
47+ *
48+ * Revision 1.6 1991/03/09 03:25:06 sac
49+ * Added support for LONG, SHORT and BYTE keywords in scripts
50+ *
51+ * Revision 1.5 1991/03/06 21:59:31 sac
52+ * Completed G++ support
53+ *
54+ * Revision 1.4 1991/03/06 02:26:02 sac
55+ * Added support for constructor sections.
56+ * Remove parsing ambiguity.
57+ * Lint
58+ *
59+ * Revision 1.3 1991/02/22 17:15:01 sac
60+ * Added RCS keywords and copyrights
61+ *
62+*/
63+
64+
65+
66+#include "sysdep.h"
67+#include "bfd.h"
68+
69+#include "ld.h"
70+#include "ldmain.h"
71+#include "ldsym.h"
72+#include "ldgram.tab.h"
73+#include "ldmisc.h"
74+#include "ldlang.h"
75+#include "ldexp.h"
76+#include "ld-emul.h"
77+#include "ldlex.h"
78+
79+/* EXPORTS */
80+
81+
82+
83+extern unsigned int undefined_global_sym_count;
84+
85+static char *startup_file;
86+static lang_input_statement_type *first_file;
87+lang_statement_list_type statement_list;
88+lang_statement_list_type *stat_ptr = &statement_list;
89+lang_statement_list_type lang_output_section_statement;
90+lang_statement_list_type input_file_chain;
91+lang_statement_list_type file_chain;
92+extern char *current_file;
93+static boolean placed_commons = false;
94+
95+boolean lang_float_flag;
96+
97+static lang_output_section_statement_type *default_common_section;
98+
99+
100+/* FORWARDS */
101+PROTO(static void, print_statements,(void));
102+PROTO(static void, print_statement,(lang_statement_union_type *,
103+ lang_output_section_statement_type *));
104+
105+
106+
107+/* EXPORTS */
108+boolean lang_has_input_file = false;
109+
110+
111+extern bfd *output_bfd;
112+size_t largest_section;
113+
114+
115+extern enum bfd_architecture ldfile_output_architecture;
116+extern unsigned long ldfile_output_machine;
117+extern char *ldfile_output_machine_name;
118+
119+
120+extern ldsym_type *symbol_head;
121+
122+bfd_vma print_dot;
123+unsigned int commons_pending;
124+
125+
126+
127+
128+extern args_type command_line;
129+extern ld_config_type config;
130+
131+char *entry_symbol;
132+
133+
134+
135+lang_output_section_statement_type *create_object_symbols;
136+
137+extern boolean had_script;
138+static boolean map_option_f;
139+
140+
141+boolean had_output_filename = false;
142+extern boolean write_map;
143+
144+
145+
146+
147+
148+
149+size_t longest_section_name = 8;
150+
151+
152+lang_input_statement_type *script_file;
153+
154+section_userdata_type common_section_userdata;
155+asection common_section;
156+
157+#ifdef __STDC__
158+#define cat(a,b) a##b
159+#else
160+#define cat(a,b) a/**/b
161+#endif
162+
163+#define new_stat(x,y) (cat(x,_type)*) new_statement(cat(x,_enum), sizeof(cat(x,_type)),y)
164+
165+#define outside_section_address(q) ( (q)->output_offset + (q)->output_section->vma)
166+
167+#define outside_symbol_address(q) ((q)->value + outside_section_address(q->section))
168+
169+boolean option_longmap = false;
170+
171+static void lang_list_init(list)
172+lang_statement_list_type *list;
173+{
174+list->head = (lang_statement_union_type *)NULL;
175+list->tail = &list->head;
176+}
177+
178+static void
179+print_section(name)
180+char *name;
181+{
182+ printf("%*s", -longest_section_name, name);
183+}
184+static void
185+print_space()
186+{
187+ printf(" ");
188+}
189+static void
190+print_nl()
191+{
192+ printf("\n");
193+}
194+static void
195+print_address(value)
196+bfd_vma value;
197+{
198+ printf("%8lx", value);
199+}
200+static void
201+print_size(value)
202+size_t value;
203+{
204+ printf("%5x", (unsigned)value);
205+}
206+static void
207+print_alignment(value)
208+unsigned int value;
209+{
210+ printf("2**%2u",value);
211+}
212+static void
213+print_fill(value)
214+fill_type value;
215+{
216+ printf("%04x",(unsigned)value);
217+}
218+
219+
220+static
221+lang_statement_union_type *new_statement(type, size, list)
222+enum statement_enum type;
223+size_t size;
224+lang_statement_list_type *list;
225+{
226+ lang_statement_union_type *new = (lang_statement_union_type *)
227+ ldmalloc(size);
228+ new->header.type = type;
229+ new->header.next = (lang_statement_union_type *)NULL;
230+ lang_statement_append(list, new, &new->header.next);
231+ return new;
232+}
233+
234+static lang_input_statement_type *
235+new_afile(name, file_type, target)
236+char *name;
237+lang_input_file_enum_type file_type;
238+char *target;
239+{
240+ lang_input_statement_type *p = new_stat(lang_input_statement,
241+ stat_ptr);
242+ lang_has_input_file = true;
243+ p->target = target;
244+ switch (file_type) {
245+ case lang_input_file_is_symbols_only_enum:
246+ p->filename = name;
247+ p->is_archive =false;
248+ p->real = true;
249+ p->local_sym_name= name;
250+ p->just_syms_flag = true;
251+ p->search_dirs_flag = false;
252+ break;
253+ case lang_input_file_is_fake_enum:
254+ p->filename = name;
255+ p->is_archive =false;
256+ p->real = false;
257+ p->local_sym_name= name;
258+ p->just_syms_flag = false;
259+ p->search_dirs_flag =false;
260+
261+ break;
262+ case lang_input_file_is_l_enum:
263+ p->is_archive = true;
264+ p->filename = name;
265+ p->real = true;
266+ p->local_sym_name = concat("-l",name,"");
267+ p->just_syms_flag = false;
268+ p->search_dirs_flag = true;
269+ break;
270+
271+ case lang_input_file_is_search_file_enum:
272+ case lang_input_file_is_marker_enum:
273+ p->filename = name;
274+ p->is_archive =false;
275+ p->real = true;
276+ p->local_sym_name= name;
277+ p->just_syms_flag = false;
278+ p->search_dirs_flag =true;
279+ break;
280+
281+
282+
283+ case lang_input_file_is_file_enum:
284+ p->filename = name;
285+ p->is_archive =false;
286+ p->real = true;
287+ p->local_sym_name= name;
288+ p->just_syms_flag = false;
289+ p->search_dirs_flag =false;
290+ break;
291+
292+
293+ default:
294+ FAIL();
295+ }
296+ p->asymbols = (asymbol **)NULL;
297+ p->superfile = (lang_input_statement_type *)NULL;
298+
299+ p->next_real_file = (lang_statement_union_type*)NULL;
300+ p->next = (lang_statement_union_type*)NULL;
301+ p->symbol_count = 0;
302+ p->common_output_section = (asection *)NULL;
303+
304+ lang_statement_append(&input_file_chain,
305+ (lang_statement_union_type *)p,
306+ &p->next_real_file);
307+ return p;
308+}
309+
310+lang_input_statement_type *
311+lang_add_input_file(name,
312+ file_type,
313+ target)
314+char *name;
315+lang_input_file_enum_type file_type;
316+char *target;
317+{
318+ /* Look it up or build a new one */
319+
320+ lang_input_statement_type *p;
321+
322+ for (p = (lang_input_statement_type *)input_file_chain.head;
323+ p != (lang_input_statement_type *)NULL;
324+ p = (lang_input_statement_type *)(p->next_real_file))
325+ {
326+ /* Sometimes we have incomplete entries in here */
327+ if (p->filename != (char *)NULL) {
328+ if(strcmp(name,p->filename) == 0) return p;
329+ }
330+ }
331+
332+ return new_afile(name, file_type, target);
333+}
334+
335+
336+
337+void
338+lang_init()
339+{
340+
341+ stat_ptr= &statement_list;
342+ lang_list_init(stat_ptr);
343+
344+ lang_list_init(&input_file_chain);
345+ lang_list_init(&lang_output_section_statement);
346+ lang_list_init(&file_chain);
347+ first_file = lang_add_input_file((char *)NULL,
348+ lang_input_file_is_marker_enum,
349+ (char *)NULL);
350+
351+}
352+
353+static void
354+lang_init2()
355+{
356+ script_file = lang_add_input_file("script file",
357+ lang_input_file_is_fake_enum,
358+ (char *)NULL);
359+ script_file->the_bfd = bfd_create("script file", output_bfd);
360+ script_file->symbol_count = 0;
361+
362+ common_section.userdata = &common_section_userdata;
363+
364+}
365+
366+
367+
368+/* this function mainains a dictionary of regions. If the *default*
369+ region is asked for then a pointer to the first region is
370+ returned. If there is no first pointer then one is created
371+*/
372+
373+static lang_memory_region_type *lang_memory_region_list;
374+static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;
375+
376+lang_memory_region_type *
377+lang_memory_region_lookup(name)
378+char *name;
379+{
380+
381+ lang_memory_region_type *p = lang_memory_region_list;
382+ for (p = lang_memory_region_list;
383+ p != ( lang_memory_region_type *)NULL;
384+ p = p->next) {
385+ if (strcmp(p->name, name) == 0) {
386+ return p;
387+ }
388+ }
389+ if (strcmp(name,"*default*")==0) {
390+ /* This is the default region, dig out first one on the list */
391+ if (lang_memory_region_list != (lang_memory_region_type*)NULL){
392+ return lang_memory_region_list;
393+ }
394+ }
395+ {
396+ lang_memory_region_type *new =
397+ (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type));
398+ new->name = name;
399+ new->next = (lang_memory_region_type *)NULL;
400+
401+ *lang_memory_region_list_tail = new;
402+ lang_memory_region_list_tail = &new->next;
403+ new->origin = 0;
404+ new->length = ~0;
405+ new->current = 0;
406+ return new;
407+ }
408+}
409+
410+
411+
412+lang_output_section_statement_type *
413+lang_output_section_find(name)
414+char *name;
415+{
416+ lang_statement_union_type *u;
417+ lang_output_section_statement_type *lookup;
418+
419+ for (u = lang_output_section_statement.head;
420+ u != (lang_statement_union_type *)NULL;
421+ u = lookup->next)
422+ {
423+ lookup = &u->output_section_statement;
424+ if (strcmp(name, lookup->name)==0) {
425+ return lookup;
426+ }
427+ }
428+ return (lang_output_section_statement_type *)NULL;
429+}
430+
431+lang_output_section_statement_type *
432+lang_output_section_statement_lookup(name)
433+char *name;
434+
435+{
436+ lang_output_section_statement_type *lookup;
437+ lookup =lang_output_section_find(name);
438+ if (lookup == (lang_output_section_statement_type *)NULL) {
439+
440+ lookup =(lang_output_section_statement_type *)
441+ new_stat(lang_output_section_statement, stat_ptr);
442+ lookup->region = (lang_memory_region_type *)NULL;
443+ lookup->fill = 0;
444+ lookup->block_value = 1;
445+ lookup->name = name;
446+
447+ lookup->next = (lang_statement_union_type*)NULL;
448+ lookup->bfd_section = (asection *)NULL;
449+ lookup->processed = false;
450+ lookup->addr_tree = (etree_type *)NULL;
451+ lang_list_init(&lookup->children);
452+
453+ lang_statement_append(&lang_output_section_statement,
454+ (lang_statement_union_type *)lookup,
455+ &lookup->next);
456+ }
457+ return lookup;
458+}
459+
460+
461+
462+
463+
464+static void
465+ print_flags(outfile, ignore_flags)
466+FILE *outfile;
467+lang_section_flags_type *ignore_flags;
468+{
469+ fprintf(outfile,"(");
470+#if 0
471+ if (flags->flag_read) fprintf(outfile,"R");
472+ if (flags->flag_write) fprintf(outfile,"W");
473+ if (flags->flag_executable) fprintf(outfile,"X");
474+ if (flags->flag_loadable) fprintf(outfile,"L");
475+#endif
476+ fprintf(outfile,")");
477+}
478+
479+void
480+lang_map(outfile)
481+ FILE *outfile;
482+{
483+ lang_memory_region_type *m;
484+ fprintf(outfile,"**MEMORY CONFIGURATION**\n\n");
485+
486+ fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n");
487+ for (m = lang_memory_region_list;
488+ m != (lang_memory_region_type *)NULL;
489+ m = m->next)
490+ {
491+ fprintf(outfile,"%-16s", m->name);
492+
493+ fprintf(outfile,"%08lx\t%08lx\t", m->origin, m->length);
494+ print_flags(outfile, &m->flags);
495+ fprintf(outfile,"\n");
496+ }
497+ fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n");
498+ fprintf(outfile,"output\t\tinput\t\tvirtual\n");
499+ fprintf(outfile,"section\t\tsection\t\taddress\tsize\n\n");
500+
501+ print_statements();
502+
503+}
504+
505+/*
506+ *
507+ */
508+static void init_os(s)
509+lang_output_section_statement_type *s;
510+{
511+ section_userdata_type *new =
512+ (section_userdata_type *)
513+ ldmalloc(sizeof(section_userdata_type));
514+
515+ s->bfd_section = bfd_make_section(output_bfd, s->name);
516+ s->bfd_section->output_section = s->bfd_section;
517+ s->bfd_section->flags = SEC_NO_FLAGS;
518+ /* We initialize an output sections output offset to minus its own */
519+ /* vma to allow us to output a section through itself */
520+ s->bfd_section->output_offset = 0;
521+ get_userdata( s->bfd_section) = new;
522+}
523+
524+static void
525+wild_doit(ptr, section,output, file)
526+lang_statement_list_type *ptr;
527+asection *section;
528+lang_output_section_statement_type *output;
529+lang_input_statement_type *file;
530+{
531+ if(output->bfd_section == (asection *)NULL)
532+ {
533+ init_os(output);
534+ }
535+
536+ if (section != (asection *)NULL
537+ && section->output_section == (asection *)NULL) {
538+ /* Add a section reference to the list */
539+ lang_input_section_type *new = new_stat(lang_input_section, ptr);
540+
541+ new->section = section;
542+ new->ifile = file;
543+ section->output_section = output->bfd_section;
544+ section->output_section->flags |= section->flags;
545+ if (section->alignment_power > output->bfd_section->alignment_power) {
546+ output->bfd_section->alignment_power = section->alignment_power;
547+ }
548+
549+ }
550+}
551+
552+static asection *
553+our_bfd_get_section_by_name(abfd, section)
554+bfd *abfd;
555+char *section;
556+{
557+ return bfd_get_section_by_name(abfd, section);
558+
559+}
560+static void
561+wild_section(ptr, section, file , output)
562+lang_wild_statement_type *ptr;
563+char *section;
564+lang_input_statement_type *file;
565+lang_output_section_statement_type *output;
566+{
567+ asection *s;
568+ if (section == (char *)NULL) {
569+ /* Do the creation to all sections in the file */
570+ for (s = file->the_bfd->sections; s != (asection *)NULL; s=s->next) {
571+ wild_doit(&ptr->children, s, output, file);
572+ }
573+ }
574+ else {
575+ /* Do the creation to the named section only */
576+ wild_doit(&ptr->children,
577+ our_bfd_get_section_by_name(file->the_bfd, section),
578+ output, file);
579+ }
580+
581+
582+
583+}
584+
585+
586+
587+static
588+lang_input_statement_type *lookup_name(name, target)
589+char *name;
590+char *target;
591+{
592+ lang_input_statement_type *search;
593+ for(search = (lang_input_statement_type *)input_file_chain.head;
594+ search != (lang_input_statement_type *)NULL;
595+ search = (lang_input_statement_type *)search->next_real_file)
596+ {
597+ if (search->filename == (char *)NULL && name == (char *)NULL) {
598+ return search;
599+ }
600+ if (search->filename != (char *)NULL && name != (char *)NULL) {
601+ if (strcmp(search->filename, name) == 0) {
602+ Q_read_file_symbols(search);
603+ return search;
604+ }
605+ }
606+ }
607+
608+ /* There isn't an afile entry for this file yet, this must be */
609+ /* because the name has only appeared inside a load script and not */
610+ /* on the command line */
611+ search = new_afile(name, lang_input_file_is_file_enum, target);
612+ Q_read_file_symbols(search);
613+ return search;
614+}
615+
616+static void
617+
618+wild(s, section, file, target, output)
619+lang_wild_statement_type *s;
620+char *section;
621+char *file;
622+char *target;
623+lang_output_section_statement_type *output;
624+{
625+ lang_input_statement_type *f;
626+ if (file == (char *)NULL) {
627+ /* Perform the iteration over all files in the list */
628+ for (f = (lang_input_statement_type *)file_chain.head;
629+ f != (lang_input_statement_type *)NULL;
630+ f = (lang_input_statement_type *)f->next) {
631+ wild_section(s, section, f, output);
632+ }
633+ }
634+ else {
635+ /* Perform the iteration over a single file */
636+ wild_section( s, section, lookup_name(file, target), output);
637+ }
638+}
639+
640+/*
641+ read in all the files
642+ */
643+static bfd *
644+open_output(name, target)
645+char *name;
646+char *target;
647+{
648+ extern char *output_filename;
649+ bfd * output = bfd_openw(name, target);
650+ output_filename = name;
651+ if (output == (bfd *)NULL)
652+ {
653+ if (bfd_error == invalid_target) {
654+ info("%P%F target %s not found\n", target);
655+ }
656+ info("%P%F problem opening output file %s, %E", name);
657+ }
658+
659+ output->flags |= D_PAGED;
660+ bfd_set_format(output, bfd_object);
661+ return output;
662+}
663+extern char *default_target;
664+static void
665+lang_phase_0(sh,target)
666+lang_statement_union_type *sh;
667+char *target;
668+{
669+ lang_statement_union_type *s = (lang_statement_union_type *)sh;
670+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
671+ {
672+ switch (s->header.type) {
673+ case lang_output_section_statement_enum:
674+ lang_phase_0(s->output_section_statement.children.head,
675+ target);
676+ break;
677+ case lang_output_statement_enum:
678+#if 1
679+ output_bfd = open_output(s->output_statement.name,
680+ target == (char *)NULL ?
681+ default_target : target);
682+ ldemul_set_output_arch();
683+#endif
684+ break;
685+ case lang_target_statement_enum:
686+ target = s->target_statement.target;
687+ break;
688+ case lang_wild_statement_enum:
689+ /* Maybe we should load the file's symbols */
690+ if (s->wild_statement.filename) {
691+ (void) lookup_name(s->wild_statement.filename, target);
692+ }
693+ break;
694+ /* Attatch this to the current output section */
695+ case lang_common_statement_enum:
696+ case lang_fill_statement_enum:
697+ case lang_input_section_enum:
698+ case lang_object_symbols_statement_enum:
699+ case lang_address_statement_enum:
700+ case lang_data_statement_enum:
701+ break;
702+ case lang_afile_asection_pair_statement_enum:
703+
704+ FAIL();
705+ break;
706+
707+ case lang_input_statement_enum:
708+ if (s->input_statement.real == true) {
709+ s->input_statement.target = target;
710+ lookup_name(s->input_statement.filename, target);
711+ }
712+ break;
713+ case lang_assignment_statement_enum:
714+#if 0
715+ (void) exp_fold_tree(s->assignment_statement.exp,
716+ output_section,
717+ false);
718+#endif
719+ break;
720+
721+ case lang_padding_statement_enum:
722+
723+ break;
724+ }
725+ }
726+
727+}
728+
729+/* If there are [COMMONS] statements, put a wild one into the bss section */
730+
731+static void
732+lang_reasonable_defaults()
733+{
734+ default_common_section =
735+ lang_output_section_statement_lookup(".bss");
736+ if (placed_commons == false) {
737+ lang_wild_statement_type *new =
738+ new_stat(lang_wild_statement,
739+ &default_common_section->children);
740+ new->section_name = "COMMON";
741+ new->filename = (char *)NULL;
742+ lang_list_init(&new->children);
743+ }
744+}
745+
746+static void lang()
747+{
748+ if (had_script == false) {
749+ parse_line(ldemul_get_script());
750+ }
751+
752+ lang_reasonable_defaults();
753+ lang_phase_0(statement_list.head,default_target);
754+}
755+
756+
757+/* Open input files and attatch to output sections */
758+static void
759+lang_open_input(s, target, output_section_statement)
760+lang_statement_union_type *s;
761+char *target;
762+lang_output_section_statement_type *output_section_statement;
763+{
764+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
765+ {
766+ switch (s->header.type) {
767+ case lang_wild_statement_enum:
768+ wild(&s->wild_statement, s->wild_statement.section_name,
769+ s->wild_statement.filename, target,
770+ output_section_statement);
771+
772+ break;
773+
774+ case lang_output_section_statement_enum:
775+ lang_open_input(s->output_section_statement.children.head,
776+ target,
777+ &s->output_section_statement);
778+ break;
779+ case lang_output_statement_enum:
780+ break;
781+ case lang_target_statement_enum:
782+ target = s->target_statement.target;
783+ break;
784+ case lang_common_statement_enum:
785+ case lang_fill_statement_enum:
786+ case lang_input_section_enum:
787+ case lang_object_symbols_statement_enum:
788+ case lang_data_statement_enum:
789+ break;
790+ case lang_afile_asection_pair_statement_enum:
791+ FAIL();
792+ break;
793+
794+ case lang_assignment_statement_enum:
795+ case lang_padding_statement_enum:
796+
797+ break;
798+ case lang_address_statement_enum:
799+ /* Mark the specified section with the supplied address */
800+ {
801+ lang_output_section_statement_type *os =
802+ lang_output_section_statement_lookup
803+ (s->address_statement.section_name);
804+ os->addr_tree = s->address_statement.address;
805+ }
806+ break;
807+ case lang_input_statement_enum:
808+ /* A standard input statement, has no wildcards */
809+ /* Q_read_file_symbols(&s->input_statement);*/
810+ break;
811+ }
812+ }
813+}
814+
815+
816+
817+
818+
819+static void
820+print_output_section_statement(output_section_statement)
821+lang_output_section_statement_type *output_section_statement;
822+{
823+ asection *section = output_section_statement->bfd_section;
824+ print_nl();
825+ print_section(output_section_statement->name);
826+
827+ if (section) {
828+ print_dot = section->vma;
829+ print_space();
830+ print_section("");
831+ print_space();
832+ print_address(section->vma);
833+ print_space();
834+ print_size(section->size);
835+ print_space();
836+ print_alignment(section->alignment_power);
837+ print_space();
838+#if 0
839+ printf("%s flags", output_section_statement->region->name);
840+ print_flags(stdout, &output_section_statement->flags);
841+#endif
842+
843+ }
844+ else {
845+ printf("No attached output section");
846+ }
847+ print_nl();
848+ print_statement(output_section_statement->children.head,
849+ output_section_statement);
850+
851+}
852+
853+static void
854+print_assignment(assignment, output_section)
855+lang_assignment_statement_type *assignment;
856+lang_output_section_statement_type *output_section;
857+{
858+ etree_value_type result;
859+ print_section("");
860+ print_space();
861+ print_section("");
862+ print_space();
863+ print_address(print_dot);
864+ print_space();
865+ result = exp_fold_tree(assignment->exp->assign.src,
866+ output_section,
867+ lang_final_phase_enum,
868+ print_dot,
869+ &print_dot);
870+
871+ if (result.valid) {
872+ print_address(result.value);
873+ }
874+ else
875+ {
876+ printf("*undefined*");
877+ }
878+ print_space();
879+ exp_print_tree(stdout, assignment->exp);
880+ printf("\n");
881+}
882+
883+static void
884+print_input_statement(statm)
885+lang_input_statement_type *statm;
886+{
887+ printf("LOAD %s\n",statm->filename);
888+}
889+
890+static void print_symbol(q)
891+asymbol *q;
892+{
893+ print_section("");
894+ printf(" ");
895+ print_section("");
896+ printf(" ");
897+ print_address(outside_symbol_address(q));
898+ printf(" %s", q->name ? q->name : " ");
899+ print_nl();
900+}
901+static void
902+print_input_section(in)
903+lang_input_section_type *in;
904+{
905+ asection *i = in->section;
906+
907+ if(i->size != 0) {
908+ print_section("");
909+ printf(" ");
910+ print_section(i->name);
911+ printf(" ");
912+ if (i->output_section) {
913+ print_address(i->output_section->vma + i->output_offset);
914+ printf(" ");
915+ print_size(i->size);
916+ printf(" ");
917+ print_alignment(i->alignment_power);
918+ printf(" ");
919+ if (in->ifile) {
920+ bfd *abfd = in->ifile->the_bfd;
921+ printf(" %s ",abfd->xvec->name);
922+ if(abfd->my_archive != (bfd *)NULL) {
923+ printf("[%s]%s", abfd->my_archive->filename,
924+ abfd->filename);
925+ }
926+ else {
927+ printf("%s", abfd->filename);
928+ }
929+ print_nl();
930+
931+ /* Find all the symbols in this file defined in this section */
932+ {
933+ asymbol **p;
934+ for (p = in->ifile->asymbols; *p; p++) {
935+ asymbol *q = *p;
936+
937+ if (bfd_get_section(q) == i && q->flags & BSF_GLOBAL) {
938+ print_symbol(q);
939+ }
940+ }
941+ }
942+ }
943+ else {
944+ print_nl();
945+ }
946+
947+
948+ print_dot = outside_section_address(i) + i->size;
949+ }
950+ else {
951+ printf("No output section allocated\n");
952+ }
953+ }
954+}
955+static void
956+print_common_statement()
957+{
958+ ldsym_type *lgs;
959+ print_section("");
960+ print_space();
961+ print_section(common_section.output_section->name);
962+ print_space();
963+ print_address(common_section.output_offset +
964+ common_section.output_section->vma);
965+ print_space();
966+ print_size(common_section.size);
967+ print_space();
968+ printf("(common)");
969+ print_nl();
970+ /* Print out all the global symbols */
971+
972+
973+ for (lgs = symbol_head; lgs != (ldsym_type *)NULL; lgs =
974+ lgs->next) {
975+ if (lgs->sdefs_chain) {
976+ asymbol *def = *(lgs->sdefs_chain);
977+ if (def->section == &common_section) {
978+ print_symbol(def);
979+ }
980+ }
981+
982+ }
983+ print_dot = common_section.output_offset +
984+ common_section.output_section->vma + common_section.size;
985+
986+
987+}
988+static void
989+print_fill_statement(fill)
990+lang_fill_statement_type *fill;
991+{
992+ printf("FILL mask ");
993+ print_fill( fill->fill);
994+}
995+
996+static void
997+print_data_statement(data)
998+lang_data_statement_type *data;
999+{
1000+/* bfd_vma value; */
1001+ print_section("");
1002+ print_space();
1003+ print_section("");
1004+ print_space();
1005+ ASSERT(print_dot == data->output_vma);
1006+
1007+ print_address(data->output_vma);
1008+ print_space();
1009+ print_address(data->value);
1010+ print_space();
1011+ switch (data->type) {
1012+ case BYTE :
1013+ printf("BYTE ");
1014+ print_dot += BYTE_SIZE;
1015+ break;
1016+ case SHORT:
1017+ printf("SHORT ");
1018+ print_dot += SHORT_SIZE;
1019+ break;
1020+ case LONG:
1021+ printf("LONG ");
1022+ print_dot += LONG_SIZE;
1023+ break;
1024+ }
1025+
1026+ exp_print_tree(stdout, data->exp);
1027+
1028+ printf("\n");
1029+}
1030+
1031+
1032+static void
1033+print_padding_statement(s)
1034+lang_padding_statement_type *s;
1035+{
1036+ print_section("");
1037+ print_space();
1038+ print_section("*fill*");
1039+ print_space();
1040+ print_address(s->output_offset + s->output_section->vma);
1041+ print_space();
1042+ print_size(s->size);
1043+ print_space();
1044+ print_fill(s->fill);
1045+ print_nl();
1046+}
1047+
1048+static void print_wild_statement(w,os)
1049+lang_wild_statement_type *w;
1050+lang_output_section_statement_type *os;
1051+{
1052+ if (w->filename != (char *)NULL) {
1053+ printf("%s",w->filename);
1054+ }
1055+ else {
1056+ printf("*");
1057+ }
1058+ if (w->section_name != (char *)NULL) {
1059+ printf("(%s)",w->section_name);
1060+ }
1061+ else {
1062+ printf("(*)");
1063+ }
1064+ print_nl();
1065+ print_statement(w->children.head, os);
1066+
1067+}
1068+static void
1069+print_statement(s, os)
1070+lang_statement_union_type *s;
1071+lang_output_section_statement_type *os;
1072+{
1073+ while (s) {
1074+ switch (s->header.type) {
1075+ case lang_wild_statement_enum:
1076+ print_wild_statement(&s->wild_statement, os);
1077+ break;
1078+ default:
1079+ printf("Fail with %d\n",s->header.type);
1080+ FAIL();
1081+ break;
1082+ case lang_address_statement_enum:
1083+ printf("address\n");
1084+ break;
1085+ case lang_common_statement_enum:
1086+ print_common_statement();
1087+ break;
1088+ case lang_object_symbols_statement_enum:
1089+ printf("object symbols\n");
1090+ break;
1091+ case lang_fill_statement_enum:
1092+ print_fill_statement(&s->fill_statement);
1093+ break;
1094+ case lang_data_statement_enum:
1095+ print_data_statement(&s->data_statement);
1096+ break;
1097+
1098+
1099+ case lang_input_section_enum:
1100+ print_input_section(&s->input_section);
1101+ break;
1102+ case lang_padding_statement_enum:
1103+ print_padding_statement(&s->padding_statement);
1104+ break;
1105+ case lang_output_section_statement_enum:
1106+ print_output_section_statement(&s->output_section_statement);
1107+ break;
1108+ case lang_assignment_statement_enum:
1109+ print_assignment(&s->assignment_statement,
1110+ os);
1111+ break;
1112+
1113+
1114+ case lang_target_statement_enum:
1115+ printf("TARGET(%s)\n", s->target_statement.target);
1116+ break;
1117+ case lang_output_statement_enum:
1118+ printf("OUTPUT(%s)\n", s->output_statement.name);
1119+ break;
1120+ case lang_input_statement_enum:
1121+ print_input_statement(&s->input_statement);
1122+ break;
1123+ case lang_afile_asection_pair_statement_enum:
1124+ FAIL();
1125+ break;
1126+ }
1127+ s = s->next;
1128+ }
1129+}
1130+
1131+
1132+static void
1133+print_statements()
1134+{
1135+ print_statement(statement_list.head,
1136+ (lang_output_section_statement_type *)NULL);
1137+}
1138+
1139+static bfd_vma
1140+insert_pad(this_ptr, fill, power, output_section_statement, dot)
1141+lang_statement_union_type **this_ptr;
1142+fill_type fill;
1143+unsigned int power;
1144+asection * output_section_statement;
1145+bfd_vma dot;
1146+{
1147+ /* Align this section first to the
1148+ input sections requirement, then
1149+ to the output section's requirement.
1150+ If this alignment is > than any seen before,
1151+ then record it too. Perform the alignment by
1152+ inserting a magic 'padding' statement.
1153+ */
1154+
1155+ unsigned int alignment_needed = align_power(dot, power) - dot;
1156+
1157+ if (alignment_needed != 0)
1158+ {
1159+ lang_statement_union_type *new =
1160+ (lang_statement_union_type *)
1161+ ldmalloc(sizeof(lang_padding_statement_type));
1162+ /* Link into existing chain */
1163+ new->header.next = *this_ptr;
1164+ *this_ptr = new;
1165+ new->header.type = lang_padding_statement_enum;
1166+ new->padding_statement.output_section = output_section_statement;
1167+ new->padding_statement.output_offset =
1168+ dot - output_section_statement->vma;
1169+ new->padding_statement.fill = fill;
1170+ new->padding_statement.size = alignment_needed;
1171+ }
1172+
1173+
1174+ /* Remember the most restrictive alignment */
1175+ if (power > output_section_statement->alignment_power) {
1176+ output_section_statement->alignment_power = power;
1177+ }
1178+ output_section_statement->size += alignment_needed;
1179+ return alignment_needed + dot;
1180+
1181+}
1182+
1183+/*
1184+ size_common runs run though each global symboxl, and works
1185+ out how big the common section will be.
1186+ */
1187+
1188+static bfd_vma
1189+size_common(output_section_statement, this_ptr, dot)
1190+lang_output_section_statement_type *output_section_statement;
1191+lang_statement_union_type **this_ptr;
1192+bfd_vma dot;
1193+{
1194+ extern ldsym_type *symbol_head;
1195+ ldsym_type *sp;
1196+ /* Make sure that each symbol is only defined once.
1197+ Allocate common symbols
1198+ Make the ref chain point to the defining asymbol.
1199+ */
1200+ /* Now, for each symbol, verify that it is defined globally at most once.
1201+ Put the global value into the symbol entry.
1202+ Common symbols are allocated here, in the BSS section.
1203+ Each defined symbol is given a '->defined' field
1204+ which is the correct N_ code for its definition,
1205+ except in the case of common symbols with -r.
1206+ Then make all the references point at the symbol entry
1207+ instead of being chained together. */
1208+
1209+
1210+ common_section.name = output_section_statement->bfd_section->name;
1211+ common_section.output_section = output_section_statement->bfd_section;
1212+ common_section.output_offset =
1213+ dot - output_section_statement->bfd_section->vma;
1214+ if (config.relocateable_output == false ||
1215+ command_line.force_common_definition== true) {
1216+ dot = insert_pad(this_ptr,
1217+ 0x0, 4, output_section_statement->bfd_section, dot);
1218+
1219+ for (sp = symbol_head; sp != (ldsym_type *)NULL; sp = sp->next)
1220+ {
1221+ /* Attatch this symbol to the correct output section*/
1222+
1223+ /* Allocate as common if wanted */
1224+
1225+ if (sp->scoms_chain )
1226+
1227+ {
1228+ unsigned long com = (*(sp->scoms_chain))->value;
1229+ /* Work out what alignment this common item s
1230+ hould be put on. Anything < int is int aligned,
1231+ anything bigger is self aligned,
1232+ up to the restriction of the machine */
1233+
1234+ unsigned int align = sizeof(int);
1235+
1236+ /* Round up size of object to nearest int */
1237+ com = ALIGN(com, sizeof(int));
1238+ /* See what alignment is necessary -*/
1239+ if (com) {
1240+ while ((com & align)==0) align <<=1;
1241+ /* FIXME */
1242+ if (align > 8) {
1243+ align = 8;
1244+ }
1245+ }
1246+ dot = ALIGN(dot, align);
1247+
1248+
1249+ /* Transmogrify this from a common symbol
1250+ into a definition of a symbol in common
1251+ */
1252+ sp->sdefs_chain = sp->scoms_chain;
1253+
1254+ {
1255+ asymbol *com_ptr = *(sp->sdefs_chain);
1256+
1257+ sp->scoms_chain = (asymbol **)NULL;
1258+ commons_pending--;
1259+ /* Assign address, but keep section relative */
1260+
1261+ /* Force the symbol to belong in the bss section */
1262+ com_ptr->flags = BSF_EXPORT | BSF_GLOBAL ;
1263+ com_ptr->section = &common_section;
1264+ common_section.size += com;
1265+ if (write_map)
1266+ {
1267+ printf ("Allocating common %s: %lx at %lx\n",
1268+ sp->name,
1269+ com,
1270+ com_ptr->value);
1271+ }
1272+ com_ptr->value = common_section.size;
1273+ }
1274+ }
1275+ }
1276+ }
1277+ if (dot >
1278+ (common_section.output_section->vma +
1279+ common_section.output_section->size)) {
1280+ common_section.output_section->size =
1281+ dot - common_section.output_section->vma;
1282+ }
1283+ return dot + common_section.size;
1284+}
1285+
1286+static bfd_vma
1287+size_input_section( this_ptr, output_section_statement, fill, dot)
1288+lang_statement_union_type **this_ptr;
1289+lang_output_section_statement_type*output_section_statement;
1290+unsigned short fill;
1291+bfd_vma dot;
1292+{
1293+ lang_input_section_type *is = &((*this_ptr)->input_section);
1294+ asection *i = is->section;
1295+
1296+ dot = insert_pad(this_ptr, fill, i->alignment_power,
1297+ output_section_statement->bfd_section, dot);
1298+
1299+ /* remember the largest size so we can malloc the largest area */
1300+ /* needed for the output stage */
1301+ if (i->size > largest_section) {
1302+ largest_section = i->size;
1303+ }
1304+
1305+ /* Remember where in the output section this input section goes */
1306+ i->output_offset = dot - output_section_statement->bfd_section->vma;
1307+
1308+ /* Mark how big the output section must be to contain this now */
1309+ dot += i->size;
1310+ output_section_statement->bfd_section->size =
1311+ dot - output_section_statement->bfd_section->vma;
1312+
1313+
1314+ return dot ;
1315+}
1316+
1317+
1318+/* Work out the size of the output sections
1319+ from the sizes of the input sections */
1320+static bfd_vma
1321+lang_size_sections(s, output_section_statement, prev, fill, dot)
1322+lang_statement_union_type *s;
1323+lang_output_section_statement_type * output_section_statement;
1324+lang_statement_union_type **prev;
1325+unsigned short fill;
1326+bfd_vma dot;
1327+{
1328+ /* Size up the sections from their constituent parts */
1329+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
1330+ {
1331+ switch (s->header.type) {
1332+ case lang_output_section_statement_enum:
1333+ {
1334+ bfd_vma after;
1335+ lang_output_section_statement_type *os =
1336+ &(s->output_section_statement);
1337+ /* The start of a section */
1338+
1339+ if (os->addr_tree == (etree_type *)NULL) {
1340+ /* No address specified for this section, get one
1341+ from the region specification
1342+ */
1343+ if (os->region == (lang_memory_region_type *)NULL) {
1344+ os->region = lang_memory_region_lookup("*default*");
1345+ }
1346+ dot = os->region->current;
1347+ }
1348+ else {
1349+ etree_value_type r ;
1350+ r = exp_fold_tree(os->addr_tree,
1351+ (lang_output_section_statement_type *)NULL,
1352+ lang_allocating_phase_enum,
1353+ dot, &dot);
1354+ if (r.valid == false) {
1355+ info("%F%S: non constant address expression for section %s\n",
1356+ os->name);
1357+ }
1358+ dot = r.value;
1359+ }
1360+ /* The section starts here */
1361+ /* First, align to what the section needs */
1362+
1363+ dot = align_power(dot, os->bfd_section->alignment_power);
1364+ os->bfd_section->vma = dot;
1365+ os->bfd_section->output_offset = 0;
1366+
1367+ (void) lang_size_sections(os->children.head, os, &os->children.head,
1368+ os->fill, dot);
1369+ /* Ignore the size of the input sections, use the vma and size to */
1370+ /* align against */
1371+
1372+
1373+ after = ALIGN(os->bfd_section->vma +
1374+ os->bfd_section->size,
1375+ os->block_value) ;
1376+
1377+
1378+ os->bfd_section->size = after - os->bfd_section->vma;
1379+ dot = os->bfd_section->vma + os->bfd_section->size;
1380+ os->processed = true;
1381+
1382+ /* Replace into region ? */
1383+ if (os->addr_tree == (etree_type *)NULL
1384+ && os->region !=(lang_memory_region_type*)NULL ) {
1385+ os->region->current = dot;
1386+ }
1387+ }
1388+
1389+ break;
1390+
1391+ case lang_data_statement_enum:
1392+ {
1393+ unsigned int size;
1394+ s->data_statement.output_vma = dot;
1395+ s->data_statement.output_section =
1396+ output_section_statement->bfd_section;
1397+
1398+ switch (s->data_statement.type) {
1399+ case LONG:
1400+ size = LONG_SIZE;
1401+ break;
1402+ case SHORT:
1403+ size = SHORT_SIZE;
1404+ break;
1405+ case BYTE:
1406+ size = BYTE_SIZE;
1407+ break;
1408+
1409+ }
1410+ dot += size;
1411+ output_section_statement->bfd_section->size += size;
1412+ }
1413+ break;
1414+
1415+ case lang_wild_statement_enum:
1416+
1417+ dot = lang_size_sections(s->wild_statement.children.head,
1418+ output_section_statement,
1419+ &s->wild_statement.children.head,
1420+
1421+ fill, dot);
1422+
1423+ break;
1424+
1425+ case lang_object_symbols_statement_enum:
1426+ create_object_symbols = output_section_statement;
1427+ break;
1428+ case lang_output_statement_enum:
1429+
1430+ case lang_target_statement_enum:
1431+ break;
1432+ case lang_common_statement_enum:
1433+ dot = size_common(output_section_statement, prev, dot);
1434+
1435+ break;
1436+
1437+ case lang_input_section_enum:
1438+ dot = size_input_section(prev,
1439+ output_section_statement,
1440+ output_section_statement->fill, dot);
1441+ break;
1442+ case lang_input_statement_enum:
1443+ break;
1444+ case lang_fill_statement_enum:
1445+ fill = s->fill_statement.fill;
1446+ break;
1447+ case lang_assignment_statement_enum:
1448+ {
1449+ bfd_vma newdot = dot;
1450+ exp_fold_tree(s->assignment_statement.exp,
1451+ output_section_statement,
1452+ lang_allocating_phase_enum,
1453+ dot,
1454+ &newdot);
1455+
1456+ if (newdot != dot)
1457+ /* We've been moved ! so insert a pad */
1458+ {
1459+ lang_statement_union_type *new =
1460+ (lang_statement_union_type *)
1461+ ldmalloc(sizeof(lang_padding_statement_type));
1462+ /* Link into existing chain */
1463+ new->header.next = *prev;
1464+ *prev = new;
1465+ new->header.type = lang_padding_statement_enum;
1466+ new->padding_statement.output_section =
1467+ output_section_statement->bfd_section;
1468+ new->padding_statement.output_offset =
1469+ dot - output_section_statement->bfd_section->vma;
1470+ new->padding_statement.fill = fill;
1471+ new->padding_statement.size = newdot - dot;
1472+ output_section_statement->bfd_section->size +=
1473+ new->padding_statement.size;
1474+ dot = newdot;
1475+ }
1476+ }
1477+
1478+ break;
1479+ case lang_padding_statement_enum:
1480+ FAIL();
1481+ break;
1482+ default:
1483+ FAIL();
1484+ break;
1485+ case lang_address_statement_enum:
1486+ break;
1487+ }
1488+ prev = &s->header.next;
1489+ }
1490+ return dot;
1491+}
1492+
1493+
1494+static bfd_vma
1495+lang_do_assignments(s, output_section_statement, fill, dot)
1496+lang_statement_union_type *s;
1497+lang_output_section_statement_type * output_section_statement;
1498+unsigned short fill;
1499+bfd_vma dot;
1500+{
1501+
1502+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
1503+ {
1504+ switch (s->header.type) {
1505+ case lang_output_section_statement_enum:
1506+ {
1507+ lang_output_section_statement_type *os =
1508+ &(s->output_section_statement);
1509+ dot = os->bfd_section->vma;
1510+ (void) lang_do_assignments(os->children.head, os, os->fill, dot);
1511+ dot = os->bfd_section->vma + os->bfd_section->size;
1512+ }
1513+ break;
1514+ case lang_wild_statement_enum:
1515+
1516+ dot = lang_do_assignments(s->wild_statement.children.head,
1517+ output_section_statement,
1518+ fill, dot);
1519+
1520+ break;
1521+
1522+ case lang_object_symbols_statement_enum:
1523+ case lang_output_statement_enum:
1524+ case lang_target_statement_enum:
1525+ case lang_common_statement_enum:
1526+ break;
1527+ case lang_data_statement_enum:
1528+ {
1529+ etree_value_type value ;
1530+ value = exp_fold_tree(s->data_statement.exp,
1531+ 0, lang_final_phase_enum, dot, &dot);
1532+ s->data_statement.value = value.value;
1533+ if (value.valid == false) info("%F%P: Invalid data statement\n");
1534+ }
1535+ switch (s->data_statement.type) {
1536+ case LONG:
1537+ dot += LONG_SIZE;
1538+ break;
1539+ case SHORT:
1540+ dot += SHORT_SIZE;
1541+ break;
1542+ case BYTE:
1543+ dot += BYTE_SIZE;
1544+ break;
1545+ }
1546+ break;
1547+ case lang_input_section_enum:
1548+ {
1549+ asection *in = s->input_section.section;
1550+ dot += in->size;
1551+ }
1552+ break;
1553+
1554+ case lang_input_statement_enum:
1555+ break;
1556+ case lang_fill_statement_enum:
1557+ fill = s->fill_statement.fill;
1558+ break;
1559+ case lang_assignment_statement_enum:
1560+ {
1561+ exp_fold_tree(s->assignment_statement.exp,
1562+ output_section_statement,
1563+ lang_final_phase_enum,
1564+ dot,
1565+ &dot);
1566+ }
1567+
1568+ break;
1569+ case lang_padding_statement_enum:
1570+ dot += s->padding_statement.size;
1571+ break;
1572+ default:
1573+ FAIL();
1574+ break;
1575+ case lang_address_statement_enum:
1576+ break;
1577+ }
1578+
1579+ }
1580+ return dot;
1581+}
1582+
1583+
1584+
1585+static void lang_relocate_globals()
1586+{
1587+
1588+ /*
1589+ Each ldsym_type maintains a chain of pointers to asymbols which
1590+ references the definition. Replace each pointer to the referenence
1591+ with a pointer to only one place, preferably the definition. If
1592+ the defintion isn't available then the common symbol, and if
1593+ there isn't one of them then choose one reference.
1594+ */
1595+
1596+ FOR_EACH_LDSYM(lgs) {
1597+ asymbol *it;
1598+ if (lgs->sdefs_chain) {
1599+ it = *(lgs->sdefs_chain);
1600+ }
1601+ else if (lgs->scoms_chain != (asymbol **)NULL) {
1602+ it = *(lgs->scoms_chain);
1603+ }
1604+ else if (lgs->srefs_chain != (asymbol **)NULL) {
1605+ it = *(lgs->srefs_chain);
1606+ }
1607+ else {
1608+ FAIL();
1609+ }
1610+ if (it != (asymbol *)NULL)
1611+ {
1612+ asymbol **ptr= lgs->srefs_chain;
1613+
1614+ while (ptr != (asymbol **)NULL) {
1615+ asymbol *ref = *ptr;
1616+ *ptr = it;
1617+ ptr = (asymbol **)(ref->udata);
1618+ }
1619+ }
1620+ }
1621+}
1622+
1623+
1624+
1625+/* now that all the jiggery pokery is finished, copy important data from
1626+ * out internal form to the bfd way. Also create a section
1627+ * for each dummy file
1628+ */
1629+
1630+static void
1631+lang_create_output_section_statements()
1632+{
1633+ lang_statement_union_type*os;
1634+ for (os = lang_output_section_statement.head;
1635+ os != (lang_statement_union_type*)NULL;
1636+ os = os->output_section_statement.next) {
1637+ lang_output_section_statement_type *s =
1638+ &os->output_section_statement;
1639+ init_os(s);
1640+ }
1641+ script_file->the_bfd->sections = output_bfd->sections;
1642+}
1643+
1644+static void
1645+lang_finish()
1646+{
1647+ ldsym_type *lgs;
1648+
1649+ if (entry_symbol == (char *)NULL) {
1650+ /* No entry has been specified, look for start */
1651+ entry_symbol = "start";
1652+ }
1653+ lgs = ldsym_get_soft(entry_symbol);
1654+ if (lgs && lgs->sdefs_chain) {
1655+ asymbol *sy = *(lgs->sdefs_chain);
1656+ /* We can set the entry address*/
1657+ bfd_set_start_address(output_bfd,
1658+ outside_symbol_address(sy));
1659+
1660+ }
1661+ else {
1662+ /* Can't find anything reasonable,
1663+ use the first address in the text section
1664+ */
1665+ asection *ts = bfd_get_section_by_name(output_bfd, ".text");
1666+ if (ts) {
1667+ bfd_set_start_address(output_bfd, ts->vma);
1668+ }
1669+ }
1670+}
1671+
1672+/* By now we know the target architecture, and we may have an */
1673+/* ldfile_output_machine_name */
1674+static void
1675+lang_check()
1676+{
1677+ lang_statement_union_type *file;
1678+
1679+
1680+ for (file = file_chain.head;
1681+ file != (lang_statement_union_type *)NULL;
1682+ file=file->input_statement.next)
1683+ {
1684+ /* Inspect the architecture and ensure we're linking like
1685+ with like
1686+ */
1687+
1688+ if (bfd_arch_compatible( file->input_statement.the_bfd,
1689+ output_bfd,
1690+ &ldfile_output_architecture,
1691+ &ldfile_output_machine)) {
1692+ bfd_set_arch_mach(output_bfd,
1693+ ldfile_output_architecture, ldfile_output_machine);
1694+ }
1695+ else {
1696+ enum bfd_architecture this_architecture =
1697+ bfd_get_architecture(file->input_statement.the_bfd);
1698+ unsigned long this_machine =
1699+ bfd_get_machine(file->input_statement.the_bfd);
1700+
1701+ info("%I: architecture %s",
1702+ file,
1703+ bfd_printable_arch_mach(this_architecture, this_machine));
1704+ info(" incompatible with output %s\n",
1705+ bfd_printable_arch_mach(ldfile_output_architecture,
1706+ ldfile_output_machine));
1707+ ldfile_output_architecture = this_architecture;
1708+ ldfile_output_machine = this_machine;
1709+ bfd_set_arch_mach(output_bfd,
1710+ ldfile_output_architecture,
1711+ ldfile_output_machine);
1712+
1713+
1714+ }
1715+ }
1716+}
1717+
1718+
1719+/*
1720+ * run through all the global common symbols and tie them
1721+ * to the output section requested.
1722+ */
1723+
1724+static void
1725+lang_common()
1726+{
1727+ ldsym_type *lgs;
1728+ if (config.relocateable_output == false ||
1729+ command_line.force_common_definition== true) {
1730+ for (lgs = symbol_head;
1731+ lgs != (ldsym_type *)NULL;
1732+ lgs=lgs->next)
1733+ {
1734+ asymbol *com ;
1735+ size_t size;
1736+ size_t align;
1737+ if (lgs->scoms_chain != (asymbol **)NULL) {
1738+
1739+ com = *(lgs->scoms_chain);
1740+ size = com->value;
1741+ align = sizeof(int);
1742+ /* Round up size of object to nearest int */
1743+ size = ALIGN(size, sizeof(int));
1744+ /* Force alignment */
1745+ if (size) {
1746+ while ((size & align)==0) align<<=1;
1747+ if (align > 8) {
1748+ align = 8;
1749+ }
1750+ }
1751+ /* Change from a common symbol into a definition of
1752+ a symbol */
1753+ lgs->sdefs_chain = lgs->scoms_chain;
1754+ lgs->scoms_chain = (asymbol **)NULL;
1755+ commons_pending--;
1756+ /* Point to the correct common section */
1757+ com->section =
1758+ ((lang_input_statement_type *)
1759+ (com->the_bfd->usrdata))->common_section;
1760+ /* Fix the size of the common section */
1761+
1762+
1763+ com->flags = BSF_EXPORT | BSF_GLOBAL;
1764+
1765+ if (write_map)
1766+ {
1767+ printf ("Allocating common %s: %x at %x\n",
1768+ lgs->name,
1769+ (unsigned) size,
1770+ (unsigned) com->section->size);
1771+ }
1772+ com->value = com->section->size;
1773+ com->section->size += size;
1774+ }
1775+ }
1776+ }
1777+}
1778+
1779+/*
1780+run through the input files and ensure that every input
1781+section has somewhere to go. If one is found without
1782+a destination then create an input request and place it
1783+into the statement tree.
1784+*/
1785+
1786+static void lang_place_orphans()
1787+{
1788+ lang_input_statement_type *file;
1789+ for (file = (lang_input_statement_type*)file_chain.head;
1790+ file != (lang_input_statement_type*)NULL;
1791+ file = (lang_input_statement_type*)file->next) {
1792+ asection *s;
1793+ for (s = file->the_bfd->sections;
1794+ s != (asection *)NULL;
1795+ s = s->next) {
1796+ if ( s->output_section == (asection *)NULL) {
1797+ /* This section of the file is not attatched, root
1798+ around for a sensible place for it to go */
1799+
1800+ if (file->common_section == s) {
1801+ /* This is a lonely common section which must
1802+ have come from an archive. We attatch to the
1803+ section with the wildcard */
1804+ wild_doit(&default_common_section->children, s,
1805+ default_common_section, file);
1806+ }
1807+ else {
1808+ lang_output_section_statement_type *os =
1809+ lang_output_section_statement_lookup(s->name);
1810+
1811+ wild_doit(&os->children, s, os, file);
1812+ }
1813+ }
1814+ }
1815+
1816+ }
1817+}
1818+
1819+
1820+/*
1821+ * phase_2
1822+ *
1823+ * peformed after every file has been opened and symbols read
1824+ */
1825+static void
1826+lang_phase_2()
1827+{
1828+ lang_init2();
1829+
1830+ lang_create_output_section_statements();
1831+ lang_open_input(statement_list.head, (char *)NULL,
1832+ ( lang_output_section_statement_type *)NULL);
1833+ lang_place_orphans();
1834+ lang_common();
1835+
1836+ ldemul_before_allocation();
1837+
1838+ lang_size_sections(statement_list.head,
1839+ (lang_output_section_statement_type *)NULL,
1840+ &(statement_list.head), 0, (bfd_vma)0);
1841+ ldemul_after_allocation();
1842+ /* Do it once again now that we know the sizes of everything */
1843+
1844+ lang_do_assignments(statement_list.head,
1845+ (lang_output_section_statement_type *)NULL,
1846+ 0, (bfd_vma)0);
1847+
1848+
1849+
1850+ lang_check();
1851+
1852+ lang_relocate_globals();
1853+
1854+
1855+ lang_finish();
1856+}
1857+
1858+
1859+
1860+
1861+void
1862+lang_set_flags(ptr, flags)
1863+lang_section_flags_type *ptr;
1864+char *flags;
1865+{
1866+ boolean state = true;
1867+ ptr->flag_read = false;
1868+ ptr->flag_write = false;
1869+ ptr->flag_executable = false;
1870+ ptr->flag_loadable= false;
1871+ while (*flags)
1872+ {
1873+ if (*flags == '!') {
1874+ state = false;
1875+ flags++;
1876+ }
1877+ else state = true;
1878+ switch (*flags) {
1879+ case 'R':
1880+ ptr->flag_read = state;
1881+ break;
1882+ case 'W':
1883+ ptr->flag_write = state;
1884+ break;
1885+ case 'X':
1886+ ptr->flag_executable= state;
1887+ break;
1888+ case 'L':
1889+ ptr->flag_loadable= state;
1890+ break;
1891+ default:
1892+ info("%P%F illegal syntax in flags\n");
1893+ break;
1894+ }
1895+ flags++;
1896+ }
1897+}
1898+
1899+
1900+
1901+void
1902+lang_for_each_file(func)
1903+void (*func)();
1904+{
1905+ lang_input_statement_type *f;
1906+ for (f = (lang_input_statement_type *)file_chain.head;
1907+ f != (lang_input_statement_type *)NULL;
1908+ f = (lang_input_statement_type *)f->next)
1909+ {
1910+ func(f);
1911+ }
1912+}
1913+
1914+
1915+void
1916+lang_for_each_input_section(func)
1917+void (*func)();
1918+{
1919+ lang_input_statement_type *f;
1920+ for (f = (lang_input_statement_type *)file_chain.head;
1921+ f != (lang_input_statement_type *)NULL;
1922+ f = (lang_input_statement_type *)f->next)
1923+ {
1924+ asection *s;
1925+ for (s = f->the_bfd->sections;
1926+ s != (asection *)NULL;
1927+ s = s->next) {
1928+ func(f->the_bfd, s);
1929+ }
1930+ }
1931+}
1932+
1933+
1934+
1935+void
1936+ldlang_add_file(entry)
1937+lang_input_statement_type *entry;
1938+{
1939+ lang_has_input_file = true;
1940+ lang_statement_append(&file_chain,
1941+ (lang_statement_union_type *)entry,
1942+ &entry->next);
1943+}
1944+
1945+
1946+
1947+void
1948+lang_add_output(name)
1949+char *name;
1950+{
1951+ lang_output_statement_type *new = new_stat(lang_output_statement,
1952+ stat_ptr);
1953+ new->name = name;
1954+ had_output_filename = true;
1955+}
1956+
1957+
1958+static lang_output_section_statement_type *current_section;
1959+
1960+void
1961+lang_enter_output_section_statement(output_section_statement_name,
1962+address_exp,
1963+block_value)
1964+char *output_section_statement_name;
1965+etree_type *address_exp;
1966+bfd_vma block_value;
1967+{
1968+ lang_output_section_statement_type *os;
1969+ current_section =
1970+ os =
1971+ lang_output_section_statement_lookup(output_section_statement_name);
1972+
1973+
1974+ /* Add this statement to tree */
1975+ /* add_statement(lang_output_section_statement_enum,
1976+ output_section_statement);*/
1977+ /* Make next things chain into subchain of this */
1978+
1979+ if (os->addr_tree ==
1980+ (etree_type *)NULL) {
1981+ os->addr_tree =
1982+ address_exp;
1983+ }
1984+ os->block_value = block_value;
1985+ stat_ptr = & os->children;
1986+
1987+}
1988+
1989+
1990+void
1991+lang_final()
1992+{
1993+ if (had_output_filename == false) {
1994+ lang_add_output("a.out");
1995+ }
1996+
1997+
1998+}
1999+
2000+
2001+
2002+
2003+
2004+asymbol *create_symbol(name, flags, section)
2005+char *name;
2006+flagword flags;
2007+asection *section;
2008+{
2009+ extern lang_input_statement_type *script_file;
2010+ asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
2011+ /* Add this definition to script file */
2012+ asymbol *def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
2013+ def->name = name;
2014+ def->udata = 0;
2015+ def->flags = flags;
2016+ def->section = section;
2017+
2018+ *def_ptr = def;
2019+ Q_enter_global_ref(def_ptr);
2020+ return def;
2021+}
2022+
2023+
2024+void
2025+lang_process()
2026+{
2027+ lang();
2028+ lang_phase_2();
2029+}
2030+
2031+
2032+/* EXPORTED TO YACC */
2033+void
2034+lang_section_start(name, address)
2035+char *name;
2036+etree_type *address;
2037+{
2038+ lang_address_statement_type *ad =new_stat(lang_address_statement, stat_ptr);
2039+ ad->section_name = name;
2040+ ad->address = address;
2041+}
2042+void lang_add_entry(name)
2043+char *name;
2044+{
2045+ entry_symbol = name;
2046+}
2047+
2048+void
2049+lang_add_target(name)
2050+char *name;
2051+{
2052+ lang_target_statement_type *new = new_stat(lang_target_statement,
2053+ stat_ptr);
2054+ new->target = name;
2055+
2056+}
2057+void
2058+lang_add_wild(section_name, filename)
2059+char *section_name;
2060+char *filename;
2061+{
2062+ lang_wild_statement_type *new = new_stat(lang_wild_statement,
2063+ stat_ptr);
2064+
2065+ if (section_name != (char *)NULL && strcmp(section_name,"COMMON") == 0)
2066+ {
2067+ placed_commons = true;
2068+ }
2069+ new->section_name = section_name;
2070+ new->filename = filename;
2071+ lang_list_init(&new->children);
2072+}
2073+
2074+void
2075+lang_add_map(name)
2076+char *name;
2077+{
2078+ while (*name) {
2079+ switch (*name) {
2080+ case 'F':
2081+ map_option_f = true;
2082+ break;
2083+ }
2084+ name++;
2085+ }
2086+}
2087+
2088+void lang_add_fill(exp)
2089+int exp;
2090+{
2091+ lang_fill_statement_type *new = new_stat(lang_fill_statement,
2092+ stat_ptr);
2093+ new->fill = exp;
2094+}
2095+
2096+void lang_add_data(type, exp)
2097+int type;
2098+union etree_union *exp;
2099+{
2100+
2101+ lang_data_statement_type *new = new_stat(lang_data_statement,
2102+ stat_ptr);
2103+ new->exp = exp;
2104+ new->type = type;
2105+
2106+}
2107+void
2108+lang_add_assignment(exp)
2109+etree_type *exp;
2110+{
2111+ lang_assignment_statement_type *new = new_stat(lang_assignment_statement,
2112+ stat_ptr);
2113+ new->exp = exp;
2114+}
2115+
2116+void
2117+lang_add_attribute(attribute)
2118+enum statement_enum attribute;
2119+{
2120+ new_statement(attribute, sizeof(lang_statement_union_type),stat_ptr);
2121+}
2122+
2123+
2124+
2125+void
2126+lang_startup(name)
2127+char *name;
2128+{
2129+ if (startup_file != (char *)NULL) {
2130+ info("%P%FMultiple STARTUP files\n");
2131+ }
2132+ first_file->filename = name;
2133+ first_file->local_sym_name = name;
2134+
2135+ startup_file= name;
2136+}
2137+void
2138+lang_float(maybe)
2139+boolean maybe;
2140+{
2141+ lang_float_flag = maybe;
2142+}
2143+
2144+void
2145+lang_leave_output_section_statement(fill, memspec)
2146+bfd_vma fill;
2147+char *memspec;
2148+{
2149+ current_section->fill = fill;
2150+ current_section->region = lang_memory_region_lookup(memspec);
2151+ stat_ptr = &statement_list;
2152+}
2153+
2154+void
2155+lang_abs_symbol_at_end_of(section, name)
2156+char *section;
2157+char *name;
2158+{
2159+ extern bfd *output_bfd;
2160+ extern asymbol *create_symbol();
2161+ asection *s = bfd_get_section_by_name(output_bfd, section);
2162+ /* Add a symbol called _end */
2163+ asymbol *def = create_symbol(name,
2164+ BSF_GLOBAL | BSF_EXPORT |
2165+ BSF_ABSOLUTE,
2166+ (asection *)NULL);
2167+ if (s != (asection *)NULL) {
2168+ def->value = s->vma + s->size;
2169+ }
2170+ else {
2171+ def->value = 0;
2172+ }
2173+}
2174+
2175+void
2176+lang_statement_append(list, element, field)
2177+lang_statement_list_type *list;
2178+lang_statement_union_type *element;
2179+lang_statement_union_type **field;
2180+{
2181+ *(list->tail) = element;
2182+ list->tail = field;
2183+}
2184+
2185+
2186+static void
2187+lang_for_each_statement_worker(func, s)
2188+void (*func)();
2189+lang_statement_union_type *s;
2190+{
2191+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
2192+ {
2193+ func(s);
2194+
2195+ switch (s->header.type) {
2196+ case lang_output_section_statement_enum:
2197+ lang_for_each_statement_worker
2198+ (func,
2199+ s->output_section_statement.children.head);
2200+ break;
2201+ case lang_wild_statement_enum:
2202+ lang_for_each_statement_worker
2203+ (func,
2204+ s->wild_statement.children.head);
2205+ break;
2206+ case lang_data_statement_enum:
2207+ case lang_object_symbols_statement_enum:
2208+ case lang_output_statement_enum:
2209+ case lang_target_statement_enum:
2210+ case lang_common_statement_enum:
2211+ case lang_input_section_enum:
2212+ case lang_input_statement_enum:
2213+ case lang_fill_statement_enum:
2214+ case lang_assignment_statement_enum:
2215+ case lang_padding_statement_enum:
2216+ case lang_address_statement_enum:
2217+ break;
2218+ default:
2219+ FAIL();
2220+ break;
2221+ }
2222+ }
2223+}
2224+
2225+void lang_for_each_statement(func)
2226+void (*func)();
2227+{
2228+ lang_for_each_statement_worker(func,
2229+ statement_list.head);
2230+
2231+}
--- /dev/null
+++ b/ld/ldlang.h
@@ -0,0 +1,347 @@
1+/* ldlang.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+typedef enum {
23+ lang_input_file_is_l_enum,
24+ lang_input_file_is_symbols_only_enum,
25+ lang_input_file_is_marker_enum,
26+ lang_input_file_is_fake_enum,
27+lang_input_file_is_search_file_enum,
28+ lang_input_file_is_file_enum } lang_input_file_enum_type;
29+
30+typedef unsigned short fill_type;
31+typedef struct statement_list {
32+ union lang_statement_union *head;
33+ union lang_statement_union **tail;
34+} lang_statement_list_type;
35+
36+
37+typedef struct {
38+ boolean flag_read;
39+ boolean flag_write;
40+ boolean flag_executable;
41+ boolean flag_loadable;
42+} lang_section_flags_type;
43+
44+typedef struct memory_region_struct {
45+ char *name;
46+ struct memory_region_struct *next;
47+ bfd_vma origin;
48+ bfd_offset length;
49+ bfd_vma current;
50+ lang_section_flags_type flags;
51+} lang_memory_region_type ;
52+
53+typedef struct lang_statement_header_struct
54+{
55+union lang_statement_union *next;
56+ enum statement_enum {
57+ lang_output_section_statement_enum,
58+ lang_assignment_statement_enum,
59+ lang_input_statement_enum,
60+ lang_address_statement_enum,
61+ lang_wild_statement_enum,
62+ lang_input_section_enum,
63+ lang_common_statement_enum,
64+ lang_object_symbols_statement_enum,
65+ lang_fill_statement_enum,
66+ lang_data_statement_enum,
67+ lang_target_statement_enum,
68+ lang_output_statement_enum,
69+ lang_padding_statement_enum,
70+
71+ lang_afile_asection_pair_statement_enum
72+ } type;
73+
74+} lang_statement_header_type;
75+
76+
77+typedef struct
78+{
79+ lang_statement_header_type header;
80+ union etree_union *exp;
81+} lang_assignment_statement_type;
82+
83+
84+typedef struct lang_target_statement_struct {
85+ lang_statement_header_type header;
86+ char *target;
87+} lang_target_statement_type;
88+
89+
90+typedef struct lang_output_statement_struct {
91+ lang_statement_header_type header;
92+ char *name;
93+} lang_output_statement_type;
94+
95+
96+typedef struct lang_output_section_statement_struct
97+{
98+ lang_statement_header_type header;
99+ union etree_union *addr_tree;
100+ lang_statement_list_type children;
101+ char *memspec;
102+ union lang_statement_union *next;
103+ char *name;
104+ unsigned long subsection_alignment;
105+ boolean processed;
106+
107+ asection *bfd_section;
108+ lang_section_flags_type flags;
109+ struct memory_region_struct *region;
110+ size_t block_value;
111+ fill_type fill;
112+} lang_output_section_statement_type;
113+
114+
115+typedef struct {
116+ lang_statement_header_type header;
117+} lang_common_statement_type;
118+
119+typedef struct {
120+ lang_statement_header_type header;
121+} lang_object_symbols_statement_type;
122+
123+typedef struct {
124+ lang_statement_header_type header;
125+fill_type fill;
126+} lang_fill_statement_type;
127+
128+typedef struct {
129+ lang_statement_header_type header;
130+ unsigned int type;
131+ union etree_union *exp;
132+ bfd_vma value;
133+ asection *output_section;
134+ bfd_vma output_vma;
135+} lang_data_statement_type;
136+
137+
138+
139+
140+typedef struct lang_input_statement_struct
141+ {
142+ lang_statement_header_type header;
143+ /* Name of this file. */
144+ char *filename;
145+ /* Name to use for the symbol giving address of text start */
146+ /* Usually the same as filename, but for a file spec'd with -l
147+ this is the -l switch itself rather than the filename. */
148+ char *local_sym_name;
149+
150+ /* Describe the layout of the contents of the file */
151+
152+ /* The file's a.out header. */
153+ /* struct exec header;*/
154+ /* Offset in file of GDB symbol segment, or 0 if there is none. */
155+ int symseg_offset;
156+
157+ /* Describe data from the file loaded into core */
158+
159+ bfd *the_bfd;
160+
161+ boolean closed;
162+ file_ptr passive_position;
163+
164+ /* Symbol table of the file. */
165+ asymbol **asymbols;
166+ unsigned int symbol_count;
167+
168+ /* Next two used only if `relocatable_output' or if needed for */
169+ /* output of undefined reference line numbers. */
170+ /* Text reloc info saved by `write_text' for `coptxtrel'. */
171+
172+
173+ /* Offset in bytes in the output file symbol table
174+ of the first local symbol for this file. Set by `write_file_symbols'. */
175+ int local_syms_offset;
176+
177+ /* For library members only */
178+
179+ /* For a library, points to chain of entries for the library members. */
180+ struct lang_input_statement_struct *subfiles;
181+ /* For a library member, offset of the member within the archive.
182+ Zero for files that are not library members. */
183+ /* int starting_offset;*/
184+ /* Size of contents of this file, if library member. */
185+ int total_size;
186+ /* For library member, points to the library's own entry. */
187+ struct lang_input_statement_struct *superfile;
188+ /* For library member, points to next entry for next member. */
189+ struct lang_input_statement_struct *chain;
190+ /* Point to the next file - whatever it is, wanders up and down archives */
191+ union lang_statement_union *next;
192+ /* Point to the next file, but skips archive contents */
193+ union lang_statement_union *next_real_file;
194+
195+ boolean is_archive;
196+
197+ /* 1 if file's header has been read into this structure. */
198+ boolean header_read_flag;
199+
200+ /* 1 means search a set of directories for this file. */
201+ boolean search_dirs_flag;
202+
203+ /* 1 means this is base file of incremental load.
204+ Do not load this file's text or data.
205+ Also default text_start to after this file's bss. */
206+ boolean just_syms_flag;
207+
208+ boolean loaded;
209+
210+
211+ /* unsigned int globals_in_this_file;*/
212+ char *target;
213+ boolean real;
214+
215+ asection *common_section;
216+ asection *common_output_section;
217+ } lang_input_statement_type;
218+
219+typedef struct {
220+ lang_statement_header_type header;
221+ asection *section;
222+ lang_input_statement_type *ifile;
223+} lang_input_section_type;
224+
225+
226+typedef struct {
227+ lang_statement_header_type header;
228+ asection *section;
229+ union lang_statement_union *file;
230+} lang_afile_asection_pair_statement_type;
231+
232+typedef struct lang_wild_statement_struct {
233+ lang_statement_header_type header;
234+ char *section_name;
235+ char *filename;
236+ lang_statement_list_type children;
237+} lang_wild_statement_type;
238+
239+typedef struct lang_address_statement_struct {
240+ lang_statement_header_type header;
241+ char *section_name;
242+ union etree_union *address;
243+} lang_address_statement_type;
244+
245+typedef struct {
246+ lang_statement_header_type header;
247+ bfd_vma output_offset;
248+ size_t size;
249+ asection *output_section;
250+ fill_type fill;
251+} lang_padding_statement_type;
252+
253+typedef union lang_statement_union
254+{
255+ lang_statement_header_type header;
256+ union lang_statement_union *next;
257+ lang_wild_statement_type wild_statement;
258+ lang_data_statement_type data_statement;
259+ lang_address_statement_type address_statement;
260+ lang_output_section_statement_type output_section_statement;
261+ lang_afile_asection_pair_statement_type afile_asection_pair_statement;
262+ lang_assignment_statement_type assignment_statement;
263+ lang_input_statement_type input_statement;
264+ lang_target_statement_type target_statement;
265+ lang_output_statement_type output_statement;
266+ lang_input_section_type input_section;
267+ lang_common_statement_type common_statement;
268+ lang_object_symbols_statement_type object_symbols_statement;
269+ lang_fill_statement_type fill_statement;
270+ lang_padding_statement_type padding_statement;
271+} lang_statement_union_type;
272+
273+
274+
275+PROTO(void,lang_init,(void));
276+PROTO(struct memory_region_struct ,*lang_memory_region_lookup,(char *));
277+PROTO(struct lang_output_section_statement_struct *,lang_output_section_find,(char *));
278+
279+PROTO(void ,lang_map,(struct _iobuf *));
280+PROTO(void,lang_set_flags,(lang_section_flags_type *, char *));
281+PROTO(void,lang_add_output,(char *));
282+
283+PROTO(void,lang_final,(void));
284+PROTO(struct symbol_cache_entry *,create_symbol,(char *, unsigned int, struct sec_struct *));
285+PROTO(void ,lang_process,(void));
286+PROTO(void ,lang_section_start,(char *, union etree_union *));
287+PROTO(void,lang_add_entry,(char *));
288+PROTO(void,lang_add_target,(char *));
289+PROTO(void,lang_add_wild,(char *, char *));
290+PROTO(void,lang_add_map,(char *));
291+PROTO(void,lang_add_fill,(int));
292+PROTO(void,lang_add_assignment,(union etree_union *));
293+PROTO(void,lang_add_attribute,(enum statement_enum));
294+PROTO(void,lang_startup,(char *));
295+PROTO(void,lang_float,(enum boolean));
296+PROTO(void,lang_leave_output_section_statement,(bfd_vma, char *));
297+PROTO(void,lang_abs_symbol_at_end_of,(char *, char *));
298+PROTO(void,lang_statement_append,(struct statement_list *, union lang_statement_union *, union lang_statement_union **));
299+PROTO(void, lang_for_each_file,(void (*dothis)(lang_input_statement_type *)));
300+
301+#define LANG_FOR_EACH_ASYMBOL(asymbol) \
302+
303+#define LANG_FOR_EACH_INPUT_STATEMENT(statement) \
304+ extern lang_statement_list_type file_chain; \
305+ lang_input_statement_type *statement; \
306+ for (statement = (lang_input_statement_type *)file_chain.head;\
307+ statement != (lang_input_statement_type *)NULL; \
308+ statement = (lang_input_statement_type *)statement->next)\
309+
310+#define LANG_FOR_EACH_INPUT_SECTION(statement, abfd, section, x) \
311+{ extern lang_statement_list_type file_chain; \
312+ lang_input_statement_type *statement; \
313+ for (statement = (lang_input_statement_type *)file_chain.head;\
314+ statement != (lang_input_statement_type *)NULL; \
315+ statement = (lang_input_statement_type *)statement->next)\
316+ { \
317+ asection *section; \
318+ bfd *abfd = statement->the_bfd; \
319+ for (section = abfd->sections; \
320+ section != (asection *)NULL; \
321+ section = section->next) { \
322+ x; \
323+ } \
324+ } \
325+ }
326+
327+#define LANG_FOR_EACH_OUTPUT_SECTION(section, x) \
328+ { extern bfd *output_bfd; \
329+ asection *section; \
330+ for (section = output_bfd->sections; \
331+ section != (asection *)NULL; \
332+ section = section->next) \
333+ { x; } \
334+ }
335+
336+
337+PROTO(void, lang_process,(void));
338+PROTO(void, ldlang_add_file,(lang_input_statement_type *));
339+
340+PROTO(lang_output_section_statement_type *,lang_output_section_find,());
341+
342+PROTO(lang_input_statement_type *,
343+ lang_add_input_file,(char *name,
344+ lang_input_file_enum_type file_type,
345+ char *target));
346+PROTO(lang_output_section_statement_type *,
347+lang_output_section_statement_lookup,(char *name));
--- /dev/null
+++ b/ld/ldlex.h
@@ -0,0 +1,26 @@
1+/* ldlex.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+PROTO(int, lex_input, (void));
22+PROTO(void, lex_unput, (int));
23+PROTO(int ,yywrap,(void));
24+PROTO(void, parse_args,(int, char **));
25+PROTO(void, parse_line,(char*));
26+
--- /dev/null
+++ b/ld/ldlex.l
@@ -0,0 +1,490 @@
1+%{
2+/* Copyright (C) 1991 Free Software Foundation, Inc.
3+
4+This file is part of GLD, the Gnu Linker.
5+
6+GLD is free software; you can redistribute it and/or modify
7+it under the terms of the GNU General Public License as published by
8+the Free Software Foundation; either version 1, or (at your option)
9+any later version.
10+
11+GLD is distributed in the hope that it will be useful,
12+but WITHOUT ANY WARRANTY; without even the implied warranty of
13+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+GNU General Public License for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GLD; see the file COPYING. If not, write to
18+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19+
20+/*
21+ * $Id$
22+ *
23+ * $Log$
24+ * Revision 1.1 1991/03/21 21:28:50 gumby
25+ * Initial revision
26+ *
27+ * Revision 1.3 1991/03/16 22:27:24 rich
28+ * fish
29+ *
30+ * Revision 1.2 1991/03/15 18:45:55 rich
31+ * foo
32+ *
33+ * Revision 1.1 1991/03/13 00:48:27 chrisb
34+ * Initial revision
35+ *
36+ * Revision 1.6 1991/03/10 09:31:32 rich
37+ * Modified Files:
38+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
39+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
40+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
41+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
42+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
43+ *
44+ * As of this round of changes, ld now builds on all hosts of (Intel960)
45+ * interest and copy passes my copy test on big endian hosts again.
46+ *
47+ * Revision 1.5 1991/03/09 03:25:49 sac
48+ * Can now parse the -Ur flag
49+ *
50+ * Revision 1.4 1991/03/06 02:26:04 sac
51+ * Added support for constructor sections.
52+ * Remove parsing ambiguity.
53+ * Lint
54+ *
55+ * Revision 1.3 1991/02/22 17:15:14 sac
56+ * Added RCS keywords and copyrights
57+ *
58+*/
59+
60+
61+
62+/*SUPPRESS 529*/
63+/*SUPPRESS 26*/
64+/*SUPPRESS 29*/
65+#define LEXDEBUG
66+#include "sysdep.h"
67+#include "bfd.h"
68+
69+#include <ctype.h>
70+#include "ldlex.h"
71+
72+#include "ld.h"
73+#include "ldexp.h"
74+#include "ldgram.tab.h"
75+#include "ldmisc.h"
76+
77+#undef input
78+#undef unput
79+#define input lex_input
80+#define unput lex_unput
81+int debug;
82+extern boolean ldgram_want_filename;
83+extern boolean ldgram_mustbe_filename;
84+extern boolean ldgram_mustbe_symbolname;
85+static char *command_line;
86+
87+extern int fgetc();
88+extern int yyparse();
89+
90+typedef struct {
91+ char *name;
92+int value;
93+} keyword_type;
94+#define RTOKEN(x) { yylval.token = x; return x; }
95+keyword_type keywords[] =
96+{
97+"MEMORY",MEMORY,
98+"ORIGIN",ORIGIN,
99+"BLOCK",BLOCK,
100+"LENGTH",LENGTH,
101+"ALIGN",ALIGN_K,
102+"SUBSECTION_ALIGN",SUBSECTION_ALIGN,
103+"ADDR",ADDR,
104+"ENTRY",ENTRY,
105+"NEXT",NEXT,
106+"MAP",MAP,
107+"SIZEOF",SIZEOF,
108+"TARGET",TARGET_K,
109+"SEARCH_DIR",SEARCH_DIR,
110+"OUTPUT",OUTPUT,
111+"INPUT",INPUT,
112+"DEFINED",DEFINED,
113+"CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS,
114+"SECTIONS",SECTIONS,
115+"FILL",FILL,
116+"STARTUP",STARTUP,
117+"HLL",HLL,
118+"SYSLIB",SYSLIB,
119+"FLOAT",FLOAT,
120+"LONG", LONG,
121+"SHORT", SHORT,
122+"BYTE", BYTE,
123+"NOFLOAT",NOFLOAT,
124+"o",ORIGIN,
125+"org",ORIGIN,
126+"l", LENGTH,
127+"len", LENGTH,
128+0,0};
129+unsigned int lineno;
130+extern boolean hex_mode;
131+FILE *ldlex_input_stack;
132+static unsigned int have_pushback;
133+#define NPUSHBACK 10
134+int pushback[NPUSHBACK];
135+int thischar;
136+extern char *ldfile_input_filename;
137+
138+int
139+lex_input()
140+{
141+ /*
142+ When we know that the next token must be a filename we force the
143+ input routine to return a '#' character, which will cause the special
144+ filname regexp to match the following chars even if they don't look
145+ much like a filename to any sane person.
146+ */
147+ if (ldgram_mustbe_filename) {
148+ ldgram_mustbe_filename = false;
149+ return '#';
150+ }
151+
152+ if (have_pushback > 0)
153+ {
154+ have_pushback --;
155+ return thischar = pushback[have_pushback];
156+ }
157+ if (ldlex_input_stack) {
158+ thischar = fgetc(ldlex_input_stack);
159+
160+ if (thischar == EOF) {
161+ fclose(ldlex_input_stack);
162+ ldlex_input_stack = (FILE *)NULL;
163+ ldfile_input_filename = (char *)NULL;
164+ thischar = lex_input();
165+
166+ }
167+ }
168+ else if (command_line && *command_line) {
169+ thischar = *(command_line++);
170+ }
171+ else thischar = 0;
172+ if(thischar == '\t') thischar = ' ';
173+ return thischar ;
174+}
175+
176+void
177+lex_unput(c)
178+int c;
179+{
180+ if (have_pushback > NPUSHBACK) {
181+ info("%F%P Too many pushbacks\n");
182+ }
183+
184+ pushback[have_pushback] = c;
185+ have_pushback ++;
186+}
187+
188+
189+ int
190+yywrap()
191+ { return 1; }
192+/*VARARGS*/
193+
194+void
195+allprint(x)
196+int x;
197+{
198+fprintf(yyout,"%d",x);
199+}
200+
201+void
202+sprint(x)
203+char *x;
204+{
205+fprintf(yyout,"%s",x);
206+}
207+
208+int thischar;
209+
210+void parse_line(arg)
211+char *arg;
212+{
213+ command_line = arg;
214+ have_pushback = 0;
215+ yyparse();
216+}
217+
218+
219+
220+void
221+parse_args(ac, av)
222+int ac;
223+char **av;
224+{
225+ char *p;
226+ int i;
227+ size_t size = 0;
228+ char *dst;
229+ debug = 1;
230+ for (i= 1; i < ac; i++) {
231+ size += strlen(av[i]) + 2;
232+ }
233+ dst = p = (char *)ldmalloc(size + 2);
234+/* Put a space arount each option */
235+
236+
237+ for (i =1; i < ac; i++) {
238+
239+ unsigned int s = strlen(av[i]);
240+ *dst++ = ' ';
241+ memcpy(dst, av[i], s);
242+ dst[s] = ' ';
243+ dst += s + 1;
244+ }
245+ *dst = 0;
246+ parse_line(p);
247+
248+ free(p);
249+
250+
251+}
252+
253+long number(text, base)
254+char *text;
255+int base;
256+{
257+unsigned long l = 0;
258+ char *p;
259+ for (p = text; *p != 0; p++) {
260+ if (*p == 'K') {
261+ l =l * 1024;
262+ }
263+ else if(*p== 'M') {
264+ l =l * 1024 * 1024;
265+ }
266+ else {
267+ l =l * base;
268+ if (isdigit(*p)) {
269+ l += *p - '0';
270+ }
271+ else if (islower(*p)) {
272+ l += *p - 'a' + 10;
273+ }
274+ else {
275+ l += *p - 'A' + 10;
276+ }
277+ }
278+ }
279+ return l;
280+}
281+%}
282+
283+%a 4000
284+%o 5000
285+FILENAMECHAR [a-zA-Z0-9\/\.\-\_\+]
286+FILENAME {FILENAMECHAR}+
287+
288+
289+WHITE [ \t]+
290+
291+%%
292+"\n" { lineno++; }
293+
294+
295+"\ -defsym" { return OPTION_defsym; }
296+"\ -noinhibit_exec" { return OPTION_noinhibit_exec; }
297+"\ -format" { return OPTION_format; }
298+"\ -n" { return OPTION_n; }
299+"\ -r" { return OPTION_r; }
300+"\ -Ur" { return OPTION_Ur; }
301+"\ -o" { return OPTION_o; }
302+"\ -g" { return OPTION_g; }
303+"\ -e" { return OPTION_e; }
304+"\ -b" { return OPTION_b; }
305+"\ -dc" { return OPTION_dc; }
306+"\ -dp" { return OPTION_dp; }
307+"\ -d" { return OPTION_d; }
308+"\ -v" { return OPTION_v; }
309+"\ -M" { return OPTION_M; }
310+"\ -t" { return OPTION_t; }
311+"\ -X" { return OPTION_X; }
312+"\ -x" { return OPTION_x; }
313+"\ -c" { return OPTION_c; }
314+"\ -s" { return OPTION_s; }
315+"\ -S" { return OPTION_S; }
316+"\ -l"{FILENAME} {
317+ yylval.name = buystring(yytext+3);
318+ return OPTION_l;
319+ }
320+
321+"\ -L"{FILENAME} {
322+ yylval.name = buystring(yytext+3);
323+ return OPTION_L;
324+ }
325+"\ -Ttext" {
326+ yylval.name = ".text";
327+ return OPTION_Texp;
328+ }
329+"\ -Tdata" {
330+ yylval.name = ".data";
331+ return OPTION_Texp;
332+ }
333+"\ -Tbss" {
334+ yylval.name = ".bss";
335+ return OPTION_Texp;
336+ }
337+
338+"\ -T"{FILENAME} {
339+ yylval.name = buystring(yytext+3);
340+ return OPTION_Tfile;
341+ }
342+"\ -T" {
343+ return OPTION_T;
344+ }
345+
346+"\ -A"{FILENAME} {
347+ yylval.name = buystring(yytext+3);
348+ return OPTION_Aarch;
349+ }
350+" " { }
351+"<<=" { RTOKEN(LSHIFTEQ);}
352+">>=" { RTOKEN(RSHIFTEQ);}
353+"||" { RTOKEN(OROR);}
354+"==" { RTOKEN(EQ);}
355+"!=" { RTOKEN(NE);}
356+">=" { RTOKEN(GE);}
357+"<=" { RTOKEN(LE);}
358+"<<" { RTOKEN(LSHIFT);}
359+">>" { RTOKEN(RSHIFT);}
360+"+=" { RTOKEN(PLUSEQ);}
361+"-=" { RTOKEN(MINUSEQ);}
362+"*=" { RTOKEN(MULTEQ);}
363+"/=" { RTOKEN(DIVEQ);}
364+"&=" { RTOKEN(ANDEQ);}
365+"|=" { RTOKEN(OREQ);}
366+
367+"&&" { RTOKEN(ANDAND);}
368+">" { RTOKEN('>');}
369+"," { RTOKEN(',');}
370+"&" { RTOKEN('&');}
371+"|" { RTOKEN('|');}
372+"~" { RTOKEN('~');}
373+"!" { RTOKEN('!');}
374+"?" { RTOKEN('?');}
375+"*" { RTOKEN('*');}
376+"%" { RTOKEN('%');}
377+"<" { RTOKEN('<');}
378+"+" { RTOKEN('+');}
379+">" { RTOKEN('>');}
380+"}" { RTOKEN('}') ; }
381+"{" { RTOKEN('{'); }
382+")" { RTOKEN(')');}
383+"(" { RTOKEN('(');}
384+"]" { RTOKEN(']');}
385+"[" { RTOKEN('[');}
386+":" { RTOKEN(':'); }
387+";" { RTOKEN(';');}
388+"-" { RTOKEN('-');}
389+"=" { RTOKEN('=');}
390+
391+
392+"/*" {
393+ while (1) {
394+ int ch;
395+ ch = input();
396+ while (ch != '*') {
397+ if (ch == '\n') {lineno++; }
398+ ch = input();
399+ }
400+
401+
402+
403+ if (input() == '/') {
404+ break;
405+ }
406+ unput(yytext[yyleng-1]);
407+ }
408+}
409+
410+"\""[^\"]*"\"" {
411+
412+ yylval.name = buystring(yytext+1);
413+ yylval.name[yyleng-2] = 0; /* Fry final quote */
414+ return NAME;
415+}
416+[0][0-7KM]* {
417+
418+ yylval.integer = number(yytext+1, 8);
419+ return INT;
420+}
421+
422+[0-9]+[KM]? {
423+ if (hex_mode == true) {
424+ yylval.integer = number(yytext, 16);
425+ }
426+ else {
427+ yylval.integer = number(yytext, 10);
428+ }
429+ return INT;
430+}
431+
432+0[Xx][0-9a-fA-FKM]+ {
433+
434+ yylval.integer = number(yytext+2,16);
435+ return INT;
436+}
437+
438+"\#"{WHITE}*{FILENAMECHAR}+ {
439+ char *p = yytext+1;
440+ while(*p ==' ' || *p == '\t') p++;
441+ yylval.name = buystring(p);
442+ return NAME;
443+}
444+
445+
446+{FILENAMECHAR} {
447+
448+int ch;
449+ keyword_type *k;
450+ if (yytext[0] == '/' && ldgram_mustbe_symbolname)
451+ { RTOKEN('/');}
452+ ch = input();
453+ while (true) {
454+ if (isalpha(ch) || isdigit(ch) || ch == '.' || ch == '_') {
455+ yytext[yyleng++] = ch;
456+ }
457+ else if (ch == '-' && ldgram_want_filename == true) {
458+ yytext[yyleng++] = ch;
459+ }
460+ else if (ch == '+' && ldgram_want_filename == true) {
461+ yytext[yyleng++] = ch;
462+ }
463+
464+ else if (ch == '/' && ldgram_want_filename == true) {
465+ yytext[yyleng++] = ch;
466+ }
467+
468+ else break;
469+ ch = input();
470+ }
471+
472+ yytext[yyleng] = 0;
473+ unput(ch);
474+
475+ for(k = keywords; k ->name != (char *)NULL; k++) {
476+
477+ if (strcmp(k->name, yytext)==0) {
478+ yylval.token = k->value;
479+ return k->value;
480+ }
481+ }
482+ yylval.name = buystring(yytext);
483+ return NAME;
484+}
485+
486+
487+
488+
489+
490+%%
--- /dev/null
+++ b/ld/ldmain.c
@@ -0,0 +1,806 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ * Written by Steve Chamberlain steve@cygnus.com
21+ *
22+ * $Id$
23+ *
24+ * $Log$
25+ * Revision 1.1 1991/03/21 21:28:52 gumby
26+ * Initial revision
27+ *
28+ * Revision 1.1 1991/03/13 00:48:27 chrisb
29+ * Initial revision
30+ *
31+ * Revision 1.7 1991/03/10 19:15:45 sac
32+ * Fixed a prototype problem
33+ *
34+ * Revision 1.6 1991/03/10 09:31:32 rich
35+ * Modified Files:
36+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
37+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
38+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
39+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
40+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
41+ *
42+ * As of this round of changes, ld now builds on all hosts of (Intel960)
43+ * interest and copy passes my copy test on big endian hosts again.
44+ *
45+ * Revision 1.5 1991/03/09 03:31:02 sac
46+ * After a fatal info message, the output file is deleted.
47+ *
48+ * Revision 1.4 1991/03/06 02:28:31 sac
49+ * Fixed partial linking and error messages.
50+ *
51+ * Revision 1.3 1991/02/22 17:15:02 sac
52+ * Added RCS keywords and copyrights
53+ *
54+ *
55+ */
56+
57+
58+#include "sysdep.h"
59+#include "bfd.h"
60+
61+#include "config.h"
62+#include "ld.h"
63+#include "ldmain.h"
64+#include "ldmisc.h"
65+#include "ldwrite.h"
66+#include "ldgram.h"
67+#include "ldsym.h"
68+#include "ldlang.h"
69+#include "ld-emul.h"
70+#include "ldlex.h"
71+#include "ldfile.h"
72+
73+/* IMPORTS */
74+extern boolean lang_has_input_file;
75+
76+/* EXPORTS */
77+
78+char *default_target;
79+char *output_filename = "a.out";
80+/* Name this program was invoked by. */
81+char *program_name;
82+
83+/* The file that we're creating */
84+bfd *output_bfd;
85+
86+extern boolean option_v;
87+
88+/* The local symbol prefix */
89+char lprefix = 'L';
90+
91+/* Count the number of global symbols multiply defined. */
92+int multiple_def_count;
93+
94+
95+/* Count the number of symbols defined through common declarations.
96+ This count is referenced in symdef_library, linear_library, and
97+ modified by enter_global_ref.
98+
99+ It is incremented when a symbol is created as a common, and
100+ decremented when the common declaration is overridden
101+
102+ Another way of thinking of it is that this is a count of
103+ all ldsym_types with a ->scoms field
104+*/
105+unsigned int commons_pending;
106+
107+
108+/* Count the number of global symbols referenced and not defined.
109+ common symbols are not included in this count.
110+ */
111+
112+unsigned int undefined_global_sym_count;
113+
114+
115+
116+/* Count the number of warning symbols encountered. */
117+int warning_count;
118+
119+/* have we had a load script ? */
120+extern boolean had_script;
121+
122+
123+
124+/* Nonzero means print names of input files as processed. */
125+boolean trace_files;
126+
127+
128+
129+/* 1 => write load map. */
130+boolean write_map;
131+
132+
133+int unix_relocate;
134+
135+
136+
137+
138+
139+
140+
141+
142+/* Force the make_executable to be output, even if there are non-fatal
143+ errors */
144+boolean force_make_executable;
145+
146+
147+/* A count of the total number of local symbols ever seen - by adding
148+ the symbol_count field of each newly read afile.*/
149+
150+
151+unsigned int total_symbols_seen;
152+
153+/* A count of the number of read files - the same as the number of elements
154+ in file_chain
155+ */
156+unsigned int total_files_seen;
157+
158+
159+/* IMPORTS */
160+args_type command_line;
161+ld_config_type config;
162+int
163+main (argc, argv)
164+ char **argv;
165+ int argc;
166+{
167+ char *emulation;
168+ program_name = argv[0];
169+ output_filename = "a.out";
170+
171+ emulation = getenv(EMULATION_ENVIRON);
172+
173+ /* Initialize the data about options. */
174+ strip_symbols = STRIP_NONE;
175+ trace_files = false;
176+ discard_locals = DISCARD_NONE;
177+
178+ write_map = false;
179+ config.relocateable_output = false;
180+ unix_relocate = 0;
181+ command_line.force_common_definition = false;
182+
183+ ldfile_add_arch("");
184+
185+ config.make_executable = true;
186+ force_make_executable = false;
187+
188+
189+ /* Initialize the cumulative counts of symbols. */
190+ undefined_global_sym_count = 0;
191+ warning_count = 0;
192+ multiple_def_count = 0;
193+ commons_pending = 0;
194+
195+ config.magic_demand_paged = true ;
196+ config.make_executable = true;
197+
198+ if (emulation == (char *)NULL) {
199+ emulation= DEFAULT_EMULATION;
200+ }
201+ ldemul_choose_mode(emulation);
202+
203+ default_target = ldemul_choose_target();
204+
205+ lang_init();
206+ ldemul_before_parse();
207+
208+ lang_has_input_file = false;
209+ parse_args(argc, argv);
210+
211+ if (lang_has_input_file == false) {
212+ info("%P%F: No input files\n");
213+ }
214+
215+ ldemul_after_parse();
216+
217+ lang_process();
218+
219+
220+
221+
222+ /* Print error messages for any missing symbols, for any warning
223+ symbols, and possibly multiple definitions */
224+
225+ /* Print a map, if requested. */
226+
227+ if (write_map) {
228+ ldsym_print_symbol_table ();
229+ lang_map(stdout);
230+ }
231+
232+
233+ if (config.relocateable_output) {
234+ output_bfd->flags &= ~( D_PAGED);
235+ output_bfd->flags |= EXEC_P;
236+ ldwrite();
237+ bfd_close(output_bfd);
238+ }
239+ else {
240+ output_bfd->flags |= EXEC_P;
241+
242+ ldwrite();
243+ bfd_close(output_bfd);
244+ if (config.make_executable == false && force_make_executable == false) {
245+ unlink(output_filename);
246+ }
247+ return (!config.make_executable);
248+ }
249+
250+ return(0);
251+} /* main() */
252+
253+
254+void
255+Q_read_entry_symbols (desc, entry)
256+ bfd *desc;
257+ struct lang_input_statement_struct *entry;
258+{
259+ if (entry->asymbols == (asymbol **)NULL) {
260+ size_t table_size = get_symtab_upper_bound(desc);
261+ entry->asymbols = (asymbol **)ldmalloc(table_size);
262+
263+ entry->symbol_count = bfd_canonicalize_symtab(desc, entry->asymbols) ;
264+ }
265+}
266+
267+
268+/*
269+ * turn this item into a reference
270+ */
271+static void
272+refize(sp, nlist_p)
273+ldsym_type *sp;
274+asymbol **nlist_p;
275+{
276+ asymbol *sym = *nlist_p;
277+ sym->value = 0;
278+ sym->flags = BSF_UNDEFINED;
279+ sym->section = (asection *)NULL;
280+ sym->udata =(void *)( sp->srefs_chain);
281+ sp->srefs_chain = nlist_p;
282+}
283+/*
284+This function is called for each name which is seen which has a global
285+scope. It enters the name into the global symbol table in the correct
286+symbol on the correct chain. Remember that each ldsym_type has three
287+chains attatched, one of all definitions of a symbol, one of all
288+references of a symbol and one of all common definitions of a symbol.
289+
290+When the function is over, the supplied is left connected to the bfd
291+to which is was born, with its udata field pointing to the next member
292+on the chain in which it has been inserted.
293+
294+A certain amount of jigery pokery is necessary since commons come
295+along and upset things, we only keep one item in the common chain; the
296+one with the biggest size seen sofar. When another common comes along
297+it either bumps the previous definition into the ref chain, since it
298+is bigger, or gets turned into a ref on the spot since the one on the
299+common chain is already bigger. If a real definition comes along then
300+the common gets bumped off anyway.
301+
302+Whilst all this is going on we keep a count of the number of multiple
303+definitions seen, undefined global symbols and pending commons.
304+*/
305+
306+
307+void
308+Q_enter_global_ref (nlist_p)
309+ asymbol **nlist_p;
310+
311+{
312+ asymbol *sym = *nlist_p;
313+ char *name = sym->name;
314+ ldsym_type *sp = ldsym_get (name);
315+
316+ flagword this_symbol_flags = sym->flags;
317+
318+
319+ ASSERT(sym->udata == 0);
320+
321+ /* Just place onto correct chain */
322+ if (flag_is_common(this_symbol_flags)) {
323+ /* If we have a definition of this symbol already then
324+ * this common turns into a reference. Also we only
325+ * ever point to the largest common, so if we
326+ * have a common, but it's bigger that the new symbol
327+ * the turn this into a reference too.
328+ */
329+ if (sp->sdefs_chain)
330+ {
331+ /* This is a common symbol, but we already have a definition
332+ for it, so just link it into the ref chain as if
333+ it were a reference
334+ */
335+ refize(sp, nlist_p);
336+ }
337+ else if (sp->scoms_chain) {
338+ /* If we have a previous common, keep only the biggest */
339+ if ( (*(sp->scoms_chain))->value > sym->value) {
340+ /* other common is bigger, throw this one away */
341+ refize(sp, nlist_p);
342+ }
343+ else if (sp->scoms_chain != nlist_p) {
344+ /* other common is smaller, throw that away */
345+ refize(sp, sp->scoms_chain);
346+ sp->scoms_chain = nlist_p;
347+ }
348+ }
349+ else {
350+ /* This is the first time we've seen a common, so
351+ * remember it - if it was undefined before, we know it's defined now
352+ */
353+ if (sp->srefs_chain)
354+ undefined_global_sym_count--;
355+
356+ commons_pending++;
357+ sp->scoms_chain = nlist_p;
358+ }
359+ }
360+
361+ else if (flag_is_defined(this_symbol_flags)) {
362+ /* This is the definition of a symbol, add to def chain */
363+ if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) {
364+ /* Multiple definition */
365+ asymbol *sy = *(sp->sdefs_chain);
366+ lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
367+ lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
368+ asymbol ** stat1_symbols = stat1 ? stat1->asymbols: 0;
369+ asymbol ** stat_symbols = stat ? stat->asymbols:0;
370+
371+ multiple_def_count++;
372+ info("%C: multiple definition of `%T'\n",
373+ sym->the_bfd,
374+ sym->section,
375+ stat1_symbols,
376+ sym->value,
377+ sym);
378+
379+ info("%C: first seen here\n",
380+ sy->the_bfd,
381+ sy->section,
382+ stat_symbols,
383+ sy->value);
384+ }
385+ else {
386+ sym->udata =(void *)( sp->sdefs_chain);
387+ sp->sdefs_chain = nlist_p;
388+ }
389+ /* A definition overrides a common symbol */
390+ if (sp->scoms_chain) {
391+ refize(sp, sp->scoms_chain);
392+ sp->scoms_chain = 0;
393+ commons_pending--;
394+ }
395+ else if (sp->srefs_chain) {
396+ /* If previously was undefined, then remember as defined */
397+ undefined_global_sym_count--;
398+ }
399+ }
400+ else {
401+ if (sp->scoms_chain == (asymbol **)NULL
402+ && sp->srefs_chain == (asymbol **)NULL
403+ && sp->sdefs_chain == (asymbol **)NULL) {
404+ /* And it's the first time we've seen it */
405+ undefined_global_sym_count++;
406+
407+ }
408+
409+ refize(sp, nlist_p);
410+ }
411+
412+ ASSERT(sp->sdefs_chain == 0 || sp->scoms_chain == 0);
413+ ASSERT(sp->scoms_chain ==0 || (*(sp->scoms_chain))->udata == 0);
414+
415+
416+}
417+
418+static void
419+Q_enter_file_symbols (entry)
420+lang_input_statement_type *entry;
421+{
422+ asymbol **q ;
423+ entry->common_section =
424+ bfd_make_section(entry->the_bfd, "COMMON");
425+
426+ ldlang_add_file(entry);
427+
428+
429+ if (trace_files || option_v) {
430+ info("%I\n", entry);
431+ }
432+
433+ total_symbols_seen += entry->symbol_count;
434+ total_files_seen ++;
435+ for (q = entry->asymbols; *q; q++)
436+ {
437+ asymbol *p = *q;
438+
439+ if (flag_is_undefined_or_global_or_common(p->flags))
440+ {
441+
442+ Q_enter_global_ref(q);
443+ }
444+ ASSERT(p->flags != 0);
445+ }
446+}
447+
448+
449+
450+/* Searching libraries */
451+
452+struct lang_input_statement_struct *decode_library_subfile ();
453+void linear_library (), symdef_library ();
454+
455+/* Search the library ENTRY, already open on descriptor DESC.
456+ This means deciding which library members to load,
457+ making a chain of `struct lang_input_statement_struct' for those members,
458+ and entering their global symbols in the hash table. */
459+
460+void
461+search_library (entry)
462+ struct lang_input_statement_struct *entry;
463+{
464+
465+ /* No need to load a library if no undefined symbols */
466+ if (!undefined_global_sym_count) return;
467+
468+ if (bfd_has_map(entry->the_bfd))
469+ symdef_library (entry);
470+ else
471+ linear_library (entry);
472+
473+}
474+
475+
476+void
477+Q_read_file_symbols (entry)
478+struct lang_input_statement_struct *entry;
479+{
480+ if (entry->asymbols == (asymbol **)NULL
481+ &&entry->real == true
482+ && entry->filename != (char *)NULL)
483+ {
484+ ldfile_open_file (entry);
485+
486+ if (bfd_check_format(entry->the_bfd, bfd_object))
487+ {
488+ entry->the_bfd->usrdata = (void*)entry;
489+
490+
491+ Q_read_entry_symbols (entry->the_bfd, entry);
492+ Q_enter_file_symbols (entry);
493+ }
494+ else if (bfd_check_format(entry->the_bfd, bfd_archive))
495+ {
496+ entry->the_bfd->usrdata = (void *)entry;
497+
498+ entry->subfiles = (lang_input_statement_type *)NULL;
499+ search_library (entry);
500+ }
501+ else
502+ {
503+ info("%F%I: malformed input file (not rel or archive) \n", entry);
504+ }
505+ }
506+
507+}
508+
509+
510+/* Construct and return a lang_input_statement_struct for a library member.
511+ The library's lang_input_statement_struct is library_entry,
512+ and the library is open on DESC.
513+ SUBFILE_OFFSET is the byte index in the library of this member's header.
514+ We store the length of the member into *LENGTH_LOC. */
515+
516+lang_input_statement_type *
517+decode_library_subfile (library_entry, subfile_offset)
518+ struct lang_input_statement_struct *library_entry;
519+ bfd *subfile_offset;
520+{
521+ register struct lang_input_statement_struct *subentry;
522+ subentry = (struct lang_input_statement_struct *) ldmalloc (sizeof (struct lang_input_statement_struct));
523+ subentry->filename = subfile_offset -> filename;
524+ subentry->local_sym_name = subfile_offset->filename;
525+ subentry->asymbols = 0;
526+ subentry->the_bfd = subfile_offset;
527+ subentry->subfiles = 0;
528+ subentry->next = 0;
529+ subentry->superfile = library_entry;
530+ subentry->is_archive = false;
531+ subentry->header_read_flag = false;
532+ subentry->just_syms_flag = false;
533+ subentry->loaded = false;
534+ subentry->chain = 0;
535+
536+ return subentry;
537+}
538+
539+boolean subfile_wanted_p ();
540+void
541+clear_syms(entry, offset)
542+struct lang_input_statement_struct *entry;
543+file_ptr offset;
544+{
545+ carsym *car;
546+ unsigned long indx = bfd_get_next_mapent(entry->the_bfd,
547+ BFD_NO_MORE_SYMBOLS,
548+ &car);
549+ while (indx != BFD_NO_MORE_SYMBOLS) {
550+ if (car->file_offset == offset) {
551+ car->name = 0;
552+ }
553+ indx = bfd_get_next_mapent(entry->the_bfd, indx, &car);
554+ }
555+
556+}
557+
558+/* Search a library that has a map
559+ */
560+void
561+symdef_library (entry)
562+ struct lang_input_statement_struct *entry;
563+
564+{
565+ register struct lang_input_statement_struct *prev = 0;
566+
567+ boolean not_finished = true;
568+
569+
570+ while (not_finished == true)
571+ {
572+ carsym *exported_library_name;
573+ bfd *prev_archive_member_bfd = 0;
574+
575+ int idx = bfd_get_next_mapent(entry->the_bfd,
576+ BFD_NO_MORE_SYMBOLS,
577+ &exported_library_name);
578+
579+ not_finished = false;
580+
581+ while (idx != BFD_NO_MORE_SYMBOLS && undefined_global_sym_count)
582+ {
583+
584+ if (exported_library_name->name)
585+ {
586+
587+ ldsym_type *sp = ldsym_get_soft (exported_library_name->name);
588+
589+ /* If we find a symbol that appears to be needed, think carefully
590+ about the archive member that the symbol is in. */
591+ /* So - if it exists, and is referenced somewhere and is
592+ undefined or */
593+ if (sp && sp->srefs_chain && !sp->sdefs_chain)
594+ {
595+ bfd *archive_member_bfd = bfd_get_elt_at_index(entry->the_bfd, idx);
596+ struct lang_input_statement_struct *archive_member_lang_input_statement_struct;
597+
598+ if (archive_member_bfd && bfd_check_format(archive_member_bfd, bfd_object))
599+ {
600+
601+ /* Don't think carefully about any archive member
602+ more than once in a given pass. */
603+ if (prev_archive_member_bfd != archive_member_bfd)
604+ {
605+
606+ prev_archive_member_bfd = archive_member_bfd;
607+
608+ /* Read the symbol table of the archive member. */
609+
610+ if (archive_member_bfd->usrdata != (void *)NULL) {
611+
612+ archive_member_lang_input_statement_struct =(lang_input_statement_type *) archive_member_bfd->usrdata;
613+ }
614+ else {
615+
616+ archive_member_lang_input_statement_struct =
617+ decode_library_subfile (entry, archive_member_bfd);
618+ archive_member_bfd->usrdata = (void *) archive_member_lang_input_statement_struct;
619+
620+ }
621+
622+ if (archive_member_lang_input_statement_struct == 0) {
623+ info ("%F%I contains invalid archive member %s\n",
624+ entry,
625+ sp->name);
626+ }
627+
628+ if (archive_member_lang_input_statement_struct->loaded == false)
629+ {
630+
631+ Q_read_entry_symbols (archive_member_bfd, archive_member_lang_input_statement_struct);
632+ /* Now scan the symbol table and decide whether to load. */
633+
634+
635+ if (subfile_wanted_p (archive_member_lang_input_statement_struct) == true)
636+
637+ {
638+ /* This member is needed; load it.
639+ Since we are loading something on this pass,
640+ we must make another pass through the symdef data. */
641+
642+ not_finished = true;
643+
644+ Q_enter_file_symbols (archive_member_lang_input_statement_struct);
645+
646+ if (prev)
647+ prev->chain = archive_member_lang_input_statement_struct;
648+ else
649+ entry->subfiles = archive_member_lang_input_statement_struct;
650+
651+
652+ prev = archive_member_lang_input_statement_struct;
653+
654+
655+ /* Clear out this member's symbols from the symdef data
656+ so that following passes won't waste time on them. */
657+ clear_syms(entry, exported_library_name->file_offset);
658+ archive_member_lang_input_statement_struct->loaded = true;
659+ }
660+ }
661+ }
662+ }
663+ }
664+ }
665+ idx = bfd_get_next_mapent(entry->the_bfd, idx, &exported_library_name);
666+ }
667+ }
668+}
669+
670+void
671+linear_library (entry)
672+struct lang_input_statement_struct *entry;
673+{
674+ boolean more_to_do = true;
675+ register struct lang_input_statement_struct *prev = 0;
676+
677+ while (more_to_do) {
678+
679+ bfd * archive = bfd_openr_next_archived_file(entry->the_bfd,0);
680+
681+ more_to_do = false;
682+ while (archive) {
683+ if (bfd_check_format(archive, bfd_object))
684+ {
685+ register struct lang_input_statement_struct *subentry;
686+
687+ subentry = decode_library_subfile (entry,
688+ archive);
689+
690+ archive->usrdata = (void *) subentry;
691+ if (!subentry) return;
692+ if (subentry->loaded == false) {
693+ Q_read_entry_symbols (archive, subentry);
694+
695+ if (subfile_wanted_p (subentry) == true)
696+ {
697+ Q_enter_file_symbols (subentry);
698+
699+ if (prev)
700+ prev->chain = subentry;
701+ else
702+ entry->subfiles = subentry;
703+ prev = subentry;
704+
705+ more_to_do = true;
706+ subentry->loaded = true;
707+ }
708+ }
709+ }
710+ archive = bfd_openr_next_archived_file(entry->the_bfd,archive);
711+
712+ }
713+
714+ }
715+}
716+
717+ /* ENTRY is an entry for a library member.
718+ Its symbols have been read into core, but not entered.
719+ Return nonzero if we ought to load this member. */
720+
721+boolean
722+subfile_wanted_p (entry)
723+struct lang_input_statement_struct *entry;
724+{
725+ asymbol **q;
726+
727+ for (q = entry->asymbols; *q; q++)
728+ {
729+ asymbol *p = *q;
730+
731+ /* If the symbol has an interesting definition, we could
732+ potentially want it. */
733+
734+ if (p->flags & BSF_FORT_COMM
735+ || p->flags & BSF_GLOBAL)
736+ {
737+ register ldsym_type *sp = ldsym_get_soft (p->name);
738+
739+
740+ /* If this symbol has not been hashed,
741+ we can't be looking for it. */
742+ if (sp != (ldsym_type *)NULL
743+ && sp->sdefs_chain == (asymbol **)NULL) {
744+ if (sp->srefs_chain != (asymbol **)NULL
745+ || sp->scoms_chain != (asymbol **)NULL)
746+ {
747+ /* This is a symbol we are looking for. It is either
748+ not yet defined or common. */
749+
750+ if (flag_is_common(p->flags))
751+ {
752+ /* This libary member has something to
753+ say about this element. We should
754+ remember if its a new size */
755+ /* Move something from the ref list to the com list */
756+ if(sp->scoms_chain) {
757+ /* Already a common symbol, maybe update it */
758+ if (p->value > (*(sp->scoms_chain))->value) {
759+ (*(sp->scoms_chain))->value = p->value;
760+ }
761+ }
762+ else {
763+ /* Take a value from the ref chain
764+ Here we are moving a symbol from the owning bfd
765+ to another bfd. We must set up the
766+ common_section portion of the bfd thing */
767+
768+
769+
770+ sp->scoms_chain = sp->srefs_chain;
771+ sp->srefs_chain =
772+ (asymbol **)((*(sp->srefs_chain))->udata);
773+ (*(sp->scoms_chain))->udata = (void*)NULL;
774+
775+ (*( sp->scoms_chain))->flags = BSF_FORT_COMM;
776+ commons_pending++;
777+ undefined_global_sym_count--;
778+ } {
779+ asymbol *com = *(sp->scoms_chain);
780+ if (((lang_input_statement_type *)
781+ (com->the_bfd->usrdata))->common_section ==
782+ (asection *)NULL) {
783+ ((lang_input_statement_type *)
784+ (com->the_bfd->usrdata))->common_section =
785+ bfd_make_section(com->the_bfd, "COMMON");
786+ }
787+ }
788+ ASSERT(p->udata == 0);
789+ }
790+
791+ else {
792+ if (write_map)
793+ {
794+ info("%I needed due to %s\n",entry, sp->name);
795+ }
796+ return true;
797+ }
798+ }
799+ }
800+ }
801+ }
802+
803+ return false;
804+}
805+
806+
--- /dev/null
+++ b/ld/ldmain.h
@@ -0,0 +1,23 @@
1+/* ldmain.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+PROTO(void, Q_enter_global_ref,(asymbol **));
22+PROTO(void, Q_read_file_symbols,(struct lang_input_statement_struct *));
23+
--- /dev/null
+++ b/ld/ldmisc.c
@@ -0,0 +1,303 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ * $Id$
21+ *
22+ * $Log$
23+ * Revision 1.1 1991/03/21 21:28:55 gumby
24+ * Initial revision
25+ *
26+ * Revision 1.2 1991/03/15 18:45:55 rich
27+ * foo
28+ *
29+ * Revision 1.1 1991/03/13 00:48:30 chrisb
30+ * Initial revision
31+ *
32+ * Revision 1.7 1991/03/10 09:31:34 rich
33+ * Modified Files:
34+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
35+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
36+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
37+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
38+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
39+ *
40+ * As of this round of changes, ld now builds on all hosts of (Intel960)
41+ * interest and copy passes my copy test on big endian hosts again.
42+ *
43+ * Revision 1.6 1991/03/09 03:31:01 sac
44+ * After a fatal info message, the output file is deleted.
45+ *
46+ * Revision 1.5 1991/03/06 21:59:54 sac
47+ * Made %C print function name if available
48+ *
49+ * Revision 1.4 1991/03/06 02:27:45 sac
50+ * Added support for linenumber printing via %C
51+ *
52+ * Revision 1.3 1991/02/22 17:15:03 sac
53+ * Added RCS keywords and copyrights
54+ *
55+ */
56+
57+/*
58+ ldmisc.c
59+
60+*/
61+
62+#include "sysdep.h"
63+#include <varargs.h>
64+#include "bfd.h"
65+
66+#include "ld.h"
67+#include "ldmisc.h"
68+#include "ldlang.h"
69+
70+/* IMPORTS */
71+
72+extern char *program_name;
73+
74+extern FILE *ldlex_input_stack;
75+extern char *ldfile_input_filename;
76+extern ld_config_type config;
77+
78+void
79+yyerror(arg)
80+char *arg;
81+{
82+ info("%P%F: %S %s\n",arg);
83+}
84+
85+extern int errno;
86+extern int sys_nerr;
87+extern char *sys_errlist[];
88+
89+/*
90+ %F error is fatal
91+ %P print progam name
92+ %S print script file and linenumber
93+ %E current bfd error or errno
94+ %I filename from a lang_input_statement_type
95+ %B filename from a bfd
96+ %T symbol table entry
97+ %X no object output, fail return
98+ %V hex bfd_vma
99+ %C Clever filename:linenumber
100+ %
101+*/
102+void info(va_alist)
103+va_dcl
104+{
105+ char *fmt;
106+ boolean fatal = false;
107+ va_list arg;
108+ va_start(arg);
109+ fmt = va_arg(arg, char *);
110+ while (*fmt) {
111+ while (*fmt != '%' && *fmt != '\0') {
112+ fputc(*fmt, stderr);
113+ fmt++;
114+ }
115+ if (*fmt == '%') {
116+ fmt ++;
117+ switch (*fmt++) {
118+ case 'X':
119+ config.make_executable = false;
120+ break;
121+ case 'V':
122+ fprintf(stderr,"%08lx", va_arg(arg, bfd_vma));
123+ break;
124+ case 'T':
125+ {
126+ asymbol *symbol = va_arg(arg, asymbol *);
127+ if (symbol) {
128+ asection *section = symbol->section;
129+ if ((symbol->flags & BSF_UNDEFINED) == 0) {
130+ char *section_name = section == (asection *)NULL ?
131+ "absolute" : section->name;
132+ fprintf(stderr,"%s (%s)", symbol->name, section_name);
133+ }
134+ else {
135+ fprintf(stderr,"%s", symbol->name);
136+ }
137+ }
138+ else {
139+ fprintf(stderr,"no symbol");
140+ }
141+ }
142+ break;
143+ case 'B':
144+ {
145+ bfd *abfd = va_arg(arg, bfd *);
146+ if (abfd->my_archive) {
147+ fprintf(stderr,"%s(%s)", abfd->my_archive->filename,
148+ abfd->filename);
149+ }
150+ else {
151+ fprintf(stderr,"%s", abfd->filename);
152+
153+ }
154+ }
155+ break;
156+ case 'F':
157+ fatal = true;
158+ break;
159+ case 'P':
160+ fprintf(stderr,"%s", program_name);
161+ break;
162+ case 'E':
163+ /* Replace with the most recent errno explanation */
164+
165+
166+ fprintf(stderr, bfd_errmsg(bfd_error));
167+
168+
169+ break;
170+ case 'I':
171+ {
172+ lang_input_statement_type *i =
173+ va_arg(arg,lang_input_statement_type *);
174+
175+ fprintf(stderr,"%s", i->local_sym_name);
176+ }
177+ break;
178+ case 'S':
179+ /* Print source script file and line number */
180+
181+ if (ldlex_input_stack) {
182+ extern unsigned int lineno;
183+ if (ldfile_input_filename == (char *)NULL) {
184+ fprintf(stderr,"command line");
185+ }
186+ else {
187+ fprintf(stderr,"%s:%u", ldfile_input_filename, lineno + 1);
188+ }
189+ }
190+ else {
191+ fprintf(stderr,"command line ");
192+ }
193+ break;
194+ case 'C':
195+ {
196+ char *filename;
197+ char *functionname;
198+ unsigned int linenumber;
199+ bfd *abfd = va_arg(arg, bfd *);
200+ asection *section = va_arg(arg, asection *);
201+ asymbol **symbols = va_arg(arg, asymbol **);
202+ bfd_vma offset = va_arg(arg, bfd_vma);
203+
204+ if (bfd_find_nearest_line(abfd,
205+ section,
206+ symbols,
207+ offset,
208+ &filename,
209+ &functionname,
210+ &linenumber))
211+ {
212+ if (filename == (char *)NULL)
213+ filename = abfd->filename;
214+ if (functionname != (char *)NULL)
215+ fprintf(stderr,"%s:%u: (%s)", filename, linenumber, functionname);
216+ else if (linenumber != 0)
217+ fprintf(stderr,"%s:%u", filename, linenumber);
218+ else
219+ fprintf(stderr,"%s", filename);
220+
221+ }
222+ else {
223+ fprintf(stderr,"%s", abfd->filename);
224+ }
225+ }
226+ break;
227+
228+ case 's':
229+ fprintf(stderr,"%s", va_arg(arg, char *));
230+ break;
231+ case 'd':
232+ fprintf(stderr,"%d", va_arg(arg, int));
233+ break;
234+ default:
235+ fprintf(stderr,"%s", va_arg(arg, char *));
236+ break;
237+ }
238+ }
239+ }
240+ if (fatal == true) {
241+ extern char *output_filename;
242+ if (output_filename)
243+ unlink(output_filename);
244+ exit(1);
245+ }
246+ va_end(arg);
247+}
248+
249+
250+void
251+info_assert(file, line)
252+char *file;
253+unsigned int line;
254+{
255+ info("%F%P internal error %s %d\n", file,line);
256+}
257+
258+/* Return a newly-allocated string
259+ whose contents concatenate those of S1, S2, S3. */
260+
261+char *
262+concat (s1, s2, s3)
263+ char *s1, *s2, *s3;
264+{
265+ size_t len1 = strlen (s1);
266+ size_t len2 = strlen (s2);
267+ size_t len3 = strlen (s3);
268+ char *result = ldmalloc (len1 + len2 + len3 + 1);
269+
270+ if (len1 != 0)
271+ memcpy(result, s1, len1);
272+ if (len2 != 0)
273+ memcpy(result+len1, s2, len2);
274+ if (len3 != 0)
275+ memcpy(result+len1+len2, s2, len3);
276+ *(result + len1 + len2 + len3) = 0;
277+
278+ return result;
279+}
280+
281+
282+
283+char *ldmalloc (size)
284+size_t size;
285+{
286+ char * result = malloc (size);
287+
288+ if (result == (char *)NULL && size != 0)
289+ info("%F%P virtual memory exhausted\n");
290+
291+ return result;
292+}
293+
294+
295+
296+char *buystring(x)
297+char *x;
298+{
299+ size_t l = strlen(x)+1;
300+ char *r = ldmalloc(l);
301+ memcpy(r, x,l);
302+ return r;
303+}
--- /dev/null
+++ b/ld/ldmisc.h
@@ -0,0 +1,34 @@
1+/* ldmisc.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+
23+/* VARARGS*/
24+PROTO(void,info,());
25+PROTO(void,info_assert,(char *, unsigned int));
26+PROTO(void,yyerror,(char *));
27+PROTO(char *,concat,(char *, char *, char *));
28+PROTO(char *, ldmalloc,(size_t));
29+PROTO(char *,buystring,(char *));
30+#define ASSERT(x) \
31+{ if (!(x)) info_assert(__FILE__,__LINE__); }
32+
33+#define FAIL() \
34+{ info_assert(__FILE__,__LINE__); }
--- /dev/null
+++ b/ld/ldsym.c
@@ -0,0 +1,452 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ * $Id$
21+ *
22+ * $Log$
23+ * Revision 1.1 1991/03/21 21:28:58 gumby
24+ * Initial revision
25+ *
26+ * Revision 1.1 1991/03/13 00:48:32 chrisb
27+ * Initial revision
28+ *
29+ * Revision 1.4 1991/03/10 09:31:36 rich
30+ * Modified Files:
31+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
32+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
33+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
34+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
35+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
36+ *
37+ * As of this round of changes, ld now builds on all hosts of (Intel960)
38+ * interest and copy passes my copy test on big endian hosts again.
39+ *
40+ * Revision 1.3 1991/03/06 02:28:56 sac
41+ * Cleaned up
42+ *
43+ * Revision 1.2 1991/02/22 17:15:06 sac
44+ * Added RCS keywords and copyrights
45+ *
46+*/
47+
48+/*
49+ Written by Steve Chamberlain steve@cygnus.com
50+
51+ All symbol handling for the linker
52+ */
53+
54+
55+#include "sysdep.h"
56+#include "bfd.h"
57+
58+#include "ld.h"
59+#include "ldsym.h"
60+#include "ldmisc.h"
61+#include "ldlang.h"
62+/* IMPORT */
63+
64+extern bfd *output_bfd;
65+/* Head and tail of global symbol table chronological list */
66+
67+ldsym_type *symbol_head = (ldsym_type *)NULL;
68+ldsym_type **symbol_tail_ptr = &symbol_head;
69+
70+/*
71+ incremented for each symbol in the ldsym_type table
72+ no matter what flavour it is
73+*/
74+unsigned int global_symbol_count;
75+
76+/* IMPORTS */
77+
78+extern boolean option_longmap ;
79+
80+/* LOCALS */
81+#define TABSIZE 1009
82+static ldsym_type *global_symbol_hash_table[TABSIZE];
83+
84+/* Compute the hash code for symbol name KEY. */
85+
86+int
87+hash_string (key)
88+ char *key;
89+{
90+ register char *cp;
91+ register int k;
92+
93+ cp = key;
94+ k = 0;
95+ while (*cp)
96+ k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
97+
98+ return k;
99+}
100+
101+/* Get the symbol table entry for the global symbol named KEY.
102+ Create one if there is none. */
103+ldsym_type *
104+ldsym_get (key)
105+ char *key;
106+{
107+ register int hashval;
108+ register ldsym_type *bp;
109+
110+ /* Determine the proper bucket. */
111+
112+ hashval = hash_string (key) % TABSIZE;
113+
114+ /* Search the bucket. */
115+
116+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
117+ if (! strcmp (key, bp->name))
118+ return bp;
119+
120+ /* Nothing was found; create a new symbol table entry. */
121+
122+ bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
123+ bp->srefs_chain = (asymbol **)NULL;
124+ bp->sdefs_chain = (asymbol **)NULL;
125+ bp->scoms_chain = (asymbol **)NULL;
126+ bp->name = (char *) ldmalloc (strlen (key) + 1);
127+ strcpy (bp->name, key);
128+
129+
130+
131+
132+ /* Add the entry to the bucket. */
133+
134+ bp->link = global_symbol_hash_table[hashval];
135+ global_symbol_hash_table[hashval] = bp;
136+
137+ /* Keep the chronological list up to date too */
138+ *symbol_tail_ptr = bp;
139+ symbol_tail_ptr = &bp->next;
140+ bp->next = 0;
141+ global_symbol_count++;
142+
143+ return bp;
144+}
145+
146+/* Like `ldsym_get' but return 0 if the symbol is not already known. */
147+
148+ldsym_type *
149+ldsym_get_soft (key)
150+ char *key;
151+{
152+ register int hashval;
153+ register ldsym_type *bp;
154+
155+ /* Determine which bucket. */
156+
157+ hashval = hash_string (key) % TABSIZE;
158+
159+ /* Search the bucket. */
160+
161+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
162+ if (! strcmp (key, bp->name))
163+ return bp;
164+
165+ return 0;
166+}
167+
168+
169+
170+
171+
172+static void
173+list_file_locals (entry)
174+lang_input_statement_type *entry;
175+{
176+ asymbol **q;
177+ fprintf (stderr, "\nLocal symbols of ");
178+ info("%I", entry);
179+ fprintf (stderr, ":\n\n");
180+ if (entry->asymbols) {
181+ for (q = entry->asymbols; *q; q++)
182+ {
183+ asymbol *p = *q;
184+ /* If this is a definition,
185+ update it if necessary by this file's start address. */
186+ if (p->flags & BSF_LOCAL)
187+ info(" %V %s\n",p->value, p->name);
188+ }
189+ }
190+}
191+
192+
193+static void
194+print_file_stuff(f)
195+lang_input_statement_type *f;
196+{
197+ fprintf (stderr, " %s", f->filename);
198+ fprintf (stderr, " ");
199+ if (f->just_syms_flag)
200+ {
201+ fprintf (stderr, " symbols only\n");
202+ }
203+ else
204+ {
205+ asection *s;
206+ if (option_longmap) {
207+ for (s = f->the_bfd->sections;
208+ s != (asection *)NULL;
209+ s = s->next) {
210+ fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
211+ s->output_offset,
212+ (unsigned)s->size, s->alignment_power, s->name);
213+ }
214+ }
215+ else {
216+ for (s = f->the_bfd->sections;
217+ s != (asection *)NULL;
218+ s = s->next) {
219+ fprintf (stderr, "%s %lx(%x) ",
220+ s->name,
221+ s->output_offset,
222+ (unsigned) s->size);
223+ }
224+ fprintf (stderr, "hex \n");
225+ }
226+ }
227+}
228+
229+void
230+ldsym_print_symbol_table ()
231+{
232+ fprintf (stderr, "\nFiles:\n\n");
233+
234+ lang_for_each_file(print_file_stuff);
235+
236+ fprintf (stderr, "\nGlobal symbols:\n\n");
237+ {
238+ register ldsym_type *sp;
239+
240+ for (sp = symbol_head; sp; sp = sp->next)
241+ {
242+ if (sp->sdefs_chain)
243+ {
244+ asymbol *defsym = *(sp->sdefs_chain);
245+ asection *defsec = bfd_get_section(defsym);
246+ fprintf(stderr,"%08lx ",defsym->value);
247+ if (defsec)
248+ {
249+ fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
250+ fprintf(stderr,
251+ "%7s",
252+ bfd_section_name(output_bfd,
253+ defsec));
254+
255+ }
256+ else
257+ {
258+ fprintf(stderr," .......");
259+ }
260+
261+ }
262+ else {
263+ fprintf(stderr,"undefined");
264+ }
265+
266+
267+ if (sp->scoms_chain) {
268+ fprintf(stderr, " common size %5lu %s",
269+ (*(sp->scoms_chain))->value, sp->name);
270+ }
271+ if (sp->sdefs_chain) {
272+ fprintf(stderr, " symbol def %08lx %s",
273+ (*(sp->sdefs_chain))->value,
274+ sp->name);
275+ }
276+ else {
277+ fprintf(stderr, " undefined %s",
278+ sp->name);
279+ }
280+ fprintf(stderr, "\n");
281+
282+ }
283+ }
284+ lang_for_each_file(list_file_locals);
285+}
286+
287+extern lang_output_section_statement_type *create_object_symbols;
288+extern char lprefix;
289+static asymbol **
290+write_file_locals(output_buffer)
291+asymbol **output_buffer;
292+{
293+LANG_FOR_EACH_INPUT_STATEMENT(entry)
294+ {
295+ /* Run trough the symbols and work out what to do with them */
296+ unsigned int i;
297+
298+ /* Add one for the filename symbol if needed */
299+ if (create_object_symbols
300+ != (lang_output_section_statement_type *)NULL) {
301+ asection *s;
302+ for (s = entry->the_bfd->sections;
303+ s != (asection *)NULL;
304+ s = s->next) {
305+ if (s->output_section == create_object_symbols->bfd_section) {
306+ /* Add symbol to this section */
307+ asymbol * newsym =
308+ (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
309+ newsym->name = entry->local_sym_name;
310+ /* The symbol belongs to the output file's text section */
311+
312+ /* The value is the start of this section in the output file*/
313+ newsym->value = 0;
314+ newsym->flags = BSF_LOCAL;
315+ newsym->section = s;
316+ *output_buffer++ = newsym;
317+ break;
318+ }
319+ }
320+ }
321+ for (i = 0; i < entry->symbol_count; i++)
322+ {
323+ asymbol *p = entry->asymbols[i];
324+
325+ if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
326+ {
327+ /* We are only interested in outputting
328+ globals at this stage in special circumstances */
329+ if (p->the_bfd == entry->the_bfd
330+ && flag_is_not_at_end(p->flags)) {
331+ /* And this is one of them */
332+ *(output_buffer++) = p;
333+ p->flags |= BSF_KEEP;
334+ }
335+ }
336+ else {
337+ if (flag_is_ordinary_local(p->flags))
338+ {
339+ if (discard_locals == DISCARD_ALL)
340+ { }
341+ else if (discard_locals == DISCARD_L &&
342+ (p->name[0] == lprefix))
343+ { }
344+ else if (p->flags == BSF_WARNING)
345+ { }
346+ else
347+ { *output_buffer++ = p; }
348+ }
349+ else if (flag_is_debugger(p->flags))
350+ {
351+ /* Only keep the debugger symbols if no stripping required */
352+ if (strip_symbols == STRIP_NONE) {
353+ *output_buffer++ = p;
354+ }
355+ }
356+ else if (flag_is_undefined(p->flags))
357+ { /* This must be global */
358+ }
359+ else if (flag_is_common(p->flags)) {
360+ /* And so must this */
361+ }
362+ else if (p->flags & BSF_CTOR) {
363+ /* Throw it away */
364+ }
365+else
366+ {
367+ FAIL();
368+ }
369+ }
370+ }
371+
372+
373+ }
374+ return output_buffer;
375+}
376+
377+
378+static asymbol **
379+write_file_globals(symbol_table)
380+asymbol **symbol_table;
381+{
382+ FOR_EACH_LDSYM(sp)
383+ {
384+ if (sp->sdefs_chain != (asymbol **)NULL) {
385+ asymbol *bufp = (*(sp->sdefs_chain));
386+
387+ if ((bufp->flags & BSF_KEEP) ==0) {
388+ ASSERT(bufp != (asymbol *)NULL);
389+
390+ bufp->name = sp->name;
391+
392+ if (sp->scoms_chain != (asymbol **)NULL)
393+
394+ {
395+ /*
396+ defined as common but not allocated, this happens
397+ only with -r and not -d, write out a common
398+ definition
399+ */
400+ bufp = *(sp->scoms_chain);
401+ }
402+ *symbol_table++ = bufp;
403+ }
404+ }
405+ else if (sp->scoms_chain != (asymbol **)NULL) {
406+ /* This symbol is a common - just output */
407+ asymbol *bufp = (*(sp->scoms_chain));
408+ *symbol_table++ = bufp;
409+ }
410+ else if (sp->srefs_chain != (asymbol **)NULL) {
411+ /* This symbol is undefined but has a reference */
412+ asymbol *bufp = (*(sp->srefs_chain));
413+ *symbol_table++ = bufp;
414+ }
415+ else {
416+ /*
417+ This symbol has neither defs nor refs, it must have come
418+ from the command line, since noone has used it it has no
419+ data attatched, so we'll ignore it
420+ */
421+ }
422+ }
423+ return symbol_table;
424+}
425+
426+
427+
428+void
429+ldsym_write()
430+{
431+ if (strip_symbols != STRIP_ALL) {
432+ /* We know the maximum size of the symbol table -
433+ it's the size of all the global symbols ever seen +
434+ the size of all the symbols from all the files +
435+ the number of files (for the per file symbols)
436+ +1 (for the null at the end)
437+ */
438+ extern unsigned int total_files_seen;
439+ extern unsigned int total_symbols_seen;
440+
441+ asymbol ** symbol_table = (asymbol **)
442+ ldmalloc ((size_t)(global_symbol_count +
443+ total_files_seen +
444+ total_symbols_seen + 1) * sizeof (asymbol *));
445+ asymbol ** tablep = write_file_locals(symbol_table);
446+
447+ tablep = write_file_globals(tablep);
448+
449+ *tablep = (asymbol *)NULL;
450+ bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
451+ }
452+}
--- /dev/null
+++ b/ld/ldwrite.c
@@ -0,0 +1,441 @@
1+/* Copyright (C) 1991 Free Software Foundation, Inc.
2+
3+This file is part of GLD, the Gnu Linker.
4+
5+GLD is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 1, or (at your option)
8+any later version.
9+
10+GLD is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with GLD; see the file COPYING. If not, write to
17+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18+
19+/*
20+ * $Id$
21+ *
22+ * $Log$
23+ * Revision 1.1 1991/03/21 21:29:04 gumby
24+ * Initial revision
25+ *
26+ * Revision 1.2 1991/03/15 18:45:55 rich
27+ * foo
28+ *
29+ * Revision 1.1 1991/03/13 00:48:37 chrisb
30+ * Initial revision
31+ *
32+ * Revision 1.7 1991/03/10 19:15:03 sac
33+ * Took out the abort() which had been put in the wrong place
34+ * Updated the version #.
35+ *
36+ * Revision 1.6 1991/03/10 09:31:41 rich
37+ * Modified Files:
38+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
39+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
40+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
41+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
42+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
43+ *
44+ * As of this round of changes, ld now builds on all hosts of (Intel960)
45+ * interest and copy passes my copy test on big endian hosts again.
46+ *
47+ * Revision 1.5 1991/03/09 03:25:08 sac
48+ * Added support for LONG, SHORT and BYTE keywords in scripts
49+ *
50+ * Revision 1.4 1991/03/06 21:59:34 sac
51+ * Completed G++ support
52+ *
53+ * Revision 1.3 1991/03/06 02:29:52 sac
54+ * Added support for partial linking.
55+ *
56+ * Revision 1.2 1991/02/22 17:15:11 sac
57+ * Added RCS keywords and copyrights
58+ *
59+*/
60+
61+/*
62+ This module writes out the final image by reading sections from the
63+ input files, relocating them and writing them out
64+
65+ There are two main paths through this module, one for normal
66+ operation and one for partial linking.
67+
68+ During normal operation, raw section data is read along with the
69+ associated relocation information, the relocation info applied and
70+ the section data written out on a section by section basis.
71+
72+ When partially linking, all the relocation records are read to work
73+ out how big the output relocation vector will be. Then raw data is
74+ read, relocated and written section by section.
75+
76+ Written by Steve Chamberlain steve@cygnus.com
77+
78+*/
79+
80+
81+#include "sysdep.h"
82+#include "bfd.h"
83+
84+#include "ldlang.h"
85+#include "ld.h"
86+#include "ldwrite.h"
87+#include "ldmisc.h"
88+#include "ldsym.h"
89+#include "ldgram.tab.h"
90+
91+
92+
93+char *ldmalloc();
94+/* Static vars for do_warnings and subroutines of it */
95+int list_unresolved_refs; /* List unresolved refs */
96+int list_warning_symbols; /* List warning syms */
97+int list_multiple_defs; /* List multiple definitions */
98+extern int errno;
99+extern char *sys_errlist[];
100+
101+extern unsigned int undefined_global_sym_count;
102+
103+extern bfd *output_bfd;
104+
105+extern struct lang_output_section_statement_struct * create_object_symbols;
106+
107+extern char lprefix;
108+
109+#ifdef __STDC__
110+void lang_for_each_statement(void (*func)());
111+#else /* __STDC__ */
112+void lang_for_each_statement();
113+#endif /* __STDC__ */
114+
115+extern size_t largest_section;
116+ld_config_type config;
117+
118+extern unsigned int global_symbol_count;
119+
120+boolean trace_files;
121+
122+static void perform_relocation(input_bfd,
123+ input_section,
124+ data,
125+ symbols)
126+bfd *input_bfd;
127+asection *input_section;
128+void *data;
129+asymbol **symbols;
130+{
131+ static asymbol *error_symbol = (asymbol *)NULL;
132+ static unsigned int error_count = 0;
133+#define MAX_ERRORS_IN_A_ROW 5
134+ size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
135+
136+ arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
137+ arelent **parent;
138+ bfd *ob = output_bfd;
139+ asection *os = input_section->output_section;
140+ if (config.relocateable_output == false) ob = (bfd *)NULL;
141+
142+ if (bfd_canonicalize_reloc(input_bfd,
143+ input_section,
144+ reloc_vector,
145+ symbols) )
146+ {
147+ for (parent = reloc_vector; *parent; parent++)
148+ {
149+
150+ bfd_reloc_status_enum_type r=
151+ bfd_perform_relocation(input_bfd,
152+ *parent,
153+ data,
154+ input_section,
155+ ob);
156+
157+ if (r == bfd_reloc_ok) {
158+ if (ob != (bfd *)NULL) {
159+ /* A parital link, so keep the relocs */
160+ os->orelocation[os->reloc_count] = *parent;
161+ os->reloc_count++;
162+ }
163+ }
164+ else
165+ {
166+ asymbol *s;
167+ arelent *p = *parent;
168+
169+ if (ob != (bfd *)NULL) {
170+ /* A parital link, so keep the relocs */
171+ os->orelocation[os->reloc_count] = *parent;
172+ os->reloc_count++;
173+ }
174+
175+ if (p->sym_ptr_ptr != (asymbol **)NULL) {
176+ s = *(p->sym_ptr_ptr);
177+ }
178+ else {
179+ s = (asymbol *)NULL;
180+ }
181+ switch (r)
182+ {
183+ case bfd_reloc_undefined:
184+ /* We remember the symbol, and never print more than
185+ a reasonable number of them in a row */
186+ if (s == error_symbol) {
187+ error_count++;
188+ }
189+ else {
190+ error_count = 0;
191+ error_symbol = s;
192+ }
193+ if (error_count < MAX_ERRORS_IN_A_ROW) {
194+ info("%C: undefined reference to `%T'\n",
195+ input_bfd,
196+ input_section,
197+ symbols,
198+ (*parent)->address,
199+ s);
200+ config.make_executable = false;
201+ }
202+ else if (error_count == MAX_ERRORS_IN_A_ROW) {
203+ info("%C: more undefined references to `%T' follow\n",
204+ input_bfd,
205+ input_section,
206+ symbols,
207+ (*parent)->address,
208+ s);
209+ }
210+ else {
211+ /* Don't print any more */
212+ }
213+ break;
214+ case bfd_reloc_dangerous:
215+ info("%B: relocation may be wrong `%T'\n",
216+ input_bfd,
217+ s);
218+ break;
219+ case bfd_reloc_outofrange:
220+ info("%B:%s relocation address out of range %T (%x)\n",
221+ input_bfd,
222+ input_section->name,
223+ s,
224+ p->address);
225+ break;
226+ case bfd_reloc_overflow:
227+ info("%B:%s relocation overflow in %T reloc type %d\n",
228+ input_bfd,
229+ input_section->name,
230+ s,
231+ p->howto->type);
232+ break;
233+ default:
234+ info("%F%B: relocation error, symbol `%T'\n",
235+ input_bfd,
236+ s);
237+ break;
238+ }
239+ }
240+ }
241+ }
242+ free((char *)reloc_vector);
243+}
244+
245+
246+
247+
248+
249+
250+void *data_area;
251+
252+static void
253+copy_and_relocate(statement)
254+lang_statement_union_type *statement;
255+{
256+ switch (statement->header.type) {
257+ case lang_fill_statement_enum:
258+ {
259+#if 0
260+ bfd_byte play_area[SHORT_SIZE];
261+ unsigned int i;
262+ bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
263+ /* Write out all entire shorts */
264+ for (i = 0;
265+ i < statement->fill_statement.size - SHORT_SIZE + 1;
266+ i+= SHORT_SIZE)
267+ {
268+ bfd_set_section_contents(output_bfd,
269+ statement->fill_statement.output_section,
270+ play_area,
271+ statement->data_statement.output_offset +i,
272+ SHORT_SIZE);
273+
274+ }
275+
276+ /* Now write any remaining byte */
277+ if (i < statement->fill_statement.size)
278+ {
279+ bfd_set_section_contents(output_bfd,
280+ statement->fill_statement.output_section,
281+ play_area,
282+ statement->data_statement.output_offset +i,
283+ 1);
284+
285+ }
286+#endif
287+ }
288+ break;
289+ case lang_data_statement_enum:
290+ {
291+ bfd_vma value = statement->data_statement.value;
292+ bfd_byte play_area[LONG_SIZE];
293+ unsigned int size;
294+ switch (statement->data_statement.type) {
295+ case LONG:
296+ bfd_putlong(output_bfd, value, play_area);
297+ size = LONG_SIZE;
298+ break;
299+ case SHORT:
300+ bfd_putshort(output_bfd, value, play_area);
301+ size = SHORT_SIZE;
302+ break;
303+ case BYTE:
304+ bfd_putchar(output_bfd, value, play_area);
305+ size = BYTE_SIZE;
306+ break;
307+ }
308+
309+ bfd_set_section_contents(output_bfd,
310+ statement->data_statement.output_section,
311+ play_area,
312+ statement->data_statement.output_vma,
313+ size);
314+
315+
316+
317+
318+ }
319+ break;
320+ case lang_input_section_enum:
321+ {
322+
323+ asection *i = statement->input_section.section;
324+ asection *output_section = i->output_section;
325+ lang_input_statement_type *ifile = statement->input_section.ifile;
326+ bfd *inbfd = ifile->the_bfd;
327+ if (output_section->flags & SEC_LOAD && i->size != 0)
328+ {
329+ if(bfd_get_section_contents(inbfd,
330+ i,
331+ data_area,
332+ 0L,
333+ i->size) == false)
334+ {
335+ info("%F%B error reading section contents %E\n",
336+ inbfd);
337+ }
338+ perform_relocation (inbfd, i, data_area, ifile->asymbols);
339+
340+
341+ if(bfd_set_section_contents(output_bfd,
342+ output_section,
343+ data_area,
344+ (file_ptr)i->output_offset,
345+ i->size) == false)
346+ {
347+ info("%F%B error writing section contents of %E\n",
348+ output_bfd);
349+ }
350+
351+ }
352+ }
353+ break;
354+
355+ default:
356+ /* All the other ones fall through */
357+ ;
358+
359+ }
360+}
361+
362+void
363+write_norel()
364+{
365+ /* Output the text and data segments, relocating as we go. */
366+ lang_for_each_statement(copy_and_relocate);
367+}
368+
369+
370+static void read_relocs(abfd, section, symbols)
371+bfd *abfd;
372+asection *section;
373+asymbol **symbols;
374+{
375+ /* Work out the output section ascociated with this input section */
376+ asection *output_section = section->output_section;
377+
378+ size_t reloc_size = get_reloc_upper_bound(abfd, section);
379+ arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
380+
381+ if (bfd_canonicalize_reloc(abfd,
382+ section,
383+ reloc_vector,
384+ symbols)) {
385+ output_section->reloc_count += section->reloc_count;
386+ }
387+}
388+
389+
390+static void
391+write_rel()
392+{
393+ /*
394+ Run through each section of each file and work work out the total
395+ number of relocation records which will finally be in each output
396+ section
397+ */
398+
399+ LANG_FOR_EACH_INPUT_SECTION
400+ (statement, abfd, section,
401+ (read_relocs(abfd, section, statement->asymbols)));
402+
403+
404+
405+ /*
406+ Now run though all the output sections and allocate the space for
407+ all the relocations
408+ */
409+ LANG_FOR_EACH_OUTPUT_SECTION
410+ (section,
411+ (section->orelocation =
412+ (arelent **)ldmalloc((size_t)(sizeof(arelent **)*
413+ section->reloc_count)),
414+ section->reloc_count = 0,
415+ section->flags |= SEC_HAS_CONTENTS));
416+
417+
418+ /*
419+ Copy the data, relocating as we go
420+ */
421+ lang_for_each_statement(copy_and_relocate);
422+}
423+
424+void
425+ldwrite ()
426+{
427+ data_area = (void*) ldmalloc(largest_section);
428+ if (config.relocateable_output == true)
429+ {
430+ write_rel();
431+ }
432+ else
433+ {
434+ write_norel();
435+ }
436+ free(data_area);
437+ /* Output the symbol table (both globals and locals). */
438+ ldsym_write ();
439+
440+}
441+
--- /dev/null
+++ b/ld/ldwrite.h
@@ -0,0 +1,24 @@
1+/* ldwrite.h -
2+
3+ Copyright (C) 1991 Free Software Foundation, Inc.
4+
5+ This file is part of GLD, the Gnu Linker.
6+
7+ GLD is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 1, or (at your option)
10+ any later version.
11+
12+ GLD is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with GLD; see the file COPYING. If not, write to
19+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20+
21+
22+
23+
24+PROTO(void, ldwrite, (void));