aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rwxr-xr-xld/Makefile182
-rwxr-xr-xld/ld-emul.c144
-rwxr-xr-xld/ld-gld.c258
-rwxr-xr-xld/ld-gld960.c189
-rwxr-xr-xld/ld-lnk960.c321
-rw-r--r--ld/ld.h132
-rw-r--r--ld/ldexp.c770
-rw-r--r--ld/ldexp.h99
-rw-r--r--ld/ldfile.c284
-rw-r--r--ld/ldfile.h27
-rw-r--r--ld/ldgram.y693
-rw-r--r--ld/ldlang.c2231
-rw-r--r--ld/ldlang.h347
-rw-r--r--ld/ldlex.h26
-rw-r--r--ld/ldlex.l490
-rw-r--r--ld/ldmain.c806
-rw-r--r--ld/ldmain.h23
-rw-r--r--ld/ldmisc.c303
-rw-r--r--ld/ldmisc.h34
-rw-r--r--ld/ldsym.c452
-rw-r--r--ld/ldwrite.c441
-rw-r--r--ld/ldwrite.h24
22 files changed, 8276 insertions, 0 deletions
diff --git a/ld/Makefile b/ld/Makefile
new file mode 100755
index 0000000..014b17f
--- /dev/null
+++ b/ld/Makefile
@@ -0,0 +1,182 @@
+#
+# Makefile for ld version 2
+#
+# $Id$
+#
+srcdir = .
+BASEDIR = ../..
+
+INCLUDE = $(srcdir)/$(BASEDIR)/include-cygnus
+INCLUDES = -I$(srcdir) -I$(INCLUDE)
+DEBUG = -g
+CFLAGS = $(INCLUDES) $(DEBUG)
+
+# go directly to ld.new in case this ld isn't capable of
+# linking native object on this host. It can be renamed on
+# install.
+PROGS = ld.new
+
+# for self hosting
+GNUTARGET=a.out-generic-big
+LDEMULATION=gld
+bfdlib=$(srcdir)/$(BASEDIR)/bfd/$(HOST)/libbfd.a
+
+OBJS= ldgram.o ldlex.o ldlang.o ldmain.o ldwrite.o ldexp.o ld-lnk960.o \
+ ld-gld.o ld-gld960.o ld-emul.o ldversion.o ldmisc.o ldsym.o ldfile.o
+
+HEADERS=config.h ldmain.h ldmain.h ldmisc.h ldsym.h ldlang.h ldexp.h \
+ ldlex.h ldwrite.h ldversion.h ld-emul.h ldfile.h ldgram.h ld.h
+
+MANSOURCES=ld.tex
+
+LDCSOURCES=ldlang.c ldmain.c ldwrite.c ld-lnk960.c ld-gld.c \
+ ld-gld960.c ld-emul.c ldversion.c ldmisc.c ldexp.c ldsym.c ldfile.c
+
+GENERATED_SOURCES=ldgram.tab.c ldlex.c
+GENERATED_HEADERS=ldgram.tab.h
+
+LDSOURCES=$(LDCSOURCES) ldgram.y ldlex.l
+
+#BFDSOURCES=../bfd/libbfd.c ../bfd/bfd.c ../bfd/sunos.c ../bfd/icoff.c ../bfd/b.out.c ../bfd/archive.c ../bfd/srec.c
+
+SOURCES= $(LDSOURCES) $(BFDSOURCES)
+LINTSOURCES= $(LDCSOURCES) $(BFDSOURCES) $(GENERATED_SOURCES)
+
+all: $(PROGS)
+
+$(PROGS): $(OBJS)
+# (cd ../bfd; make)
+# 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
+# gld -o ld /lib/crt0.o $(OBJS) $(bfdlib) -lc /usr/local/lib/gcc/sparc/1.91/gnulib
+ $(CC) -Bstatic -o ld.new $(OBJS) $(bfdlib)
+
+
+ld1: ld
+ gcc -v -B./ -o ld1 $(OBJS) $(bfdlib)
+
+ld2: ld1
+ mv ld1 ld
+ gcc -v -B./ -o ld2 $(OBJS) $(bfdlib)
+
+ld3: ld2
+ mv ld2 ld
+ gcc -v -B./ -o ld3 $(OBJS) $(bfdlib)
+
+ld.dvi:ld.tex
+ tex ld.tex
+
+ldgram.o:ldgram.y
+ yacc -d ldgram.y
+ mv y.tab.c ldgram.tab.c
+ $(CC) -c $(CFLAGS) ldgram.tab.c
+ mv ldgram.tab.o ldgram.o
+
+ldgram.tab.h:ldgram.o
+ cp y.tab.h ldgram.tab.h
+
+ldlex.c: ldlex.l ldgram.tab.h
+ldlex.o: ldlex.c ldgram.tab.h
+
+ldmain.o: ldmain.c
+ldversion.o: ldversion.c
+ldfile.o: ldfile.c
+ldwrite.o: ldwrite.c
+ldlang.o: ldlang.c ldgram.tab.h
+ld-gld.o: ld-gld.c
+ld-gld960.o: ld-gld960.c
+ld-emul.o:ld-emul.c
+ld-lnk960.o:ld-lnk960.c
+ldexp.o:ldexp.c ldgram.tab.h
+ldmisc.o:ldmisc.c
+ldsym.o:ldsym.c
+
+clean:
+ - rm -f $(OBJS) $(GENERATED_SOURCES) $(GENERATED_HEADERS)
+ - rm -f ld ld1 ld2
+
+lintlog:$(SOURCES) Makefile
+ $(LINT) -abhxzn $(CFLAGS) $(LINTSOURCES) \
+| grep -v "pointer casts may be troublesome" \
+| grep -v "possible pointer alignment problem" \
+| grep -v "ignore" \
+| grep -v "conversion from long may lose accuracy" \
+| grep -v "warning: constant argument to NOT" \
+| grep -v "enumeration type clash, operator CAST" \
+| grep -v "warning: constant in conditional context"\
+| grep -v "archive\.c"
+
+
+tags TAGS:$(SOURCES) $(HEADERS)
+ etags -t $(SOURCES) $(HEADERS)
+
+release:
+ (cd /4/steve/ld; tar cf - $(LDSOURCES) $(HEADERS) $(MANSOURCES)) | tar xf -
+
+objdump:objdump.c
+
+install: $(PROGS)
+ rm -f $G960BASE/bin/$(PROGS)
+ cp $(PROGS) $$G960BASE/bin/gld960c
+
+#-----------------------------------------------------------------------------
+# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT
+#
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#-----------------------------------------------------------------------------
+
+ver960.c: FORCE
+ rm -f ver960.c
+ echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+ @V=`cat VERSION` ; \
+ MAJ=`sed 's/\..*//' VERSION` ; \
+ MIN=`sed 's/.*\.//' VERSION` ; \
+ V=$$MAJ.`expr $$MIN + 1` ; \
+ rm -f VERSION ; \
+ echo $$V >VERSION ; \
+ echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+.force:
+FORCE:
+
+# Target to uncomment host-specific lines in this makefile. Such lines must
+# have the following string beginning in column 1: #__<hostname>__#
+# Original Makefile is backed up as 'Makefile.old'.
+#
+# Invoke with: make make HOST=xxx
+#
+make:
+ -@if test $(HOST)x = x ; then \
+ echo 'Specify "make make HOST=???"'; \
+ exit 1; \
+ fi ; \
+ grep -s "^#The next line was generated by 'make make'" Makefile; \
+ if test $$? = 0 ; then \
+ echo "Makefile has already been processed with 'make make'";\
+ exit 1; \
+ fi ; \
+ mv -f Makefile Makefile.old; \
+ echo "#The next line was generated by 'make make'" >Makefile ; \
+ echo "HOST=$(HOST)" >>Makefile ; \
+ echo >>Makefile ; \
+ sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile
+
+#
+
+Makefile: ../common/Makefile
+ mv Makefile Makefile.backup
+ cp ../common/Makefile .
+ $(MAKE) "HOST=$(HOST)" make
+
+### Local Variables: ***
+### mode:fundamental ***
+### page-delimiter: "^# " ***
+### End: ***
+### end of file
diff --git a/ld/ld-emul.c b/ld/ld-emul.c
new file mode 100755
index 0000000..7eb23d4
--- /dev/null
+++ b/ld/ld-emul.c
@@ -0,0 +1,144 @@
+
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ $Id$
+
+ $Log$
+ Revision 1.1 1991/03/21 21:28:19 gumby
+ Initial revision
+
+ * Revision 1.1 1991/03/13 00:48:09 chrisb
+ * Initial revision
+ *
+ * Revision 1.4 1991/03/10 09:31:16 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3 1991/02/22 17:14:55 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+/*
+ * clearing house for ld emulation states
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "config.h"
+#include "ld.h"
+#include "ld-emul.h"
+#include "ldmisc.h"
+
+extern ld_emulation_xfer_type ld_lnk960_emulation;
+extern ld_emulation_xfer_type ld_gld_emulation;
+extern ld_emulation_xfer_type ld_gld960_emulation;
+
+
+
+ld_emulation_xfer_type *ld_emulation;
+
+void
+ldemul_hll(name)
+char *name;
+{
+ ld_emulation->hll(name);
+}
+
+
+void ldemul_syslib(name)
+char *name;
+{
+ ld_emulation->syslib(name);
+}
+
+void
+ldemul_after_parse()
+{
+ ld_emulation->after_parse();
+}
+
+void
+ldemul_before_parse()
+{
+ ld_emulation->before_parse();
+}
+
+void
+ldemul_after_allocation()
+{
+ ld_emulation->after_allocation();
+}
+
+void
+ldemul_before_allocation()
+{
+ if (ld_emulation->before_allocation) {
+ ld_emulation->before_allocation();
+ }
+}
+
+
+void
+ldemul_set_output_arch()
+{
+ ld_emulation->set_output_arch();
+}
+
+char *
+ldemul_choose_target()
+{
+ return ld_emulation->choose_target();
+}
+
+char *
+ldemul_get_script()
+{
+ return ld_emulation->get_script();
+}
+
+void
+ldemul_choose_mode(target)
+char *target;
+{
+ if (strcmp(target,LNK960_EMULATION_NAME)==0) {
+ ld_emulation = &ld_lnk960_emulation;
+ }
+ else if (strcmp(target,GLD_EMULATION_NAME)==0) {
+ ld_emulation = &ld_gld_emulation;
+ }
+ else if (strcmp(target,GLD960_EMULATION_NAME)==0) {
+ ld_emulation = &ld_gld960_emulation;
+ }
+ else {
+ info("%P%F unrecognised emulation mode: %s",target);
+ }
+}
+
+
+
diff --git a/ld/ld-gld.c b/ld/ld-gld.c
new file mode 100755
index 0000000..4c3df1a
--- /dev/null
+++ b/ld/ld-gld.c
@@ -0,0 +1,258 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:24 gumby
+ * Initial revision
+ *
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:11 chrisb
+ * Initial revision
+ *
+ * Revision 1.7 1991/03/10 09:31:18 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.6 1991/03/09 03:23:12 sac
+ * Added -Ur loader script.
+ *
+ * Revision 1.5 1991/03/06 21:59:29 sac
+ * Completed G++ support
+ *
+ * Revision 1.4 1991/03/06 02:23:34 sac
+ * Added support for partial linking.
+ *
+ * Revision 1.3 1991/02/22 17:14:56 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ * emulate the original gld
+ *
+ * Written by Steve Chamberlain steve@cygnus.com
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+extern boolean lang_float_flag;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+extern bfd *output_bfd;
+
+
+
+static void gld_before_parse()
+{
+ ldfile_add_library_path("/lib");
+ ldfile_add_library_path("/usr/lib");
+ ldfile_add_library_path("/usr/local/lib/lib");
+ ldfile_output_architecture = bfd_arch_sparc;
+}
+
+
+static void
+gld_after_parse()
+{
+
+}
+
+static void
+gld_after_allocation()
+{
+
+}
+
+static void
+gld_before_allocation()
+{
+
+}
+
+
+static void
+gld_set_output_arch()
+{
+ /* Set the output architecture and machine if possible */
+ unsigned long machine = 0;
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+gld_choose_target()
+{
+ char *from_outside = getenv(TARGET_ENVIRON);
+ if (from_outside != (char *)NULL)
+ return from_outside;
+ return GLD_TARGET;
+}
+
+static void
+gld_syslib()
+{
+ info("%S SYSLIB ignored\n");
+}
+
+static void
+gld_hll(ignore)
+char *ignore;
+{
+ info("%S HLL ignored\n");
+}
+
+static char *gld_script = " \
+SEARCH_DIR(/lib) \
+SEARCH_DIR(/usr/lib) \
+SEARCH_DIR(/usr/local/lib) \
+__DYNAMIC = 0; \
+SECTIONS \
+{ \
+ .text 0x2020 BLOCK(0x2000): \
+ { \
+ CREATE_OBJECT_SYMBOLS \
+ *(.text) \
+ _etext = ALIGN( 0x2000); \
+ } \
+ .data ALIGN(0x2000) : \
+ { \
+ *(.data) \
+ ___DTOR_LIST__=. ; \
+ LONG((___CTOR_LIST__ - .)/4 -2) \
+ *(___DTOR_LIST__) \
+ LONG(0) \
+ ___CTOR_LIST__=. ; \
+ LONG((_edata - .)/4 -2) \
+ *(___CTOR_LIST__) \
+ LONG(0) \
+ _edata = .; \
+ } \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { \
+ *(.bss) \
+ [COMMON] \
+ _end=.; \
+ } \
+}";
+
+
+static char *gld_script_option_Ur = "\
+SEARCH_DIR(/lib) \
+SEARCH_DIR(/usr/lib) \
+SEARCH_DIR(/usr/local/lib) \
+SECTIONS \
+{ \
+ .text 0: \
+ { \
+ CREATE_OBJECT_SYMBOLS \
+ *(.text) \
+ } \
+ .data SIZEOF(.text) + ADDR(.text) : \
+ { \
+ *(.data) \
+ ___DTOR_LIST__=. ; \
+ LONG((___CTOR_LIST__ - .)/4 -2) \
+ *(___DTOR_LIST__) \
+ LONG(0) \
+ ___CTOR_LIST__=. ; \
+ LONG((___end_list__ - .)/4 -2) \
+ *(___CTOR_LIST__) \
+ LONG(0) \
+ ___end_list__ = . ; \
+ } \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { \
+ *(.bss) \
+ [COMMON] \
+ } \
+} \
+";
+
+static char *gld_script_option_r = "\
+SEARCH_DIR(/lib) \
+SEARCH_DIR(/usr/lib) \
+SEARCH_DIR(/usr/local/lib) \
+SECTIONS \
+{ \
+ .text 0: \
+ { \
+ CREATE_OBJECT_SYMBOLS \
+ *(.text) \
+ } \
+ .data SIZEOF(.text) + ADDR(.text) : \
+ { \
+ *(.data) \
+ } \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { \
+ *(.bss) \
+ [COMMON] \
+ } \
+} \
+";
+
+static char *gld_get_script()
+{
+ extern ld_config_type config;
+ if (config.relocateable_output == true &&
+ config.build_constructors == true) {
+ return gld_script_option_Ur;
+ }
+ if (config.relocateable_output) {
+ return gld_script_option_r;
+ }
+
+ return gld_script;
+}
+struct ld_emulation_xfer_struct ld_gld_emulation =
+{
+ gld_before_parse,
+ gld_syslib,
+ gld_hll,
+ gld_after_parse,
+ gld_after_allocation,
+ gld_set_output_arch,
+ gld_choose_target,
+ gld_before_allocation,
+ gld_get_script,
+};
+
diff --git a/ld/ld-gld960.c b/ld/ld-gld960.c
new file mode 100755
index 0000000..5e0c1a2
--- /dev/null
+++ b/ld/ld-gld960.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ $Id$
+
+ $Log$
+ Revision 1.1 1991/03/21 21:28:26 gumby
+ Initial revision
+
+ * Revision 1.3 1991/03/16 22:27:24 rich
+ * fish
+ *
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:12 chrisb
+ * Initial revision
+ *
+ * Revision 1.4 1991/03/10 09:31:19 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3 1991/02/22 17:14:57 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ * emulate the Intels port of gld
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+
+/* IMPORTS */
+extern char *output_filename;
+extern boolean lang_float_flag;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+extern bfd *output_bfd;
+
+
+
+static void gld960_before_parse()
+{
+ char *env ;
+ env = getenv("G960LIB");
+ if (env) {
+ ldfile_add_library_path(env);
+ }
+ env = getenv("G960BASE");
+ if (env) {
+ ldfile_add_library_path(concat(env,"/lib",""));
+ }
+ ldfile_output_architecture = bfd_arch_i960;
+}
+
+
+static void
+gld960_after_parse()
+{
+
+}
+
+static void
+gld960_after_allocation()
+{
+
+}
+
+static void
+gld960_before_allocation()
+{
+
+}
+
+
+static void
+gld960_set_output_arch()
+{
+ /* Set the output architecture and machine if possible */
+ unsigned long machine = 0;
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+gld960_choose_target()
+{
+ char *from_outside = getenv(TARGET_ENVIRON);
+ output_filename = "b.out";
+
+ if (from_outside != (char *)NULL)
+ return from_outside;
+ return GLD960_TARGET;
+}
+
+static void
+gld960_syslib()
+{
+ info("%S SYSLIB ignored\n");
+}
+
+static void
+gld960_hll()
+{
+ info("%S HLL ignored\n");
+}
+
+
+static char *script = "\
+ \
+SECTIONS \
+{ \
+ .text : \
+ { \
+ CREATE_OBJECT_SYMBOLS \
+ *(.text) \
+ _etext =.;\
+ } \
+ \
+ .data SIZEOF(.text) + ADDR(.text):\
+ { \
+ \
+ *(.data) \
+ _edata = .; \
+ } \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { _bss_start = .;\
+ *(.bss) \
+ [COMMON] \
+ _end = . ; \
+ } \
+} \
+";
+
+static char *
+gld960_get_script()
+{
+return script;
+}
+
+struct ld_emulation_xfer_struct ld_gld960_emulation =
+{
+ gld960_before_parse,
+ gld960_syslib,
+ gld960_hll,
+ gld960_after_parse,
+ gld960_after_allocation,
+ gld960_set_output_arch,
+ gld960_choose_target,
+ gld960_before_allocation,
+ gld960_get_script,
+};
diff --git a/ld/ld-lnk960.c b/ld/ld-lnk960.c
new file mode 100755
index 0000000..0f82ebe
--- /dev/null
+++ b/ld/ld-lnk960.c
@@ -0,0 +1,321 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ $Id$
+
+ $Log$
+ Revision 1.1 1991/03/21 21:28:28 gumby
+ Initial revision
+
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:13 chrisb
+ * Initial revision
+ *
+ * Revision 1.6 1991/03/10 09:31:20 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:23:47 sac
+ * Now looks in G960BASE if I960BASE isn't defined.
+ *
+ * Revision 1.4 1991/03/06 02:23:35 sac
+ * Added support for partial linking.
+ *
+ * Revision 1.3 1991/02/22 17:14:58 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+
+ Written by Steve Chamberlain steve@cygnus.com
+
+ * intel coff loader emulation specific stuff
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+/*#include "archures.h"*/
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+#include "ldfile.h"
+
+extern boolean lang_float_flag;
+extern bfd *output_bfd;
+
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+
+typedef struct lib_list {
+ char *name;
+ struct lib_list *next;
+} lib_list_type;
+
+static lib_list_type *hll_list;
+static lib_list_type **hll_list_tail = &hll_list;
+
+static lib_list_type *syslib_list;
+static lib_list_type **syslib_list_tail = &syslib_list;
+
+
+static void
+append(list, name)
+lib_list_type ***list;
+char *name;
+{
+ lib_list_type *element =
+ (lib_list_type *)(ldmalloc(sizeof(lib_list_type)));
+
+ element->name = name;
+ element->next = (lib_list_type *)NULL;
+ **list = element;
+ *list = &element->next;
+
+}
+
+static boolean had_hll = false;
+static boolean had_hll_name = false;
+static void
+lnk960_hll(name)
+char *name;
+{
+ had_hll = true;
+ if (name != (char *)NULL) {
+ had_hll_name = true;
+ append(&hll_list_tail, name);
+ }
+}
+
+static void
+lnk960_syslib(name)
+char *name;
+{
+ append(&syslib_list_tail,name);
+}
+
+
+
+static void
+lnk960_before_parse()
+{
+ char *name = getenv("I960BASE");
+
+ if (name == (char *)NULL) {
+ name = getenv("G960BASE");
+ if (name == (char *)NULL) {
+ info("%P%F I960BASE and G960BASE not set\n");
+ }
+ }
+
+
+ ldfile_add_library_path(concat(name,"/lib",""));
+ ldfile_output_architecture = bfd_arch_i960;
+ ldfile_output_machine = bfd_mach_i960_core;
+}
+
+static void
+add_on(list, search)
+lib_list_type *list;
+lang_input_file_enum_type search;
+{
+ while (list) {
+ lang_add_input_file(list->name,
+ search,
+ (char *)NULL);
+ list = list->next;
+ }
+}
+static void lnk960_after_parse()
+{
+
+ /* If there has been no arch, default to -KB */
+ if (ldfile_output_machine_name[0] ==0) {
+ ldfile_add_arch("kb");
+ }
+
+ /* if there has been no hll list then add our own */
+
+ if(had_hll && !had_hll_name) {
+ append(&hll_list_tail,"c");
+ if (lang_float_flag == true) {
+ append(&hll_list_tail,"m");
+ }
+ else {
+ append(&hll_list_tail,"mstub");
+ }
+ if (ldfile_output_machine == bfd_mach_i960_ka_sa ||
+ ldfile_output_machine == bfd_mach_i960_ca) {
+ {
+ append(&hll_list_tail,"f");
+ }
+ }
+ }
+
+
+
+ add_on(hll_list, lang_input_file_is_l_enum);
+ add_on(syslib_list, lang_input_file_is_search_file_enum);
+
+
+}
+
+static void
+lnk960_before_allocation()
+{
+}
+static void
+lnk960_after_allocation()
+{
+ lang_abs_symbol_at_end_of(".text","_etext");
+ lang_abs_symbol_at_end_of(".data","_edata");
+ lang_abs_symbol_at_end_of(".bss","_end");
+}
+
+static struct
+ {
+ unsigned long number;
+ char *name;
+ }
+machine_table[] = {
+ bfd_mach_i960_core ,"CORE",
+ bfd_mach_i960_kb_sb ,"KB",
+ bfd_mach_i960_kb_sb ,"SB",
+ bfd_mach_i960_mc ,"MC",
+ bfd_mach_i960_xa ,"XA",
+ bfd_mach_i960_ca ,"CA",
+ bfd_mach_i960_ka_sa ,"KA",
+ bfd_mach_i960_ka_sa ,"SA",
+
+ bfd_mach_i960_core ,"core",
+ bfd_mach_i960_kb_sb ,"kb",
+ bfd_mach_i960_kb_sb ,"sb",
+ bfd_mach_i960_mc ,"mc",
+ bfd_mach_i960_xa ,"xa",
+ bfd_mach_i960_ca ,"ca",
+ bfd_mach_i960_ka_sa ,"ka",
+ bfd_mach_i960_ka_sa ,"sa",
+ 0,(char *)NULL
+};
+
+static void
+lnk960_set_output_arch()
+{
+ /* Set the output architecture and machine if possible */
+ unsigned int i;
+ ldfile_output_machine = bfd_mach_i960_core;
+ for (i= 0; machine_table[i].name != (char*)NULL; i++) {
+ if (strcmp(ldfile_output_machine_name,machine_table[i].name)==0) {
+ ldfile_output_machine = machine_table[i].number;
+ break;
+ }
+ }
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, ldfile_output_machine);
+}
+
+static char *
+lnk960_choose_target()
+{
+ char *from_outside = getenv(TARGET_ENVIRON);
+ if (from_outside != (char *)NULL)
+ return from_outside;
+ return LNK960_TARGET;
+}
+
+/* The default script if none is offered */
+static char *lnk960_script = "\
+SECTIONS \
+{ \
+ .text : \
+ { \
+ *(.text) \
+ } \
+_etext = .;\
+ .data SIZEOF(.text) + ADDR(.text):\
+ { \
+ *(.data) \
+ } \
+_edata = .; \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { \
+ _bss_start = . ;\
+ *(.bss) \
+ [COMMON] \
+ } \
+_end = . ; \
+} \
+";
+
+static char *lnk960_script_relocateable = "\
+SECTIONS \
+{ \
+ .text 0x40000000: \
+ { \
+ *(.text) \
+ } \
+ .data 0:\
+ { \
+ *(.data) \
+ } \
+ .bss SIZEOF(.data) + ADDR(.data) : \
+ { \
+ *(.bss) \
+ [COMMON] \
+ } \
+} \
+";
+
+static char *lnk960_get_script()
+{
+extern ld_config_type config;
+if (config.relocateable_output) {
+ return lnk960_script_relocateable;
+}
+return lnk960_script;
+
+
+}
+struct ld_emulation_xfer_struct ld_lnk960_emulation =
+{
+ lnk960_before_parse,
+ lnk960_syslib,
+ lnk960_hll,
+ lnk960_after_parse,
+ lnk960_after_allocation,
+ lnk960_set_output_arch,
+ lnk960_choose_target,
+ lnk960_before_allocation,
+ lnk960_get_script,
+};
diff --git a/ld/ld.h b/ld/ld.h
new file mode 100644
index 0000000..fb2b62a
--- /dev/null
+++ b/ld/ld.h
@@ -0,0 +1,132 @@
+/* ld.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define flag_is_not_at_end(x) ((x) & BSF_NOT_AT_END)
+#define flag_is_ordinary_local(x) (((x) & (BSF_LOCAL))&!((x) & (BSF_DEBUGGING)))
+#define flag_is_debugger(x) ((x) & BSF_DEBUGGING)
+#define flag_is_undefined_or_global(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL))
+#define flag_is_defined(x) (!((x) & (BSF_UNDEFINED)))
+#define flag_is_global_or_common(x) ((x) & (BSF_GLOBAL | BSF_FORT_COMM))
+#define flag_is_undefined_or_global_or_common(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM))
+#define flag_is_common(x) ((x) & BSF_FORT_COMM)
+#define flag_is_global(x) ((x) & (BSF_GLOBAL))
+#define flag_is_undefined(x) ((x) & BSF_UNDEFINED)
+#define flag_set(x,y) (x = y)
+#define flag_is_fort_comm(x) ((x) & BSF_FORT_COMM)
+#define flag_is_absolute(x) ((x) & BSF_ABSOLUTE)
+/* Extra information we hold on sections */
+typedef struct user_section_struct {
+ /* Pointer to the section where this data will go */
+ struct lang_input_statement_struct *file;
+} section_userdata_type;
+
+
+#define get_userdata(x) ((x)->userdata)
+#define as_output_section_statement(x) ((x)->otheruserdata)
+
+#if 0
+/*
+ * Structure for communication between do_file_warnings and it's
+ * helper routines. Will in practice be an array of three of these:
+ * 0) Current line, 1) Next line, 2) Source file info.
+ */
+struct line_debug_entry
+{
+ int line;
+ char *filename;
+ struct nlist *sym;
+};
+
+#endif
+
+
+/* Which symbols should be stripped (omitted from the output):
+ none, all, or debugger symbols. */
+enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER } strip_symbols;
+
+
+
+
+/* Which local symbols should be omitted:
+ none, all, or those starting with L.
+ This is irrelevant if STRIP_NONE. */
+enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals;
+
+
+
+
+
+
+#define ALIGN(this, boundary) ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+#if 0
+#define FOREACHGLOBALSYMBOL(x) ldsym_type *x; for (x = symbol_head; x; x=x->next)
+
+
+
+
+#define SECTIONLOOP(abfd, ptr) \
+ asection *ptr; for(ptr = abfd->sections; ptr;ptr=ptr->next)
+
+
+#endif
+typedef struct {
+
+ /* 1 => assign space to common symbols even if `relocatable_output'. */
+ boolean force_common_definition;
+
+} args_type;
+
+typedef int token_code_type;
+
+typedef struct
+{
+ unsigned int specified_data_size;
+ boolean magic_demand_paged;
+ boolean make_executable;
+ /* 1 => write relocation into output file so can re-input it later. */
+ boolean relocateable_output;
+
+ /* Will we build contstructors, or leave alone ? */
+ boolean build_constructors;
+ /* 1 => write relocation such that a UNIX linker can understand it.
+ This is used mainly to finish of sets that were built. */
+ boolean unix_relocate;
+
+
+} ld_config_type;
+#define set_asymbol_chain(x,y) ((x)->udata = (void *)y)
+#define get_asymbol_chain(x) ((asymbol **)((x)->udata))
+#define get_loader_symbol(x) ((loader_global_asymbol *)((x)->udata))
+#define set_loader_symbol(x,y) ((x)->udata = (void *)y)
+
+
+
+
+
+
+typedef enum {
+ lang_first_phase_enum,
+ lang_allocating_phase_enum,
+ lang_final_phase_enum } lang_phase_type;
+
+
+
+
diff --git a/ld/ldexp.c b/ld/ldexp.c
new file mode 100644
index 0000000..5b8581f
--- /dev/null
+++ b/ld/ldexp.c
@@ -0,0 +1,770 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ $Id$
+
+ $Log$
+ Revision 1.1 1991/03/21 21:28:34 gumby
+ Initial revision
+
+ * Revision 1.1 1991/03/13 00:48:16 chrisb
+ * Initial revision
+ *
+ * Revision 1.6 1991/03/10 09:31:22 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:25:04 sac
+ * Added support for LONG, SHORT and BYTE keywords in scripts
+ *
+ * Revision 1.4 1991/03/06 02:27:15 sac
+ * Added LONG, SHORT and BYTE keywords
+ *
+ * Revision 1.3 1991/02/22 17:14:59 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ * Written by Steve Chamberlain
+ * steve@cygnus.com
+ *
+ * This module handles expression trees.
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldgram.tab.h"
+#include "ldsym.h"
+#include "ldlang.h"
+
+extern char *output_filename;
+extern unsigned int undefined_global_sym_count;
+extern unsigned int defined_global_sym_count;
+extern bfd *output_bfd;
+extern size_t largest_section;
+extern lang_statement_list_type file_chain;
+extern args_type command_line;
+extern ld_config_type config;
+
+extern lang_input_statement_type *script_file;
+extern unsigned int defined_global_sym_count;
+
+extern bfd_vma print_dot;
+
+
+static void
+exp_print_token(outfile, code)
+FILE *outfile;
+token_code_type code;
+{
+ static struct {
+ token_code_type code;
+ char *name;
+ } table[] =
+ {
+ INT, "int",
+ CHAR,"char",
+ NAME,"NAME",
+ PLUSEQ,"+=",
+ MINUSEQ,"-=",
+ MULTEQ,"*=",
+ DIVEQ,"/=",
+ LSHIFTEQ,"<<=",
+ RSHIFTEQ,">>=",
+ ANDEQ,"&=",
+ OREQ,"|=",
+ OROR,"||",
+ ANDAND,"&&",
+ EQ,"==",
+ NE,"!=",
+ LE,"<=",
+ GE,">=",
+ LSHIFT,"<<",
+ RSHIFT,">>=",
+ ALIGN_K,"ALIGN",
+ BLOCK,"BLOCK",
+ SECTIONS,"SECTIONS",
+ ALIGNMENT,"ALIGNMENT",
+ SIZEOF_HEADERS,"SIZEOF_HEADERS",
+ NEXT,"NEXT",
+ SIZEOF,"SIZEOF",
+ ADDR,"ADDR",
+ MEMORY,"MEMORY",
+ DSECT,"DSECT",
+ NOLOAD,"NOLOAD",
+ COPY,"COPY",
+ INFO,"INFO",
+ OVERLAY,"OVERLAY",
+ DEFINED,"DEFINED",
+ TARGET_K,"TARGET",
+ SEARCH_DIR,"SEARCH_DIR",
+ MAP,"MAP",
+ LONG,"LONG",
+ SHORT,"SHORT",
+ BYTE,"BYTE",
+ ENTRY,"ENTRY",
+ 0,(char *)NULL} ;
+
+
+
+ unsigned int idx;
+ for (idx = 0; table[idx].name != (char*)NULL; idx++) {
+ if (table[idx].code == code) {
+ fprintf(outfile, "%s", table[idx].name);
+ return;
+ }
+ }
+ /* Not in table, just print it alone */
+ fprintf(outfile, "%c",code);
+}
+
+static void
+make_abs(ptr)
+etree_value_type *ptr;
+{
+ if (ptr->section != (lang_output_section_statement_type *)NULL) {
+ asection *s = ptr->section->bfd_section;
+ ptr->value += s->vma;
+ ptr->section = (lang_output_section_statement_type *)NULL;
+ }
+
+}
+static
+etree_value_type new_abs(value)
+bfd_vma value;
+{
+ etree_value_type new;
+ new.valid = true;
+ new.section = (lang_output_section_statement_type *)NULL;
+ new.value = value;
+ return new;
+}
+
+static void check(os)
+lang_output_section_statement_type *os;
+{
+ if (os == (lang_output_section_statement_type *)NULL) {
+ info("%F%P undefined section");
+ }
+ if (os->processed == false) {
+ info("%F%P forward reference of section");
+ }
+}
+
+etree_type *exp_intop(value)
+bfd_vma value;
+{
+ etree_type *new = (etree_type *)ldmalloc(sizeof(new->value));
+ new->type.node_code = INT;
+ new->value.value = value;
+ new->type.node_class = etree_value;
+ return new;
+
+}
+
+
+static
+etree_value_type new_rel(value, section)
+bfd_vma value;
+lang_output_section_statement_type *section;
+{
+ etree_value_type new;
+ new.valid = true;
+ new.value = value;
+ new.section = section;
+ return new;
+}
+
+static
+etree_value_type new_rel_from_section(value, section)
+bfd_vma value;
+lang_output_section_statement_type *section;
+{
+ etree_value_type new;
+ new.valid = true;
+ new.value = value;
+ new.section = section;
+ if (new.section != (lang_output_section_statement_type *)NULL) {
+ new.value -= section->bfd_section->vma;
+ }
+ return new;
+}
+
+static etree_value_type
+fold_binary(tree, current_section, allocation_done, dot, dotp)
+etree_type *tree;
+lang_output_section_statement_type *current_section;
+lang_phase_type allocation_done;
+bfd_vma dot;
+bfd_vma *dotp;
+{
+ etree_value_type result;
+
+ result = exp_fold_tree(tree->binary.lhs, current_section,
+ allocation_done, dot, dotp);
+ if (result.valid) {
+ etree_value_type other;
+ other = exp_fold_tree(tree->binary.rhs,
+ current_section,
+ allocation_done, dot,dotp) ;
+ if (other.valid) {
+ /* If values are from different sections, or this is an */
+ /* absolute expression, make both source args absolute */
+ if (result.section != other.section ||
+ current_section == (lang_output_section_statement_type *)NULL) {
+
+ make_abs(&result);
+ make_abs(&other);
+ }
+
+ switch (tree->type.node_code)
+ {
+ case '%':
+ /* Mod, both absolule*/
+
+ if (other.value == 0) {
+ info("%F%S % by zero\n");
+ }
+ result.value %= other.value;
+ break;
+ case '/':
+ if (other.value == 0) {
+ info("%F%S / by zero\n");
+ }
+ result.value /= other.value;
+ break;
+#define BOP(x,y) case x : result.value = result.value y other.value;break;
+ BOP('+',+);
+ BOP('*',*);
+ BOP('-',-);
+ BOP(LSHIFT,<<);
+ BOP(RSHIFT,>>);
+ BOP(EQ,==);
+ BOP(NE,!=);
+ BOP('<',<);
+ BOP('>',>);
+ BOP(LE,<=);
+ BOP(GE,>=);
+ BOP('&',&);
+ BOP('^',^);
+ BOP('|',|);
+ BOP(ANDAND,&&);
+ BOP(OROR,||);
+ default:
+ FAIL();
+ }
+ }
+ }
+ return result;
+}
+etree_value_type invalid()
+{
+ etree_value_type new;
+ new.valid = false;
+ return new;
+}
+
+etree_value_type fold_name(tree, current_section, allocation_done, dot)
+etree_type *tree;
+lang_output_section_statement_type *current_section;
+lang_phase_type allocation_done;
+bfd_vma dot;
+
+{
+ etree_value_type result;
+ switch (tree->type.node_code)
+ {
+ case DEFINED:
+ result.value =
+ ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
+ result.section = 0;
+ result.valid = true;
+ break;
+ case NAME:
+ result.valid = false;
+ if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
+
+ if (allocation_done != lang_first_phase_enum) {
+ result = new_rel_from_section(dot, current_section);
+ }
+ else {
+ result = invalid();
+ }
+ }
+ else {
+ if (allocation_done == lang_final_phase_enum) {
+ ldsym_type *sy = ldsym_get_soft(tree->name.name);
+
+ if (sy) {
+ asymbol **sdefp = sy->sdefs_chain;
+
+ if (sdefp) {
+ asymbol *sdef = *sdefp;
+ if (sdef->section == (asection *)NULL) {
+ /* This is an absolute symbol */
+ result = new_abs(sdef->value);
+ }
+ else {
+ lang_output_section_statement_type *os =
+ lang_output_section_statement_lookup( sdef->section->output_section->name);
+ result = new_rel(sdef->value, os);
+ }
+ }
+ }
+ if (result.valid == false) {
+ info("%F%S: undefined symbol `%s' referenced in expression.\n",
+ tree->name.name);
+ }
+
+ }
+ }
+
+ break;
+
+ case ADDR:
+
+ if (allocation_done != lang_first_phase_enum) {
+ lang_output_section_statement_type *os =
+ lang_output_section_find(tree->name.name);
+ check(os);
+ result = new_rel((bfd_vma)0, os);
+ }
+ else {
+ result = invalid();
+ }
+ break;
+ case SIZEOF:
+ if(allocation_done != lang_first_phase_enum) {
+ lang_output_section_statement_type *os =
+ lang_output_section_find(tree->name.name);
+ check(os);
+ result = new_abs((bfd_vma)(os->bfd_section->size));
+ }
+ else {
+ result = invalid();
+ }
+ break;
+
+ default:
+ FAIL();
+ break;
+ }
+
+ return result;
+}
+etree_value_type exp_fold_tree(tree, current_section, allocation_done,
+ dot, dotp)
+etree_type *tree;
+lang_output_section_statement_type *current_section;
+lang_phase_type allocation_done;
+bfd_vma dot;
+bfd_vma *dotp;
+{
+ etree_value_type result;
+
+ if (tree == (etree_type *)NULL) {
+ result.valid = false;
+ }
+ else {
+ switch (tree->type.node_class)
+ {
+ case etree_value:
+ result = new_rel(tree->value.value, current_section);
+ break;
+ case etree_unary:
+ result = exp_fold_tree(tree->unary.child,
+ current_section,
+ allocation_done, dot, dotp);
+ if (result.valid == true)
+ {
+ switch(tree->type.node_code)
+ {
+ case ALIGN_K:
+ if (allocation_done != lang_first_phase_enum) {
+ result = new_rel_from_section(ALIGN(dot,
+ result.value) ,
+ current_section);
+
+ }
+ else {
+ result.valid = false;
+ }
+ break;
+ case '-':
+ result.value = -result.value;
+ break;
+ case NEXT:
+ result.valid = false;
+ break;
+ default:
+ FAIL();
+ }
+ }
+
+ break;
+ case etree_trinary:
+
+ result = exp_fold_tree(tree->trinary.cond,
+ current_section,
+ allocation_done, dot, dotp);
+ if (result.valid) {
+ result = exp_fold_tree(result.value ?
+ tree->trinary.lhs:tree->trinary.rhs,
+ current_section,
+ allocation_done, dot, dotp);
+ }
+
+ break;
+ case etree_binary:
+ result = fold_binary(tree, current_section, allocation_done,
+ dot, dotp);
+ break;
+ case etree_assign:
+ if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
+ /* Assignment to dot can only be done during allocation */
+ if (allocation_done == lang_allocating_phase_enum) {
+ result = exp_fold_tree(tree->assign.src,
+ current_section,
+ lang_allocating_phase_enum, dot, dotp);
+ if (result.valid == false) {
+ info("%F%S invalid assignment to location counter\n");
+ }
+ else {
+ if (current_section ==
+ (lang_output_section_statement_type *)NULL) {
+ info("%F%S assignment to location counter invalid outside of SECTION\n");
+ }
+ else {
+ unsigned long nextdot =result.value +
+ current_section->bfd_section->vma;
+ if (nextdot < dot) {
+ info("%F%S cannot move location counter backwards");
+ }
+ else {
+ *dotp = nextdot;
+ }
+ }
+ }
+ }
+ }
+ else {
+ ldsym_type *sy = ldsym_get(tree->assign.dst);
+
+ /* If this symbol has just been created then we'll place it into
+ * a section of our choice
+ */
+ result = exp_fold_tree(tree->assign.src,
+ current_section, allocation_done,
+ dot, dotp);
+ if (result.valid)
+ {
+ asymbol *def;
+ asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+ /* Add this definition to script file */
+ def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
+ *def_ptr = def;
+
+
+ def->value = result.value;
+ if (result.section !=
+ (lang_output_section_statement_type *)NULL) {
+ if (current_section !=
+ (lang_output_section_statement_type *)NULL) {
+
+ def->section = result.section->bfd_section;
+ def->flags = BSF_GLOBAL | BSF_EXPORT;
+ }
+ else {
+ /* Force to absolute */
+ def->value += result.section->bfd_section->vma;
+ def->section = (asection *)NULL;
+ def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
+ }
+
+
+ }
+ else {
+ def->section = (asection *)NULL;
+ def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
+ }
+
+
+ def->udata = (void *)NULL;
+ def->name = sy->name;
+ Q_enter_global_ref(def_ptr);
+ }
+
+ }
+
+
+ break;
+ case etree_name:
+ result = fold_name(tree, current_section, allocation_done, dot);
+ break;
+ default:
+ info("%F%S Need more of these %d",tree->type.node_class );
+
+ }
+ }
+
+ return result;
+}
+
+
+etree_value_type exp_fold_tree_no_dot(tree, current_section, allocation_done)
+etree_type *tree;
+lang_output_section_statement_type *current_section;
+lang_phase_type allocation_done;
+{
+return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
+ 0, (bfd_vma *)NULL);
+}
+
+etree_type *
+exp_binop(code, lhs, rhs)
+int code;
+etree_type *lhs;
+etree_type *rhs;
+{
+ etree_type value, *new;
+ etree_value_type r;
+
+ value.type.node_code = code;
+ value.binary.lhs = lhs;
+ value.binary.rhs = rhs;
+ value.type.node_class = etree_binary;
+ r = exp_fold_tree_no_dot(&value, (lang_output_section_statement_type *)NULL,
+ lang_first_phase_enum );
+ if (r.valid)
+ {
+ return exp_intop(r.value);
+ }
+ new = (etree_type *)ldmalloc(sizeof(new->binary));
+ memcpy((char *)new, (char *)&value, sizeof(new->binary));
+ return new;
+}
+
+etree_type *
+exp_trinop(code, cond, lhs, rhs)
+int code;
+etree_type *cond;
+etree_type *lhs;
+etree_type *rhs;
+{
+ etree_type value, *new;
+ etree_value_type r;
+ value.type.node_code = code;
+ value.trinary.lhs = lhs;
+ value.trinary.cond = cond;
+ value.trinary.rhs = rhs;
+ value.type.node_class = etree_trinary;
+ r= exp_fold_tree_no_dot(&value, (lang_output_section_statement_type
+ *)NULL,lang_first_phase_enum);
+ if (r.valid) {
+ return exp_intop(r.value);
+ }
+ new = (etree_type *)ldmalloc(sizeof(new->trinary));
+ memcpy((char *)new,(char *) &value, sizeof(new->trinary));
+ return new;
+}
+
+
+etree_type *
+exp_unop(code, child)
+int code;
+etree_type *child;
+{
+ etree_type value, *new;
+
+ etree_value_type r;
+ value.unary.type.node_code = code;
+ value.unary.child = child;
+ value.unary.type.node_class = etree_unary;
+r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
+ lang_first_phase_enum);
+if (r.valid) {
+ return exp_intop(r.value);
+ }
+ new = (etree_type *)ldmalloc(sizeof(new->unary));
+ memcpy((char *)new, (char *)&value, sizeof(new->unary));
+ return new;
+}
+
+
+etree_type *
+exp_nameop(code, name)
+int code;
+char *name;
+{
+
+ etree_type value, *new;
+
+ etree_value_type r;
+ value.name.type.node_code = code;
+ value.name.name = name;
+ value.name.type.node_class = etree_name;
+
+
+ r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
+ lang_first_phase_enum);
+ if (r.valid) {
+ return exp_intop(r.value);
+ }
+ new = (etree_type *)ldmalloc(sizeof(new->name));
+ memcpy((char *)new, (char *)&value, sizeof(new->name));
+ return new;
+
+}
+
+
+
+
+etree_type *
+exp_assop(code, dst, src)
+int code;
+char *dst;
+etree_type *src;
+{
+ etree_type value, *new;
+
+ value.assign.type.node_code = code;
+
+
+ value.assign.src = src;
+ value.assign.dst = dst;
+ value.assign.type.node_class = etree_assign;
+
+#if 0
+ if (exp_fold_tree_no_dot(&value, &result)) {
+ return exp_intop(result);
+ }
+#endif
+ new = (etree_type*)ldmalloc(sizeof(new->assign));
+ memcpy((char *)new, (char *)&value, sizeof(new->assign));
+ return new;
+}
+
+void
+exp_print_tree(outfile, tree)
+FILE *outfile;
+etree_type *tree;
+{
+ switch (tree->type.node_class) {
+ case etree_value:
+ fprintf(outfile,"0x%08lx",(bfd_vma)(tree->value.value));
+ return;
+ case etree_assign:
+#if 0
+ if (tree->assign.dst->sdefs != (asymbol *)NULL){
+ fprintf(outfile,"%s (%x) ",tree->assign.dst->name,
+ tree->assign.dst->sdefs->value);
+ }
+ else {
+ fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name);
+ }
+#endif
+ fprintf(outfile,"%s ",tree->assign.dst);
+ exp_print_token(outfile,tree->type.node_code);
+ exp_print_tree(outfile,tree->assign.src);
+ break;
+ case etree_binary:
+ exp_print_tree(outfile,tree->binary.lhs);
+ exp_print_token(outfile,tree->type.node_code);
+ exp_print_tree(outfile,tree->binary.rhs);
+ break;
+ case etree_trinary:
+ exp_print_tree(outfile,tree->trinary.cond);
+ fprintf(outfile,"?");
+ exp_print_tree(outfile,tree->trinary.lhs);
+ fprintf(outfile,":");
+ exp_print_tree(outfile,tree->trinary.rhs);
+ break;
+ case etree_unary:
+ exp_print_token(outfile,tree->unary.type.node_code);
+ fprintf(outfile,"(");
+ exp_print_tree(outfile,tree->unary.child);
+ fprintf(outfile,")");
+ break;
+ case etree_undef:
+ fprintf(outfile,"????????");
+ break;
+ case etree_name:
+ if (tree->type.node_code == NAME) {
+ fprintf(outfile,"%s", tree->name.name);
+ }
+ else {
+ exp_print_token(outfile,tree->type.node_code);
+ fprintf(outfile,"(%s)", tree->name.name);
+ }
+ break;
+ default:
+ FAIL();
+ break;
+ }
+}
+
+
+
+
+bfd_vma
+exp_get_vma(tree, def, name, allocation_done)
+etree_type *tree;
+bfd_vma def;
+char *name;
+lang_phase_type allocation_done;
+{
+ etree_value_type r;
+
+ if (tree != (etree_type *)NULL) {
+ r = exp_fold_tree_no_dot(tree,
+ (lang_output_section_statement_type *)NULL,
+ allocation_done);
+ if (r.valid == false && name) {
+ info("%F%S Nonconstant expression for %s\n",name);
+ }
+ return r.value;
+ }
+ else {
+ return def;
+ }
+}
+
+int
+exp_get_value_int(tree,def,name, allocation_done)
+etree_type *tree;
+int def;
+char *name;
+lang_phase_type allocation_done;
+{
+ return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
+}
diff --git a/ld/ldexp.h b/ld/ldexp.h
new file mode 100644
index 0000000..f7e1321
--- /dev/null
+++ b/ld/ldexp.h
@@ -0,0 +1,99 @@
+/* ldexp.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+
+/* The result of an expression tree */
+typedef struct
+{
+ bfd_vma value;
+ struct lang_output_section_statement_struct *section;
+ boolean valid;
+} etree_value_type;
+
+
+
+typedef struct
+{
+ int node_code;
+ enum { etree_binary,
+ etree_trinary,
+ etree_unary,
+ etree_name,
+ etree_assign,
+ etree_undef,
+ etree_unspec,
+ etree_value } node_class;
+} node_type;
+
+
+
+typedef union etree_union
+{
+ node_type type;
+ struct {
+ node_type type;
+ union etree_union *lhs;
+ union etree_union *rhs;
+ } binary;
+ struct {
+ node_type type;
+ union etree_union *cond;
+ union etree_union *lhs;
+ union etree_union *rhs;
+ } trinary;
+ struct {
+ node_type type;
+ char *dst;
+ union etree_union *src;
+ } assign;
+
+ struct {
+ node_type type;
+ union etree_union *child;
+ } unary;
+ struct {
+ node_type type;
+ char *name;
+ } name;
+ struct {
+ node_type type;
+ bfd_vma value;
+ } value;
+
+} etree_type;
+
+
+PROTO(etree_type *,exp_intop,(bfd_vma));
+
+PROTO(etree_value_type, invalid,(void));
+PROTO(etree_value_type, exp_fold_tree,(etree_type *, struct
+ lang_output_section_statement_struct *, lang_phase_type,
+ bfd_vma, bfd_vma *));
+
+PROTO(etree_type *, exp_binop,(int, etree_type *, etree_type *));
+PROTO(etree_type *,exp_trinop,(int,etree_type *, etree_type *, etree_type *));
+PROTO(etree_type *,exp_unop,(int, etree_type *));
+PROTO(etree_type *,exp_nameop,(int, char *));
+PROTO(etree_type *,exp_assop,(int, char *, etree_type *));
+PROTO(void, exp_print_tree,(struct _iobuf *, etree_type *));
+PROTO(bfd_vma, exp_get_vma,(etree_type *, bfd_vma, char *, enum boolean));
+PROTO(int, exp_get_value_int,(etree_type *, int, char *, enum boolean));
diff --git a/ld/ldfile.c b/ld/ldfile.c
new file mode 100644
index 0000000..bc55f04
--- /dev/null
+++ b/ld/ldfile.c
@@ -0,0 +1,284 @@
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ $Id$
+
+ $Log$
+ Revision 1.1 1991/03/21 21:28:37 gumby
+ Initial revision
+
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:18 chrisb
+ * Initial revision
+ *
+ * Revision 1.4 1991/03/10 09:31:24 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3 1991/02/22 17:15:00 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ ldfile.c
+
+ look after all the file stuff
+
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ldmisc.h"
+#include "ldlang.h"
+#include "ldfile.h"
+
+#include <ctype.h>
+
+/* EXPORT */
+char *ldfile_input_filename;
+char *ldfile_output_machine_name;
+unsigned long ldfile_output_machine;
+enum bfd_architecture ldfile_output_architecture;
+boolean had_script;
+
+/* IMPORT */
+
+extern boolean option_v;
+
+
+
+
+
+/* LOACL */
+typedef struct search_dirs_struct
+{
+ char *name;
+ struct search_dirs_struct *next;
+} search_dirs_type;
+
+static search_dirs_type *search_head;
+static search_dirs_type **search_tail_ptr = &search_head;
+
+typedef struct search_arch_struct
+{
+ char *name;
+ struct search_arch_struct *next;
+} search_arch_type;
+
+static search_arch_type *search_arch_head;
+static search_arch_type **search_arch_tail_ptr = &search_arch_head;
+
+void
+ldfile_add_library_path(name)
+char *name;
+{
+ search_dirs_type *new =
+ (search_dirs_type *)ldmalloc(sizeof(search_dirs_type));
+ new->name = name;
+ new->next = (search_dirs_type*)NULL;
+ *search_tail_ptr = new;
+ search_tail_ptr = &new->next;
+}
+
+
+static bfd*
+cached_bfd_openr(attempt,entry)
+char *attempt;
+lang_input_statement_type *entry;
+{
+ entry->the_bfd = bfd_openr(attempt, entry->target);
+
+
+ return entry->the_bfd;
+}
+
+static bfd *
+open_a(arch, entry, lib, suffix)
+char *arch;
+lang_input_statement_type *entry;
+char *lib;
+char *suffix;
+{
+ bfd*desc;
+ search_dirs_type *search ;
+ for (search = search_head;
+ search != (search_dirs_type *)NULL;
+ search = search->next)
+ {
+ char buffer[1000];
+ char *string;
+ if (entry->is_archive == true) {
+ sprintf(buffer,
+ "%s/%s%s%s%s",
+ search->name,
+ lib,
+ entry->filename, arch, suffix);
+ }
+ else {
+ if (entry->filename[0] == '/') {
+ strcpy(buffer, entry->filename);
+ } else {
+ sprintf(buffer,"%s/%s",search->name, entry->filename);
+ } /* */
+ }
+ string = buystring(buffer);
+ desc = cached_bfd_openr (string, entry);
+ if (desc)
+ {
+ entry->filename = string;
+ entry->search_dirs_flag = false;
+ entry->the_bfd = desc;
+ return desc;
+ }
+ free(string);
+ }
+ return (bfd *)NULL;
+}
+
+/* Open the input file specified by 'entry', and return a descriptor.
+ The open file is remembered; if the same file is opened twice in a row,
+ a new open is not actually done. */
+
+void
+ldfile_open_file (entry)
+lang_input_statement_type *entry;
+{
+
+ if (entry->superfile)
+ ldfile_open_file (entry->superfile);
+
+ if (entry->search_dirs_flag)
+ {
+ search_arch_type *arch;
+ for (arch = search_arch_head;
+ arch != (search_arch_type *)NULL;
+ arch = arch->next) {
+ if (open_a(arch->name,entry,"","") != (bfd *)NULL) {
+ return;
+ }
+ if (open_a(arch->name,entry,"lib",".a") != (bfd *)NULL) {
+ return;
+ }
+
+ }
+
+
+ }
+ else {
+ entry->the_bfd = cached_bfd_openr (entry->filename, entry);
+
+ }
+ if (!entry->the_bfd) info("%F%P: %E %I\n", entry);
+
+}
+
+
+
+
+
+
+static FILE *
+try_open(name, exten)
+char *name;
+char *exten;
+{
+ FILE *result;
+ char buff[1000];
+ result = fopen(name, "r");
+ if (result && option_v == true) {
+ info("%s\n",name);
+ return result;
+ }
+ sprintf(buff, "%s%s", name, exten);
+ result = fopen(buff, "r");
+
+ if (result && option_v == true) {
+ info("%s\n", buff);
+ }
+ return result;
+}
+static FILE *
+find_a_name(name, extend)
+char *name;
+char *extend;
+{
+ search_dirs_type *search;
+ FILE *result;
+ char buffer[1000];
+ /* First try raw name */
+ result = try_open(name,"");
+ if (result == (FILE *)NULL) {
+ /* Try now prefixes */
+ for (search = search_head;
+ search != (search_dirs_type *)NULL;
+ search = search->next) {
+ sprintf(buffer,"%s/%s", search->name, name);
+ result = try_open(buffer, extend);
+ if (result)break;
+ }
+ }
+ return result;
+}
+
+void ldfile_open_command_file(name)
+char *name;
+{
+ extern FILE *ldlex_input_stack;
+ ldlex_input_stack = find_a_name(name, ".ld");
+
+ if (ldlex_input_stack == (FILE *)NULL) {
+ info("%P%F cannot open load script file %s\n",name);
+ }
+ ldfile_input_filename = name;
+ had_script = true;
+}
+
+
+
+
+void
+ldfile_add_arch(name)
+char *name;
+{
+ search_arch_type *new =
+ (search_arch_type *)ldmalloc(sizeof(search_arch_type));
+ ldfile_output_machine_name = name;
+
+ new->name = name;
+ new->next = (search_arch_type*)NULL;
+ while (*name) {
+ if (isupper(*name)) *name = tolower(*name);
+ name++;
+ }
+ *search_arch_tail_ptr = new;
+ search_arch_tail_ptr = &new->next;
+
+}
diff --git a/ld/ldfile.h b/ld/ldfile.h
new file mode 100644
index 0000000..876d47f
--- /dev/null
+++ b/ld/ldfile.h
@@ -0,0 +1,27 @@
+/* ldfile.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+PROTO(void,ldfile_add_arch,(char *));
+PROTO(void,ldfile_add_library_path,(char *));
+PROTO(void,ldfile_open_command_file,(char *name));
+PROTO(void,ldfile_open_file,(struct lang_input_statement_struct *));
+
diff --git a/ld/ldgram.y b/ld/ldgram.y
new file mode 100644
index 0000000..aa0f325
--- /dev/null
+++ b/ld/ldgram.y
@@ -0,0 +1,693 @@
+%{
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:41 gumby
+ * Initial revision
+ *
+ * Revision 1.2 1991/03/16 22:27:24 rich
+ * fish
+ *
+ * Revision 1.1 1991/03/13 00:48:21 chrisb
+ * Initial revision
+ *
+ * Revision 1.6 1991/03/10 09:31:26 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:25:48 sac
+ * Can now parse the -Ur flag
+ *
+ * Revision 1.4 1991/03/06 02:26:01 sac
+ * Added support for constructor sections.
+ * Remove parsing ambiguity.
+ * Lint
+ *
+ * Revision 1.3 1991/02/22 17:15:13 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ This is a YACC grammer intended to parse a superset of the AT&T
+ linker scripting languaue.
+
+
+ Written by Steve Chamberlain steve@cygnus.com
+*/
+
+
+/*SUPPRESS 166*/
+/*SUPPRESS 112*/
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldexp.h"
+#include "ldversion.h"
+#include "ldlang.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#define YYDEBUG 1
+
+boolean option_v;
+
+
+extern unsigned int lineno;
+extern boolean trace_files;
+extern boolean write_map;
+
+boolean hex_mode;
+
+
+
+
+lang_memory_region_type *region;
+
+
+lang_memory_region_type *lang_memory_region_lookup();
+lang_output_section_statement_type *lang_output_section_statement_lookup();
+
+#ifdef __STDC__
+
+void lang_add_data(int type, union etree_union *exp);
+void lang_enter_output_section_statement(char *output_section_statement_name, etree_type *address_exp, bfd_vma block_value);
+
+#else
+
+void lang_add_data();
+void lang_enter_output_section_statement();
+
+#endif /* __STDC__ */
+
+extern args_type command_line;
+char *current_file;
+boolean ldgram_want_filename = true;
+boolean had_script = false;
+boolean force_make_executable = false;
+boolean ldgram_mustbe_filename = false;
+boolean ldgram_mustbe_symbolname = false;
+boolean ldgram_has_inputfile = false;
+
+/* LOCALS */
+
+
+
+
+%}
+%union {
+ bfd_vma integer;
+ int voidval;
+ char *name;
+ int token;
+ union etree_union *etree;
+ asection *section;
+ struct lang_output_section_statement_struct *output_section_statement;
+ union lang_statement_union **statement_ptr;
+ int lineno;
+ struct {
+ FILE *file;
+ char *name;
+ unsigned int lineno;
+ } state;
+
+
+}
+
+%type <etree> exp opt_exp exp_head
+%type <integer> fill_opt opt_block
+%type <name> memspec_opt
+%token <integer> INT CHAR
+%token <name> NAME
+%type <integer> length
+
+%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
+%right <token> '?' ':'
+%left <token> OROR
+%left <token> ANDAND
+%left <token> '|'
+%left <token> '^'
+%left <token> '&'
+%left <token> EQ NE
+%left <token> '<' '>' LE GE
+%left <token> LSHIFT RSHIFT
+%left <token> '+' '-'
+%left <token> '*' '/' '%'
+%right UNARY
+%left <token> '('
+%token <token> ALIGN_K BLOCK LONG SHORT BYTE
+%token SECTIONS
+%token '{' '}'
+%token ALIGNMENT SIZEOF_HEADERS
+%token NEXT SIZEOF ADDR
+%token MEMORY
+%token DSECT NOLOAD COPY INFO OVERLAY
+%token NAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
+%token OPTION_e OPTION_c OPTION_noinhibit_exec OPTION_s OPTION_S OPTION_format
+%token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X
+%token OPTION_v OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT OPTION_defsym
+%token OPTION_n OPTION_r OPTION_o OPTION_b OPTION_A
+%token <name> OPTION_l OPTION_L OPTION_T OPTION_Aarch OPTION_Tfile OPTION_Texp
+%token OPTION_Ur
+%token ORIGIN FILL OPTION_g
+%token LENGTH BIND SUBSECTION_ALIGN CREATE_OBJECT_SYMBOLS INPUT OUTPUT
+%type <token> assign_op SIZEOF NEXT ADDR
+%type <etree> assignment
+%type <name> filename
+
+%{
+ld_config_type config;
+%}
+
+%%
+
+
+
+file: command_line { lang_final(); };
+
+
+filename:
+ {
+ ldgram_mustbe_filename =true;
+ }
+ NAME
+ {
+ ldgram_mustbe_filename = false;
+ $$ = $2;
+ }
+
+command_line:
+ command_line command_line_option
+ |
+ ;
+
+command_line_option:
+ OPTION_v
+ {
+ ldversion();
+ option_v = true;
+ }
+ | OPTION_t {
+ trace_files = true;
+ }
+ | OPTION_M {
+ write_map = true;
+ }
+ | OPTION_n {
+ config.magic_demand_paged = false;
+ config.make_executable = false;
+ }
+ | OPTION_s {
+ strip_symbols = STRIP_ALL;
+ }
+ | OPTION_S {
+ strip_symbols = STRIP_DEBUGGER;
+ }
+
+ | OPTION_r {
+ config.relocateable_output = true;
+ config.build_constructors = false;
+ config.magic_demand_paged = false;
+ }
+ | OPTION_Ur {
+ config.relocateable_output = true;
+ config.build_constructors = true;
+ config.magic_demand_paged = false;
+ }
+ | OPTION_o filename
+ {
+ lang_add_output($2);
+ }
+ | OPTION_e NAME
+ { lang_add_entry($2);
+ }
+ | OPTION_X {
+ discard_locals = DISCARD_L;
+ }
+ | OPTION_x {
+ discard_locals = DISCARD_ALL;
+ }
+
+ | OPTION_noinhibit_exec
+ {
+ force_make_executable = true;
+ }
+ | OPTION_d {
+ command_line.force_common_definition = true;
+ }
+ | OPTION_dc
+ {
+ command_line.force_common_definition = true;
+ }
+ | OPTION_g
+ {
+ /* Ignored */
+ }
+ | OPTION_dp
+ {
+ command_line.force_common_definition = true;
+ }
+ | OPTION_format NAME
+ {
+ lang_add_target($2);
+ }
+
+ | OPTION_Texp { hex_mode =true; }
+ exp_head
+ { lang_section_start($1, $3);
+ hex_mode = false; }
+
+ | OPTION_Aarch
+ { ldfile_add_arch($1); }
+ | OPTION_b NAME
+ {
+ lang_add_target($2);
+ }
+ | OPTION_L
+ {
+ ldfile_add_library_path($1);
+ }
+ | ifile_p1
+ | input_list
+ | OPTION_c filename
+ { ldfile_open_command_file($2); }
+ | OPTION_Tfile
+ { ldfile_open_command_file($1); }
+
+ | OPTION_T filename
+ { ldfile_open_command_file($2); }
+
+ | OPTION_l
+ {
+ lang_add_input_file($1,
+ lang_input_file_is_l_enum,
+ (char *)NULL);
+ }
+ | OPTION_A filename
+ {
+ lang_add_input_file($2,
+ lang_input_file_is_symbols_only_enum,
+ (char *)NULL);
+ }
+ | OPTION_defsym assignment_with_nospaces
+ ;
+
+
+input_section_spec:
+ NAME
+ {
+ lang_add_wild((char *)NULL, $1);
+ }
+ | '['
+ {
+ current_file = (char *)NULL;
+ }
+ file_NAME_list
+ ']'
+ | NAME
+ {
+ current_file =$1;
+ }
+ '(' file_NAME_list ')'
+ | '*'
+ {
+ current_file = (char *)NULL;
+ }
+ '(' file_NAME_list ')'
+ ;
+
+
+
+file_NAME_list:
+ NAME
+ { lang_add_wild($1, current_file); }
+ | file_NAME_list opt_comma NAME
+ { lang_add_wild($3, current_file); }
+ ;
+
+
+
+ifile_p1:
+ memory
+ | sections
+ | startup
+ | high_level_library
+ | low_level_library
+ | floating_point_support
+ | assignment end
+ | TARGET_K '(' NAME ')'
+ { lang_add_target($3); }
+ | SEARCH_DIR '(' filename ')'
+ { ldfile_add_library_path($3); }
+ | OUTPUT '(' filename ')'
+ { lang_add_output($3); }
+ | INPUT '(' input_list ')'
+ | MAP '(' filename ')'
+ { lang_add_map($3); }
+ ;
+
+input_list:
+ NAME
+ { lang_add_input_file($1,lang_input_file_is_file_enum,
+ (char *)NULL); }
+ | input_list ',' NAME
+ { lang_add_input_file($3,lang_input_file_is_file_enum,
+ (char *)NULL); }
+ | input_list NAME
+ { lang_add_input_file($2, lang_input_file_is_file_enum,
+ (char *)NULL); }
+ ;
+
+sections:
+ SECTIONS '{'sec_or_group_p1 '}'
+ ;
+
+sec_or_group_p1:
+ sec_or_group_p1 section
+ | sec_or_group_p1 statement_anywhere
+ |
+ ;
+
+statement_anywhere:
+ ENTRY '(' NAME ')'
+ { lang_add_entry($3); }
+ | assignment end
+ ;
+
+statement:
+ statement assignment end
+ | statement CREATE_OBJECT_SYMBOLS
+ { lang_add_attribute(lang_object_symbols_statement_enum); }
+ | statement input_section_spec
+ | statement length '(' exp_head ')'
+ {
+ lang_add_data($2,$4);
+ }
+
+ | statement FILL '(' exp_head ')'
+ {
+ lang_add_fill
+ (exp_get_value_int($4,
+ 0,
+ "fill value",
+ lang_first_phase_enum));
+ }
+ |
+ ;
+
+length:
+ LONG
+ { $$ = $1; }
+ | SHORT
+ { $$ = $1; }
+ | BYTE
+ { $$ = $1; }
+ ;
+
+fill_opt:
+ '=' exp_head
+ {
+ $$ = exp_get_value_int($2,
+ 0,
+ "fill value",
+ lang_first_phase_enum);
+ }
+ | { $$ = 0; }
+ ;
+
+
+
+assign_op:
+ PLUSEQ
+ { $$ = '+'; }
+ | MINUSEQ
+ { $$ = '-'; }
+ | MULTEQ
+ { $$ = '*'; }
+ | DIVEQ
+ { $$ = '/'; }
+ | LSHIFTEQ
+ { $$ = LSHIFT; }
+ | RSHIFTEQ
+ { $$ = RSHIFT; }
+ | ANDEQ
+ { $$ = '&'; }
+ | OREQ
+ { $$ = '|'; }
+
+ ;
+
+end: ';' | ','
+ ;
+
+assignment_with_nospaces:
+ { ldgram_want_filename = false; }
+ assignment
+ { ldgram_want_filename = true; }
+ ;
+
+assignment:
+
+ NAME '=' exp_head
+ {
+ lang_add_assignment(exp_assop($2,$1,$3));
+ }
+ | NAME assign_op exp_head
+ {
+ lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3)));
+ }
+
+ ;
+
+
+opt_comma:
+ ',' | ;
+
+
+memory:
+ MEMORY '{' memory_spec memory_spec_list '}'
+ ;
+
+memory_spec_list:
+ memory_spec_list memory_spec
+ | memory_spec_list ',' memory_spec
+ |
+ ;
+
+
+memory_spec:
+ NAME
+ { region = lang_memory_region_lookup($1); }
+ attributes_opt ':' origin_spec opt_comma length_spec
+
+ {
+
+
+ }
+ ;
+origin_spec:
+ ORIGIN '=' exp
+ { region->current =
+ region->origin =
+ exp_get_vma($3, 0L,"origin", lang_first_phase_enum); }
+ ;
+length_spec:
+ LENGTH '=' exp
+ { region->length = exp_get_vma($3,
+ ~((bfd_vma)0),
+ "length",
+ lang_first_phase_enum);
+ }
+
+
+attributes_opt:
+ '(' NAME ')'
+ {
+ lang_set_flags(&region->flags, $2);
+ }
+ |
+
+ ;
+
+startup:
+ STARTUP '(' filename ')'
+ { lang_startup($3); }
+ ;
+
+high_level_library:
+ HLL '(' high_level_library_NAME_list ')'
+ | HLL '(' ')'
+ { ldemul_hll((char *)NULL); }
+ ;
+
+high_level_library_NAME_list:
+ high_level_library_NAME_list opt_comma filename
+ { ldemul_hll($3); }
+ | filename
+ { ldemul_hll($1); }
+
+ ;
+
+low_level_library:
+ SYSLIB '(' low_level_library_NAME_list ')'
+ ;
+low_level_library_NAME_list:
+ low_level_library_NAME_list opt_comma filename
+ { ldemul_syslib($3); }
+ |
+ ;
+
+floating_point_support:
+ FLOAT
+ { lang_float(true); }
+ | NOFLOAT
+ { lang_float(false); }
+ ;
+
+
+
+
+exp :
+ '-' exp %prec UNARY
+ { $$ = exp_unop('-', $2); }
+ | '(' exp ')'
+ { $$ = $2; }
+ | NEXT '(' exp ')' %prec UNARY
+ { $$ = exp_unop($1,$3); }
+ | '!' exp %prec UNARY
+ { $$ = exp_unop('!', $2); }
+ | '+' exp %prec UNARY
+ { $$ = $2; }
+ | '~' exp %prec UNARY
+ { $$ = exp_unop('~', $2);}
+
+ | exp '*' exp
+ { $$ = exp_binop('*', $1, $3); }
+ | exp '/' exp
+ { $$ = exp_binop('/', $1, $3); }
+ | exp '%' exp
+ { $$ = exp_binop('%', $1, $3); }
+ | exp '+' exp
+ { $$ = exp_binop('+', $1, $3); }
+ | exp '-' exp
+ { $$ = exp_binop('-' , $1, $3); }
+ | exp LSHIFT exp
+ { $$ = exp_binop(LSHIFT , $1, $3); }
+ | exp RSHIFT exp
+ { $$ = exp_binop(RSHIFT , $1, $3); }
+ | exp EQ exp
+ { $$ = exp_binop(EQ , $1, $3); }
+ | exp NE exp
+ { $$ = exp_binop(NE , $1, $3); }
+ | exp LE exp
+ { $$ = exp_binop(LE , $1, $3); }
+ | exp GE exp
+ { $$ = exp_binop(GE , $1, $3); }
+ | exp '<' exp
+ { $$ = exp_binop('<' , $1, $3); }
+ | exp '>' exp
+ { $$ = exp_binop('>' , $1, $3); }
+ | exp '&' exp
+ { $$ = exp_binop('&' , $1, $3); }
+ | exp '^' exp
+ { $$ = exp_binop('^' , $1, $3); }
+ | exp '|' exp
+ { $$ = exp_binop('|' , $1, $3); }
+ | exp '?' exp ':' exp
+ { $$ = exp_trinop('?' , $1, $3, $5); }
+ | exp ANDAND exp
+ { $$ = exp_binop(ANDAND , $1, $3); }
+ | exp OROR exp
+ { $$ = exp_binop(OROR , $1, $3); }
+ | DEFINED '(' NAME ')'
+ { $$ = exp_nameop(DEFINED, $3); }
+ | INT
+ { $$ = exp_intop($1); }
+
+ | SIZEOF '(' NAME ')'
+ { $$ = exp_nameop($1,$3); }
+ | ADDR '(' NAME ')'
+ { $$ = exp_nameop($1,$3); }
+ | ALIGN_K '(' exp ')'
+ { $$ = exp_unop($1,$3); }
+ | NAME
+ { $$ = exp_nameop(NAME,$1); }
+ ;
+
+
+
+
+section: NAME opt_exp opt_block ':' opt_things'{'
+ {
+ lang_enter_output_section_statement($1,$2,$3);
+ }
+ statement '}' fill_opt memspec_opt
+ {
+ lang_leave_output_section_statement($10, $11);
+ }
+
+ ;
+
+opt_things:
+ {
+
+ }
+ ;
+
+exp_head:
+ { ldgram_mustbe_symbolname = true; }
+ exp
+ { ldgram_mustbe_symbolname = false;
+ $$ = $2;
+ }
+
+opt_exp:
+ exp
+ { $$ = $1; }
+ | { $$= (etree_type *)NULL; }
+ ;
+
+opt_block:
+ BLOCK '(' exp_head ')'
+ { $$ = exp_get_value_int($3,
+ 1L,
+ "block",
+ lang_first_phase_enum);
+ }
+ | { $$ = 1; }
+ ;
+
+memspec_opt:
+ '>' NAME
+ { $$ = $2; }
+ | { $$ = "*default*"; }
+ ;
+
diff --git a/ld/ldlang.c b/ld/ldlang.c
new file mode 100644
index 0000000..1fccbc2
--- /dev/null
+++ b/ld/ldlang.c
@@ -0,0 +1,2231 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:45 gumby
+ * Initial revision
+ *
+ * Revision 1.3 1991/03/16 22:19:21 rich
+ * pop
+ *
+ * Revision 1.2 1991/03/15 18:52:42 rich
+ * pop
+ *
+ * Revision 1.1 1991/03/13 00:48:23 chrisb
+ * Initial revision
+ *
+ * Revision 1.8 1991/03/10 09:31:28 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.7 1991/03/09 03:31:03 sac
+ * After a fatal info message, the output file is deleted.
+ *
+ * Revision 1.6 1991/03/09 03:25:06 sac
+ * Added support for LONG, SHORT and BYTE keywords in scripts
+ *
+ * Revision 1.5 1991/03/06 21:59:31 sac
+ * Completed G++ support
+ *
+ * Revision 1.4 1991/03/06 02:26:02 sac
+ * Added support for constructor sections.
+ * Remove parsing ambiguity.
+ * Lint
+ *
+ * Revision 1.3 1991/02/22 17:15:01 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldsym.h"
+#include "ldgram.tab.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+#include "ldexp.h"
+#include "ld-emul.h"
+#include "ldlex.h"
+
+/* EXPORTS */
+
+
+
+extern unsigned int undefined_global_sym_count;
+
+static char *startup_file;
+static lang_input_statement_type *first_file;
+lang_statement_list_type statement_list;
+lang_statement_list_type *stat_ptr = &statement_list;
+lang_statement_list_type lang_output_section_statement;
+lang_statement_list_type input_file_chain;
+lang_statement_list_type file_chain;
+extern char *current_file;
+static boolean placed_commons = false;
+
+boolean lang_float_flag;
+
+static lang_output_section_statement_type *default_common_section;
+
+
+/* FORWARDS */
+PROTO(static void, print_statements,(void));
+PROTO(static void, print_statement,(lang_statement_union_type *,
+ lang_output_section_statement_type *));
+
+
+
+/* EXPORTS */
+boolean lang_has_input_file = false;
+
+
+extern bfd *output_bfd;
+size_t largest_section;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+
+extern ldsym_type *symbol_head;
+
+bfd_vma print_dot;
+unsigned int commons_pending;
+
+
+
+
+extern args_type command_line;
+extern ld_config_type config;
+
+char *entry_symbol;
+
+
+
+lang_output_section_statement_type *create_object_symbols;
+
+extern boolean had_script;
+static boolean map_option_f;
+
+
+boolean had_output_filename = false;
+extern boolean write_map;
+
+
+
+
+
+
+size_t longest_section_name = 8;
+
+
+lang_input_statement_type *script_file;
+
+section_userdata_type common_section_userdata;
+asection common_section;
+
+#ifdef __STDC__
+#define cat(a,b) a##b
+#else
+#define cat(a,b) a/**/b
+#endif
+
+#define new_stat(x,y) (cat(x,_type)*) new_statement(cat(x,_enum), sizeof(cat(x,_type)),y)
+
+#define outside_section_address(q) ( (q)->output_offset + (q)->output_section->vma)
+
+#define outside_symbol_address(q) ((q)->value + outside_section_address(q->section))
+
+boolean option_longmap = false;
+
+static void lang_list_init(list)
+lang_statement_list_type *list;
+{
+list->head = (lang_statement_union_type *)NULL;
+list->tail = &list->head;
+}
+
+static void
+print_section(name)
+char *name;
+{
+ printf("%*s", -longest_section_name, name);
+}
+static void
+print_space()
+{
+ printf(" ");
+}
+static void
+print_nl()
+{
+ printf("\n");
+}
+static void
+print_address(value)
+bfd_vma value;
+{
+ printf("%8lx", value);
+}
+static void
+print_size(value)
+size_t value;
+{
+ printf("%5x", (unsigned)value);
+}
+static void
+print_alignment(value)
+unsigned int value;
+{
+ printf("2**%2u",value);
+}
+static void
+print_fill(value)
+fill_type value;
+{
+ printf("%04x",(unsigned)value);
+}
+
+
+static
+lang_statement_union_type *new_statement(type, size, list)
+enum statement_enum type;
+size_t size;
+lang_statement_list_type *list;
+{
+ lang_statement_union_type *new = (lang_statement_union_type *)
+ ldmalloc(size);
+ new->header.type = type;
+ new->header.next = (lang_statement_union_type *)NULL;
+ lang_statement_append(list, new, &new->header.next);
+ return new;
+}
+
+static lang_input_statement_type *
+new_afile(name, file_type, target)
+char *name;
+lang_input_file_enum_type file_type;
+char *target;
+{
+ lang_input_statement_type *p = new_stat(lang_input_statement,
+ stat_ptr);
+ lang_has_input_file = true;
+ p->target = target;
+ switch (file_type) {
+ case lang_input_file_is_symbols_only_enum:
+ p->filename = name;
+ p->is_archive =false;
+ p->real = true;
+ p->local_sym_name= name;
+ p->just_syms_flag = true;
+ p->search_dirs_flag = false;
+ break;
+ case lang_input_file_is_fake_enum:
+ p->filename = name;
+ p->is_archive =false;
+ p->real = false;
+ p->local_sym_name= name;
+ p->just_syms_flag = false;
+ p->search_dirs_flag =false;
+
+ break;
+ case lang_input_file_is_l_enum:
+ p->is_archive = true;
+ p->filename = name;
+ p->real = true;
+ p->local_sym_name = concat("-l",name,"");
+ p->just_syms_flag = false;
+ p->search_dirs_flag = true;
+ break;
+
+ case lang_input_file_is_search_file_enum:
+ case lang_input_file_is_marker_enum:
+ p->filename = name;
+ p->is_archive =false;
+ p->real = true;
+ p->local_sym_name= name;
+ p->just_syms_flag = false;
+ p->search_dirs_flag =true;
+ break;
+
+
+
+ case lang_input_file_is_file_enum:
+ p->filename = name;
+ p->is_archive =false;
+ p->real = true;
+ p->local_sym_name= name;
+ p->just_syms_flag = false;
+ p->search_dirs_flag =false;
+ break;
+
+
+ default:
+ FAIL();
+ }
+ p->asymbols = (asymbol **)NULL;
+ p->superfile = (lang_input_statement_type *)NULL;
+
+ p->next_real_file = (lang_statement_union_type*)NULL;
+ p->next = (lang_statement_union_type*)NULL;
+ p->symbol_count = 0;
+ p->common_output_section = (asection *)NULL;
+
+ lang_statement_append(&input_file_chain,
+ (lang_statement_union_type *)p,
+ &p->next_real_file);
+ return p;
+}
+
+lang_input_statement_type *
+lang_add_input_file(name,
+ file_type,
+ target)
+char *name;
+lang_input_file_enum_type file_type;
+char *target;
+{
+ /* Look it up or build a new one */
+
+ lang_input_statement_type *p;
+
+ for (p = (lang_input_statement_type *)input_file_chain.head;
+ p != (lang_input_statement_type *)NULL;
+ p = (lang_input_statement_type *)(p->next_real_file))
+ {
+ /* Sometimes we have incomplete entries in here */
+ if (p->filename != (char *)NULL) {
+ if(strcmp(name,p->filename) == 0) return p;
+ }
+ }
+
+ return new_afile(name, file_type, target);
+}
+
+
+
+void
+lang_init()
+{
+
+ stat_ptr= &statement_list;
+ lang_list_init(stat_ptr);
+
+ lang_list_init(&input_file_chain);
+ lang_list_init(&lang_output_section_statement);
+ lang_list_init(&file_chain);
+ first_file = lang_add_input_file((char *)NULL,
+ lang_input_file_is_marker_enum,
+ (char *)NULL);
+
+}
+
+static void
+lang_init2()
+{
+ script_file = lang_add_input_file("script file",
+ lang_input_file_is_fake_enum,
+ (char *)NULL);
+ script_file->the_bfd = bfd_create("script file", output_bfd);
+ script_file->symbol_count = 0;
+
+ common_section.userdata = &common_section_userdata;
+
+}
+
+
+
+/* this function mainains a dictionary of regions. If the *default*
+ region is asked for then a pointer to the first region is
+ returned. If there is no first pointer then one is created
+*/
+
+static lang_memory_region_type *lang_memory_region_list;
+static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;
+
+lang_memory_region_type *
+lang_memory_region_lookup(name)
+char *name;
+{
+
+ lang_memory_region_type *p = lang_memory_region_list;
+ for (p = lang_memory_region_list;
+ p != ( lang_memory_region_type *)NULL;
+ p = p->next) {
+ if (strcmp(p->name, name) == 0) {
+ return p;
+ }
+ }
+ if (strcmp(name,"*default*")==0) {
+ /* This is the default region, dig out first one on the list */
+ if (lang_memory_region_list != (lang_memory_region_type*)NULL){
+ return lang_memory_region_list;
+ }
+ }
+ {
+ lang_memory_region_type *new =
+ (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type));
+ new->name = name;
+ new->next = (lang_memory_region_type *)NULL;
+
+ *lang_memory_region_list_tail = new;
+ lang_memory_region_list_tail = &new->next;
+ new->origin = 0;
+ new->length = ~0;
+ new->current = 0;
+ return new;
+ }
+}
+
+
+
+lang_output_section_statement_type *
+lang_output_section_find(name)
+char *name;
+{
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+
+ for (u = lang_output_section_statement.head;
+ u != (lang_statement_union_type *)NULL;
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+ if (strcmp(name, lookup->name)==0) {
+ return lookup;
+ }
+ }
+ return (lang_output_section_statement_type *)NULL;
+}
+
+lang_output_section_statement_type *
+lang_output_section_statement_lookup(name)
+char *name;
+
+{
+ lang_output_section_statement_type *lookup;
+ lookup =lang_output_section_find(name);
+ if (lookup == (lang_output_section_statement_type *)NULL) {
+
+ lookup =(lang_output_section_statement_type *)
+ new_stat(lang_output_section_statement, stat_ptr);
+ lookup->region = (lang_memory_region_type *)NULL;
+ lookup->fill = 0;
+ lookup->block_value = 1;
+ lookup->name = name;
+
+ lookup->next = (lang_statement_union_type*)NULL;
+ lookup->bfd_section = (asection *)NULL;
+ lookup->processed = false;
+ lookup->addr_tree = (etree_type *)NULL;
+ lang_list_init(&lookup->children);
+
+ lang_statement_append(&lang_output_section_statement,
+ (lang_statement_union_type *)lookup,
+ &lookup->next);
+ }
+ return lookup;
+}
+
+
+
+
+
+static void
+ print_flags(outfile, ignore_flags)
+FILE *outfile;
+lang_section_flags_type *ignore_flags;
+{
+ fprintf(outfile,"(");
+#if 0
+ if (flags->flag_read) fprintf(outfile,"R");
+ if (flags->flag_write) fprintf(outfile,"W");
+ if (flags->flag_executable) fprintf(outfile,"X");
+ if (flags->flag_loadable) fprintf(outfile,"L");
+#endif
+ fprintf(outfile,")");
+}
+
+void
+lang_map(outfile)
+ FILE *outfile;
+{
+ lang_memory_region_type *m;
+ fprintf(outfile,"**MEMORY CONFIGURATION**\n\n");
+
+ fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n");
+ for (m = lang_memory_region_list;
+ m != (lang_memory_region_type *)NULL;
+ m = m->next)
+ {
+ fprintf(outfile,"%-16s", m->name);
+
+ fprintf(outfile,"%08lx\t%08lx\t", m->origin, m->length);
+ print_flags(outfile, &m->flags);
+ fprintf(outfile,"\n");
+ }
+ fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n");
+ fprintf(outfile,"output\t\tinput\t\tvirtual\n");
+ fprintf(outfile,"section\t\tsection\t\taddress\tsize\n\n");
+
+ print_statements();
+
+}
+
+/*
+ *
+ */
+static void init_os(s)
+lang_output_section_statement_type *s;
+{
+ section_userdata_type *new =
+ (section_userdata_type *)
+ ldmalloc(sizeof(section_userdata_type));
+
+ s->bfd_section = bfd_make_section(output_bfd, s->name);
+ s->bfd_section->output_section = s->bfd_section;
+ s->bfd_section->flags = SEC_NO_FLAGS;
+ /* We initialize an output sections output offset to minus its own */
+ /* vma to allow us to output a section through itself */
+ s->bfd_section->output_offset = 0;
+ get_userdata( s->bfd_section) = new;
+}
+
+static void
+wild_doit(ptr, section,output, file)
+lang_statement_list_type *ptr;
+asection *section;
+lang_output_section_statement_type *output;
+lang_input_statement_type *file;
+{
+ if(output->bfd_section == (asection *)NULL)
+ {
+ init_os(output);
+ }
+
+ if (section != (asection *)NULL
+ && section->output_section == (asection *)NULL) {
+ /* Add a section reference to the list */
+ lang_input_section_type *new = new_stat(lang_input_section, ptr);
+
+ new->section = section;
+ new->ifile = file;
+ section->output_section = output->bfd_section;
+ section->output_section->flags |= section->flags;
+ if (section->alignment_power > output->bfd_section->alignment_power) {
+ output->bfd_section->alignment_power = section->alignment_power;
+ }
+
+ }
+}
+
+static asection *
+our_bfd_get_section_by_name(abfd, section)
+bfd *abfd;
+char *section;
+{
+ return bfd_get_section_by_name(abfd, section);
+
+}
+static void
+wild_section(ptr, section, file , output)
+lang_wild_statement_type *ptr;
+char *section;
+lang_input_statement_type *file;
+lang_output_section_statement_type *output;
+{
+ asection *s;
+ if (section == (char *)NULL) {
+ /* Do the creation to all sections in the file */
+ for (s = file->the_bfd->sections; s != (asection *)NULL; s=s->next) {
+ wild_doit(&ptr->children, s, output, file);
+ }
+ }
+ else {
+ /* Do the creation to the named section only */
+ wild_doit(&ptr->children,
+ our_bfd_get_section_by_name(file->the_bfd, section),
+ output, file);
+ }
+
+
+
+}
+
+
+
+static
+lang_input_statement_type *lookup_name(name, target)
+char *name;
+char *target;
+{
+ lang_input_statement_type *search;
+ for(search = (lang_input_statement_type *)input_file_chain.head;
+ search != (lang_input_statement_type *)NULL;
+ search = (lang_input_statement_type *)search->next_real_file)
+ {
+ if (search->filename == (char *)NULL && name == (char *)NULL) {
+ return search;
+ }
+ if (search->filename != (char *)NULL && name != (char *)NULL) {
+ if (strcmp(search->filename, name) == 0) {
+ Q_read_file_symbols(search);
+ return search;
+ }
+ }
+ }
+
+ /* There isn't an afile entry for this file yet, this must be */
+ /* because the name has only appeared inside a load script and not */
+ /* on the command line */
+ search = new_afile(name, lang_input_file_is_file_enum, target);
+ Q_read_file_symbols(search);
+ return search;
+}
+
+static void
+
+wild(s, section, file, target, output)
+lang_wild_statement_type *s;
+char *section;
+char *file;
+char *target;
+lang_output_section_statement_type *output;
+{
+ lang_input_statement_type *f;
+ if (file == (char *)NULL) {
+ /* Perform the iteration over all files in the list */
+ for (f = (lang_input_statement_type *)file_chain.head;
+ f != (lang_input_statement_type *)NULL;
+ f = (lang_input_statement_type *)f->next) {
+ wild_section(s, section, f, output);
+ }
+ }
+ else {
+ /* Perform the iteration over a single file */
+ wild_section( s, section, lookup_name(file, target), output);
+ }
+}
+
+/*
+ read in all the files
+ */
+static bfd *
+open_output(name, target)
+char *name;
+char *target;
+{
+ extern char *output_filename;
+ bfd * output = bfd_openw(name, target);
+ output_filename = name;
+ if (output == (bfd *)NULL)
+ {
+ if (bfd_error == invalid_target) {
+ info("%P%F target %s not found\n", target);
+ }
+ info("%P%F problem opening output file %s, %E", name);
+ }
+
+ output->flags |= D_PAGED;
+ bfd_set_format(output, bfd_object);
+ return output;
+}
+extern char *default_target;
+static void
+lang_phase_0(sh,target)
+lang_statement_union_type *sh;
+char *target;
+{
+ lang_statement_union_type *s = (lang_statement_union_type *)sh;
+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
+ {
+ switch (s->header.type) {
+ case lang_output_section_statement_enum:
+ lang_phase_0(s->output_section_statement.children.head,
+ target);
+ break;
+ case lang_output_statement_enum:
+#if 1
+ output_bfd = open_output(s->output_statement.name,
+ target == (char *)NULL ?
+ default_target : target);
+ ldemul_set_output_arch();
+#endif
+ break;
+ case lang_target_statement_enum:
+ target = s->target_statement.target;
+ break;
+ case lang_wild_statement_enum:
+ /* Maybe we should load the file's symbols */
+ if (s->wild_statement.filename) {
+ (void) lookup_name(s->wild_statement.filename, target);
+ }
+ break;
+ /* Attatch this to the current output section */
+ case lang_common_statement_enum:
+ case lang_fill_statement_enum:
+ case lang_input_section_enum:
+ case lang_object_symbols_statement_enum:
+ case lang_address_statement_enum:
+ case lang_data_statement_enum:
+ break;
+ case lang_afile_asection_pair_statement_enum:
+
+ FAIL();
+ break;
+
+ case lang_input_statement_enum:
+ if (s->input_statement.real == true) {
+ s->input_statement.target = target;
+ lookup_name(s->input_statement.filename, target);
+ }
+ break;
+ case lang_assignment_statement_enum:
+#if 0
+ (void) exp_fold_tree(s->assignment_statement.exp,
+ output_section,
+ false);
+#endif
+ break;
+
+ case lang_padding_statement_enum:
+
+ break;
+ }
+ }
+
+}
+
+/* If there are [COMMONS] statements, put a wild one into the bss section */
+
+static void
+lang_reasonable_defaults()
+{
+ default_common_section =
+ lang_output_section_statement_lookup(".bss");
+ if (placed_commons == false) {
+ lang_wild_statement_type *new =
+ new_stat(lang_wild_statement,
+ &default_common_section->children);
+ new->section_name = "COMMON";
+ new->filename = (char *)NULL;
+ lang_list_init(&new->children);
+ }
+}
+
+static void lang()
+{
+ if (had_script == false) {
+ parse_line(ldemul_get_script());
+ }
+
+ lang_reasonable_defaults();
+ lang_phase_0(statement_list.head,default_target);
+}
+
+
+/* Open input files and attatch to output sections */
+static void
+lang_open_input(s, target, output_section_statement)
+lang_statement_union_type *s;
+char *target;
+lang_output_section_statement_type *output_section_statement;
+{
+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
+ {
+ switch (s->header.type) {
+ case lang_wild_statement_enum:
+ wild(&s->wild_statement, s->wild_statement.section_name,
+ s->wild_statement.filename, target,
+ output_section_statement);
+
+ break;
+
+ case lang_output_section_statement_enum:
+ lang_open_input(s->output_section_statement.children.head,
+ target,
+ &s->output_section_statement);
+ break;
+ case lang_output_statement_enum:
+ break;
+ case lang_target_statement_enum:
+ target = s->target_statement.target;
+ break;
+ case lang_common_statement_enum:
+ case lang_fill_statement_enum:
+ case lang_input_section_enum:
+ case lang_object_symbols_statement_enum:
+ case lang_data_statement_enum:
+ break;
+ case lang_afile_asection_pair_statement_enum:
+ FAIL();
+ break;
+
+ case lang_assignment_statement_enum:
+ case lang_padding_statement_enum:
+
+ break;
+ case lang_address_statement_enum:
+ /* Mark the specified section with the supplied address */
+ {
+ lang_output_section_statement_type *os =
+ lang_output_section_statement_lookup
+ (s->address_statement.section_name);
+ os->addr_tree = s->address_statement.address;
+ }
+ break;
+ case lang_input_statement_enum:
+ /* A standard input statement, has no wildcards */
+ /* Q_read_file_symbols(&s->input_statement);*/
+ break;
+ }
+ }
+}
+
+
+
+
+
+static void
+print_output_section_statement(output_section_statement)
+lang_output_section_statement_type *output_section_statement;
+{
+ asection *section = output_section_statement->bfd_section;
+ print_nl();
+ print_section(output_section_statement->name);
+
+ if (section) {
+ print_dot = section->vma;
+ print_space();
+ print_section("");
+ print_space();
+ print_address(section->vma);
+ print_space();
+ print_size(section->size);
+ print_space();
+ print_alignment(section->alignment_power);
+ print_space();
+#if 0
+ printf("%s flags", output_section_statement->region->name);
+ print_flags(stdout, &output_section_statement->flags);
+#endif
+
+ }
+ else {
+ printf("No attached output section");
+ }
+ print_nl();
+ print_statement(output_section_statement->children.head,
+ output_section_statement);
+
+}
+
+static void
+print_assignment(assignment, output_section)
+lang_assignment_statement_type *assignment;
+lang_output_section_statement_type *output_section;
+{
+ etree_value_type result;
+ print_section("");
+ print_space();
+ print_section("");
+ print_space();
+ print_address(print_dot);
+ print_space();
+ result = exp_fold_tree(assignment->exp->assign.src,
+ output_section,
+ lang_final_phase_enum,
+ print_dot,
+ &print_dot);
+
+ if (result.valid) {
+ print_address(result.value);
+ }
+ else
+ {
+ printf("*undefined*");
+ }
+ print_space();
+ exp_print_tree(stdout, assignment->exp);
+ printf("\n");
+}
+
+static void
+print_input_statement(statm)
+lang_input_statement_type *statm;
+{
+ printf("LOAD %s\n",statm->filename);
+}
+
+static void print_symbol(q)
+asymbol *q;
+{
+ print_section("");
+ printf(" ");
+ print_section("");
+ printf(" ");
+ print_address(outside_symbol_address(q));
+ printf(" %s", q->name ? q->name : " ");
+ print_nl();
+}
+static void
+print_input_section(in)
+lang_input_section_type *in;
+{
+ asection *i = in->section;
+
+ if(i->size != 0) {
+ print_section("");
+ printf(" ");
+ print_section(i->name);
+ printf(" ");
+ if (i->output_section) {
+ print_address(i->output_section->vma + i->output_offset);
+ printf(" ");
+ print_size(i->size);
+ printf(" ");
+ print_alignment(i->alignment_power);
+ printf(" ");
+ if (in->ifile) {
+ bfd *abfd = in->ifile->the_bfd;
+ printf(" %s ",abfd->xvec->name);
+ if(abfd->my_archive != (bfd *)NULL) {
+ printf("[%s]%s", abfd->my_archive->filename,
+ abfd->filename);
+ }
+ else {
+ printf("%s", abfd->filename);
+ }
+ print_nl();
+
+ /* Find all the symbols in this file defined in this section */
+ {
+ asymbol **p;
+ for (p = in->ifile->asymbols; *p; p++) {
+ asymbol *q = *p;
+
+ if (bfd_get_section(q) == i && q->flags & BSF_GLOBAL) {
+ print_symbol(q);
+ }
+ }
+ }
+ }
+ else {
+ print_nl();
+ }
+
+
+ print_dot = outside_section_address(i) + i->size;
+ }
+ else {
+ printf("No output section allocated\n");
+ }
+ }
+}
+static void
+print_common_statement()
+{
+ ldsym_type *lgs;
+ print_section("");
+ print_space();
+ print_section(common_section.output_section->name);
+ print_space();
+ print_address(common_section.output_offset +
+ common_section.output_section->vma);
+ print_space();
+ print_size(common_section.size);
+ print_space();
+ printf("(common)");
+ print_nl();
+ /* Print out all the global symbols */
+
+
+ for (lgs = symbol_head; lgs != (ldsym_type *)NULL; lgs =
+ lgs->next) {
+ if (lgs->sdefs_chain) {
+ asymbol *def = *(lgs->sdefs_chain);
+ if (def->section == &common_section) {
+ print_symbol(def);
+ }
+ }
+
+ }
+ print_dot = common_section.output_offset +
+ common_section.output_section->vma + common_section.size;
+
+
+}
+static void
+print_fill_statement(fill)
+lang_fill_statement_type *fill;
+{
+ printf("FILL mask ");
+ print_fill( fill->fill);
+}
+
+static void
+print_data_statement(data)
+lang_data_statement_type *data;
+{
+/* bfd_vma value; */
+ print_section("");
+ print_space();
+ print_section("");
+ print_space();
+ ASSERT(print_dot == data->output_vma);
+
+ print_address(data->output_vma);
+ print_space();
+ print_address(data->value);
+ print_space();
+ switch (data->type) {
+ case BYTE :
+ printf("BYTE ");
+ print_dot += BYTE_SIZE;
+ break;
+ case SHORT:
+ printf("SHORT ");
+ print_dot += SHORT_SIZE;
+ break;
+ case LONG:
+ printf("LONG ");
+ print_dot += LONG_SIZE;
+ break;
+ }
+
+ exp_print_tree(stdout, data->exp);
+
+ printf("\n");
+}
+
+
+static void
+print_padding_statement(s)
+lang_padding_statement_type *s;
+{
+ print_section("");
+ print_space();
+ print_section("*fill*");
+ print_space();
+ print_address(s->output_offset + s->output_section->vma);
+ print_space();
+ print_size(s->size);
+ print_space();
+ print_fill(s->fill);
+ print_nl();
+}
+
+static void print_wild_statement(w,os)
+lang_wild_statement_type *w;
+lang_output_section_statement_type *os;
+{
+ if (w->filename != (char *)NULL) {
+ printf("%s",w->filename);
+ }
+ else {
+ printf("*");
+ }
+ if (w->section_name != (char *)NULL) {
+ printf("(%s)",w->section_name);
+ }
+ else {
+ printf("(*)");
+ }
+ print_nl();
+ print_statement(w->children.head, os);
+
+}
+static void
+print_statement(s, os)
+lang_statement_union_type *s;
+lang_output_section_statement_type *os;
+{
+ while (s) {
+ switch (s->header.type) {
+ case lang_wild_statement_enum:
+ print_wild_statement(&s->wild_statement, os);
+ break;
+ default:
+ printf("Fail with %d\n",s->header.type);
+ FAIL();
+ break;
+ case lang_address_statement_enum:
+ printf("address\n");
+ break;
+ case lang_common_statement_enum:
+ print_common_statement();
+ break;
+ case lang_object_symbols_statement_enum:
+ printf("object symbols\n");
+ break;
+ case lang_fill_statement_enum:
+ print_fill_statement(&s->fill_statement);
+ break;
+ case lang_data_statement_enum:
+ print_data_statement(&s->data_statement);
+ break;
+
+
+ case lang_input_section_enum:
+ print_input_section(&s->input_section);
+ break;
+ case lang_padding_statement_enum:
+ print_padding_statement(&s->padding_statement);
+ break;
+ case lang_output_section_statement_enum:
+ print_output_section_statement(&s->output_section_statement);
+ break;
+ case lang_assignment_statement_enum:
+ print_assignment(&s->assignment_statement,
+ os);
+ break;
+
+
+ case lang_target_statement_enum:
+ printf("TARGET(%s)\n", s->target_statement.target);
+ break;
+ case lang_output_statement_enum:
+ printf("OUTPUT(%s)\n", s->output_statement.name);
+ break;
+ case lang_input_statement_enum:
+ print_input_statement(&s->input_statement);
+ break;
+ case lang_afile_asection_pair_statement_enum:
+ FAIL();
+ break;
+ }
+ s = s->next;
+ }
+}
+
+
+static void
+print_statements()
+{
+ print_statement(statement_list.head,
+ (lang_output_section_statement_type *)NULL);
+}
+
+static bfd_vma
+insert_pad(this_ptr, fill, power, output_section_statement, dot)
+lang_statement_union_type **this_ptr;
+fill_type fill;
+unsigned int power;
+asection * output_section_statement;
+bfd_vma dot;
+{
+ /* Align this section first to the
+ input sections requirement, then
+ to the output section's requirement.
+ If this alignment is > than any seen before,
+ then record it too. Perform the alignment by
+ inserting a magic 'padding' statement.
+ */
+
+ unsigned int alignment_needed = align_power(dot, power) - dot;
+
+ if (alignment_needed != 0)
+ {
+ lang_statement_union_type *new =
+ (lang_statement_union_type *)
+ ldmalloc(sizeof(lang_padding_statement_type));
+ /* Link into existing chain */
+ new->header.next = *this_ptr;
+ *this_ptr = new;
+ new->header.type = lang_padding_statement_enum;
+ new->padding_statement.output_section = output_section_statement;
+ new->padding_statement.output_offset =
+ dot - output_section_statement->vma;
+ new->padding_statement.fill = fill;
+ new->padding_statement.size = alignment_needed;
+ }
+
+
+ /* Remember the most restrictive alignment */
+ if (power > output_section_statement->alignment_power) {
+ output_section_statement->alignment_power = power;
+ }
+ output_section_statement->size += alignment_needed;
+ return alignment_needed + dot;
+
+}
+
+/*
+ size_common runs run though each global symboxl, and works
+ out how big the common section will be.
+ */
+
+static bfd_vma
+size_common(output_section_statement, this_ptr, dot)
+lang_output_section_statement_type *output_section_statement;
+lang_statement_union_type **this_ptr;
+bfd_vma dot;
+{
+ extern ldsym_type *symbol_head;
+ ldsym_type *sp;
+ /* Make sure that each symbol is only defined once.
+ Allocate common symbols
+ Make the ref chain point to the defining asymbol.
+ */
+ /* Now, for each symbol, verify that it is defined globally at most once.
+ Put the global value into the symbol entry.
+ Common symbols are allocated here, in the BSS section.
+ Each defined symbol is given a '->defined' field
+ which is the correct N_ code for its definition,
+ except in the case of common symbols with -r.
+ Then make all the references point at the symbol entry
+ instead of being chained together. */
+
+
+ common_section.name = output_section_statement->bfd_section->name;
+ common_section.output_section = output_section_statement->bfd_section;
+ common_section.output_offset =
+ dot - output_section_statement->bfd_section->vma;
+ if (config.relocateable_output == false ||
+ command_line.force_common_definition== true) {
+ dot = insert_pad(this_ptr,
+ 0x0, 4, output_section_statement->bfd_section, dot);
+
+ for (sp = symbol_head; sp != (ldsym_type *)NULL; sp = sp->next)
+ {
+ /* Attatch this symbol to the correct output section*/
+
+ /* Allocate as common if wanted */
+
+ if (sp->scoms_chain )
+
+ {
+ unsigned long com = (*(sp->scoms_chain))->value;
+ /* Work out what alignment this common item s
+ hould be put on. Anything < int is int aligned,
+ anything bigger is self aligned,
+ up to the restriction of the machine */
+
+ unsigned int align = sizeof(int);
+
+ /* Round up size of object to nearest int */
+ com = ALIGN(com, sizeof(int));
+ /* See what alignment is necessary -*/
+ if (com) {
+ while ((com & align)==0) align <<=1;
+ /* FIXME */
+ if (align > 8) {
+ align = 8;
+ }
+ }
+ dot = ALIGN(dot, align);
+
+
+ /* Transmogrify this from a common symbol
+ into a definition of a symbol in common
+ */
+ sp->sdefs_chain = sp->scoms_chain;
+
+ {
+ asymbol *com_ptr = *(sp->sdefs_chain);
+
+ sp->scoms_chain = (asymbol **)NULL;
+ commons_pending--;
+ /* Assign address, but keep section relative */
+
+ /* Force the symbol to belong in the bss section */
+ com_ptr->flags = BSF_EXPORT | BSF_GLOBAL ;
+ com_ptr->section = &common_section;
+ common_section.size += com;
+ if (write_map)
+ {
+ printf ("Allocating common %s: %lx at %lx\n",
+ sp->name,
+ com,
+ com_ptr->value);
+ }
+ com_ptr->value = common_section.size;
+ }
+ }
+ }
+ }
+ if (dot >
+ (common_section.output_section->vma +
+ common_section.output_section->size)) {
+ common_section.output_section->size =
+ dot - common_section.output_section->vma;
+ }
+ return dot + common_section.size;
+}
+
+static bfd_vma
+size_input_section( this_ptr, output_section_statement, fill, dot)
+lang_statement_union_type **this_ptr;
+lang_output_section_statement_type*output_section_statement;
+unsigned short fill;
+bfd_vma dot;
+{
+ lang_input_section_type *is = &((*this_ptr)->input_section);
+ asection *i = is->section;
+
+ dot = insert_pad(this_ptr, fill, i->alignment_power,
+ output_section_statement->bfd_section, dot);
+
+ /* remember the largest size so we can malloc the largest area */
+ /* needed for the output stage */
+ if (i->size > largest_section) {
+ largest_section = i->size;
+ }
+
+ /* Remember where in the output section this input section goes */
+ i->output_offset = dot - output_section_statement->bfd_section->vma;
+
+ /* Mark how big the output section must be to contain this now */
+ dot += i->size;
+ output_section_statement->bfd_section->size =
+ dot - output_section_statement->bfd_section->vma;
+
+
+ return dot ;
+}
+
+
+/* Work out the size of the output sections
+ from the sizes of the input sections */
+static bfd_vma
+lang_size_sections(s, output_section_statement, prev, fill, dot)
+lang_statement_union_type *s;
+lang_output_section_statement_type * output_section_statement;
+lang_statement_union_type **prev;
+unsigned short fill;
+bfd_vma dot;
+{
+ /* Size up the sections from their constituent parts */
+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
+ {
+ switch (s->header.type) {
+ case lang_output_section_statement_enum:
+ {
+ bfd_vma after;
+ lang_output_section_statement_type *os =
+ &(s->output_section_statement);
+ /* The start of a section */
+
+ if (os->addr_tree == (etree_type *)NULL) {
+ /* No address specified for this section, get one
+ from the region specification
+ */
+ if (os->region == (lang_memory_region_type *)NULL) {
+ os->region = lang_memory_region_lookup("*default*");
+ }
+ dot = os->region->current;
+ }
+ else {
+ etree_value_type r ;
+ r = exp_fold_tree(os->addr_tree,
+ (lang_output_section_statement_type *)NULL,
+ lang_allocating_phase_enum,
+ dot, &dot);
+ if (r.valid == false) {
+ info("%F%S: non constant address expression for section %s\n",
+ os->name);
+ }
+ dot = r.value;
+ }
+ /* The section starts here */
+ /* First, align to what the section needs */
+
+ dot = align_power(dot, os->bfd_section->alignment_power);
+ os->bfd_section->vma = dot;
+ os->bfd_section->output_offset = 0;
+
+ (void) lang_size_sections(os->children.head, os, &os->children.head,
+ os->fill, dot);
+ /* Ignore the size of the input sections, use the vma and size to */
+ /* align against */
+
+
+ after = ALIGN(os->bfd_section->vma +
+ os->bfd_section->size,
+ os->block_value) ;
+
+
+ os->bfd_section->size = after - os->bfd_section->vma;
+ dot = os->bfd_section->vma + os->bfd_section->size;
+ os->processed = true;
+
+ /* Replace into region ? */
+ if (os->addr_tree == (etree_type *)NULL
+ && os->region !=(lang_memory_region_type*)NULL ) {
+ os->region->current = dot;
+ }
+ }
+
+ break;
+
+ case lang_data_statement_enum:
+ {
+ unsigned int size;
+ s->data_statement.output_vma = dot;
+ s->data_statement.output_section =
+ output_section_statement->bfd_section;
+
+ switch (s->data_statement.type) {
+ case LONG:
+ size = LONG_SIZE;
+ break;
+ case SHORT:
+ size = SHORT_SIZE;
+ break;
+ case BYTE:
+ size = BYTE_SIZE;
+ break;
+
+ }
+ dot += size;
+ output_section_statement->bfd_section->size += size;
+ }
+ break;
+
+ case lang_wild_statement_enum:
+
+ dot = lang_size_sections(s->wild_statement.children.head,
+ output_section_statement,
+ &s->wild_statement.children.head,
+
+ fill, dot);
+
+ break;
+
+ case lang_object_symbols_statement_enum:
+ create_object_symbols = output_section_statement;
+ break;
+ case lang_output_statement_enum:
+
+ case lang_target_statement_enum:
+ break;
+ case lang_common_statement_enum:
+ dot = size_common(output_section_statement, prev, dot);
+
+ break;
+
+ case lang_input_section_enum:
+ dot = size_input_section(prev,
+ output_section_statement,
+ output_section_statement->fill, dot);
+ break;
+ case lang_input_statement_enum:
+ break;
+ case lang_fill_statement_enum:
+ fill = s->fill_statement.fill;
+ break;
+ case lang_assignment_statement_enum:
+ {
+ bfd_vma newdot = dot;
+ exp_fold_tree(s->assignment_statement.exp,
+ output_section_statement,
+ lang_allocating_phase_enum,
+ dot,
+ &newdot);
+
+ if (newdot != dot)
+ /* We've been moved ! so insert a pad */
+ {
+ lang_statement_union_type *new =
+ (lang_statement_union_type *)
+ ldmalloc(sizeof(lang_padding_statement_type));
+ /* Link into existing chain */
+ new->header.next = *prev;
+ *prev = new;
+ new->header.type = lang_padding_statement_enum;
+ new->padding_statement.output_section =
+ output_section_statement->bfd_section;
+ new->padding_statement.output_offset =
+ dot - output_section_statement->bfd_section->vma;
+ new->padding_statement.fill = fill;
+ new->padding_statement.size = newdot - dot;
+ output_section_statement->bfd_section->size +=
+ new->padding_statement.size;
+ dot = newdot;
+ }
+ }
+
+ break;
+ case lang_padding_statement_enum:
+ FAIL();
+ break;
+ default:
+ FAIL();
+ break;
+ case lang_address_statement_enum:
+ break;
+ }
+ prev = &s->header.next;
+ }
+ return dot;
+}
+
+
+static bfd_vma
+lang_do_assignments(s, output_section_statement, fill, dot)
+lang_statement_union_type *s;
+lang_output_section_statement_type * output_section_statement;
+unsigned short fill;
+bfd_vma dot;
+{
+
+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
+ {
+ switch (s->header.type) {
+ case lang_output_section_statement_enum:
+ {
+ lang_output_section_statement_type *os =
+ &(s->output_section_statement);
+ dot = os->bfd_section->vma;
+ (void) lang_do_assignments(os->children.head, os, os->fill, dot);
+ dot = os->bfd_section->vma + os->bfd_section->size;
+ }
+ break;
+ case lang_wild_statement_enum:
+
+ dot = lang_do_assignments(s->wild_statement.children.head,
+ output_section_statement,
+ fill, dot);
+
+ break;
+
+ case lang_object_symbols_statement_enum:
+ case lang_output_statement_enum:
+ case lang_target_statement_enum:
+ case lang_common_statement_enum:
+ break;
+ case lang_data_statement_enum:
+ {
+ etree_value_type value ;
+ value = exp_fold_tree(s->data_statement.exp,
+ 0, lang_final_phase_enum, dot, &dot);
+ s->data_statement.value = value.value;
+ if (value.valid == false) info("%F%P: Invalid data statement\n");
+ }
+ switch (s->data_statement.type) {
+ case LONG:
+ dot += LONG_SIZE;
+ break;
+ case SHORT:
+ dot += SHORT_SIZE;
+ break;
+ case BYTE:
+ dot += BYTE_SIZE;
+ break;
+ }
+ break;
+ case lang_input_section_enum:
+ {
+ asection *in = s->input_section.section;
+ dot += in->size;
+ }
+ break;
+
+ case lang_input_statement_enum:
+ break;
+ case lang_fill_statement_enum:
+ fill = s->fill_statement.fill;
+ break;
+ case lang_assignment_statement_enum:
+ {
+ exp_fold_tree(s->assignment_statement.exp,
+ output_section_statement,
+ lang_final_phase_enum,
+ dot,
+ &dot);
+ }
+
+ break;
+ case lang_padding_statement_enum:
+ dot += s->padding_statement.size;
+ break;
+ default:
+ FAIL();
+ break;
+ case lang_address_statement_enum:
+ break;
+ }
+
+ }
+ return dot;
+}
+
+
+
+static void lang_relocate_globals()
+{
+
+ /*
+ Each ldsym_type maintains a chain of pointers to asymbols which
+ references the definition. Replace each pointer to the referenence
+ with a pointer to only one place, preferably the definition. If
+ the defintion isn't available then the common symbol, and if
+ there isn't one of them then choose one reference.
+ */
+
+ FOR_EACH_LDSYM(lgs) {
+ asymbol *it;
+ if (lgs->sdefs_chain) {
+ it = *(lgs->sdefs_chain);
+ }
+ else if (lgs->scoms_chain != (asymbol **)NULL) {
+ it = *(lgs->scoms_chain);
+ }
+ else if (lgs->srefs_chain != (asymbol **)NULL) {
+ it = *(lgs->srefs_chain);
+ }
+ else {
+ FAIL();
+ }
+ if (it != (asymbol *)NULL)
+ {
+ asymbol **ptr= lgs->srefs_chain;
+
+ while (ptr != (asymbol **)NULL) {
+ asymbol *ref = *ptr;
+ *ptr = it;
+ ptr = (asymbol **)(ref->udata);
+ }
+ }
+ }
+}
+
+
+
+/* now that all the jiggery pokery is finished, copy important data from
+ * out internal form to the bfd way. Also create a section
+ * for each dummy file
+ */
+
+static void
+lang_create_output_section_statements()
+{
+ lang_statement_union_type*os;
+ for (os = lang_output_section_statement.head;
+ os != (lang_statement_union_type*)NULL;
+ os = os->output_section_statement.next) {
+ lang_output_section_statement_type *s =
+ &os->output_section_statement;
+ init_os(s);
+ }
+ script_file->the_bfd->sections = output_bfd->sections;
+}
+
+static void
+lang_finish()
+{
+ ldsym_type *lgs;
+
+ if (entry_symbol == (char *)NULL) {
+ /* No entry has been specified, look for start */
+ entry_symbol = "start";
+ }
+ lgs = ldsym_get_soft(entry_symbol);
+ if (lgs && lgs->sdefs_chain) {
+ asymbol *sy = *(lgs->sdefs_chain);
+ /* We can set the entry address*/
+ bfd_set_start_address(output_bfd,
+ outside_symbol_address(sy));
+
+ }
+ else {
+ /* Can't find anything reasonable,
+ use the first address in the text section
+ */
+ asection *ts = bfd_get_section_by_name(output_bfd, ".text");
+ if (ts) {
+ bfd_set_start_address(output_bfd, ts->vma);
+ }
+ }
+}
+
+/* By now we know the target architecture, and we may have an */
+/* ldfile_output_machine_name */
+static void
+lang_check()
+{
+ lang_statement_union_type *file;
+
+
+ for (file = file_chain.head;
+ file != (lang_statement_union_type *)NULL;
+ file=file->input_statement.next)
+ {
+ /* Inspect the architecture and ensure we're linking like
+ with like
+ */
+
+ if (bfd_arch_compatible( file->input_statement.the_bfd,
+ output_bfd,
+ &ldfile_output_architecture,
+ &ldfile_output_machine)) {
+ bfd_set_arch_mach(output_bfd,
+ ldfile_output_architecture, ldfile_output_machine);
+ }
+ else {
+ enum bfd_architecture this_architecture =
+ bfd_get_architecture(file->input_statement.the_bfd);
+ unsigned long this_machine =
+ bfd_get_machine(file->input_statement.the_bfd);
+
+ info("%I: architecture %s",
+ file,
+ bfd_printable_arch_mach(this_architecture, this_machine));
+ info(" incompatible with output %s\n",
+ bfd_printable_arch_mach(ldfile_output_architecture,
+ ldfile_output_machine));
+ ldfile_output_architecture = this_architecture;
+ ldfile_output_machine = this_machine;
+ bfd_set_arch_mach(output_bfd,
+ ldfile_output_architecture,
+ ldfile_output_machine);
+
+
+ }
+ }
+}
+
+
+/*
+ * run through all the global common symbols and tie them
+ * to the output section requested.
+ */
+
+static void
+lang_common()
+{
+ ldsym_type *lgs;
+ if (config.relocateable_output == false ||
+ command_line.force_common_definition== true) {
+ for (lgs = symbol_head;
+ lgs != (ldsym_type *)NULL;
+ lgs=lgs->next)
+ {
+ asymbol *com ;
+ size_t size;
+ size_t align;
+ if (lgs->scoms_chain != (asymbol **)NULL) {
+
+ com = *(lgs->scoms_chain);
+ size = com->value;
+ align = sizeof(int);
+ /* Round up size of object to nearest int */
+ size = ALIGN(size, sizeof(int));
+ /* Force alignment */
+ if (size) {
+ while ((size & align)==0) align<<=1;
+ if (align > 8) {
+ align = 8;
+ }
+ }
+ /* Change from a common symbol into a definition of
+ a symbol */
+ lgs->sdefs_chain = lgs->scoms_chain;
+ lgs->scoms_chain = (asymbol **)NULL;
+ commons_pending--;
+ /* Point to the correct common section */
+ com->section =
+ ((lang_input_statement_type *)
+ (com->the_bfd->usrdata))->common_section;
+ /* Fix the size of the common section */
+
+
+ com->flags = BSF_EXPORT | BSF_GLOBAL;
+
+ if (write_map)
+ {
+ printf ("Allocating common %s: %x at %x\n",
+ lgs->name,
+ (unsigned) size,
+ (unsigned) com->section->size);
+ }
+ com->value = com->section->size;
+ com->section->size += size;
+ }
+ }
+ }
+}
+
+/*
+run through the input files and ensure that every input
+section has somewhere to go. If one is found without
+a destination then create an input request and place it
+into the statement tree.
+*/
+
+static void lang_place_orphans()
+{
+ lang_input_statement_type *file;
+ for (file = (lang_input_statement_type*)file_chain.head;
+ file != (lang_input_statement_type*)NULL;
+ file = (lang_input_statement_type*)file->next) {
+ asection *s;
+ for (s = file->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ if ( s->output_section == (asection *)NULL) {
+ /* This section of the file is not attatched, root
+ around for a sensible place for it to go */
+
+ if (file->common_section == s) {
+ /* This is a lonely common section which must
+ have come from an archive. We attatch to the
+ section with the wildcard */
+ wild_doit(&default_common_section->children, s,
+ default_common_section, file);
+ }
+ else {
+ lang_output_section_statement_type *os =
+ lang_output_section_statement_lookup(s->name);
+
+ wild_doit(&os->children, s, os, file);
+ }
+ }
+ }
+
+ }
+}
+
+
+/*
+ * phase_2
+ *
+ * peformed after every file has been opened and symbols read
+ */
+static void
+lang_phase_2()
+{
+ lang_init2();
+
+ lang_create_output_section_statements();
+ lang_open_input(statement_list.head, (char *)NULL,
+ ( lang_output_section_statement_type *)NULL);
+ lang_place_orphans();
+ lang_common();
+
+ ldemul_before_allocation();
+
+ lang_size_sections(statement_list.head,
+ (lang_output_section_statement_type *)NULL,
+ &(statement_list.head), 0, (bfd_vma)0);
+ ldemul_after_allocation();
+ /* Do it once again now that we know the sizes of everything */
+
+ lang_do_assignments(statement_list.head,
+ (lang_output_section_statement_type *)NULL,
+ 0, (bfd_vma)0);
+
+
+
+ lang_check();
+
+ lang_relocate_globals();
+
+
+ lang_finish();
+}
+
+
+
+
+void
+lang_set_flags(ptr, flags)
+lang_section_flags_type *ptr;
+char *flags;
+{
+ boolean state = true;
+ ptr->flag_read = false;
+ ptr->flag_write = false;
+ ptr->flag_executable = false;
+ ptr->flag_loadable= false;
+ while (*flags)
+ {
+ if (*flags == '!') {
+ state = false;
+ flags++;
+ }
+ else state = true;
+ switch (*flags) {
+ case 'R':
+ ptr->flag_read = state;
+ break;
+ case 'W':
+ ptr->flag_write = state;
+ break;
+ case 'X':
+ ptr->flag_executable= state;
+ break;
+ case 'L':
+ ptr->flag_loadable= state;
+ break;
+ default:
+ info("%P%F illegal syntax in flags\n");
+ break;
+ }
+ flags++;
+ }
+}
+
+
+
+void
+lang_for_each_file(func)
+void (*func)();
+{
+ lang_input_statement_type *f;
+ for (f = (lang_input_statement_type *)file_chain.head;
+ f != (lang_input_statement_type *)NULL;
+ f = (lang_input_statement_type *)f->next)
+ {
+ func(f);
+ }
+}
+
+
+void
+lang_for_each_input_section(func)
+void (*func)();
+{
+ lang_input_statement_type *f;
+ for (f = (lang_input_statement_type *)file_chain.head;
+ f != (lang_input_statement_type *)NULL;
+ f = (lang_input_statement_type *)f->next)
+ {
+ asection *s;
+ for (s = f->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ func(f->the_bfd, s);
+ }
+ }
+}
+
+
+
+void
+ldlang_add_file(entry)
+lang_input_statement_type *entry;
+{
+ lang_has_input_file = true;
+ lang_statement_append(&file_chain,
+ (lang_statement_union_type *)entry,
+ &entry->next);
+}
+
+
+
+void
+lang_add_output(name)
+char *name;
+{
+ lang_output_statement_type *new = new_stat(lang_output_statement,
+ stat_ptr);
+ new->name = name;
+ had_output_filename = true;
+}
+
+
+static lang_output_section_statement_type *current_section;
+
+void
+lang_enter_output_section_statement(output_section_statement_name,
+address_exp,
+block_value)
+char *output_section_statement_name;
+etree_type *address_exp;
+bfd_vma block_value;
+{
+ lang_output_section_statement_type *os;
+ current_section =
+ os =
+ lang_output_section_statement_lookup(output_section_statement_name);
+
+
+ /* Add this statement to tree */
+ /* add_statement(lang_output_section_statement_enum,
+ output_section_statement);*/
+ /* Make next things chain into subchain of this */
+
+ if (os->addr_tree ==
+ (etree_type *)NULL) {
+ os->addr_tree =
+ address_exp;
+ }
+ os->block_value = block_value;
+ stat_ptr = & os->children;
+
+}
+
+
+void
+lang_final()
+{
+ if (had_output_filename == false) {
+ lang_add_output("a.out");
+ }
+
+
+}
+
+
+
+
+
+asymbol *create_symbol(name, flags, section)
+char *name;
+flagword flags;
+asection *section;
+{
+ extern lang_input_statement_type *script_file;
+ asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+ /* Add this definition to script file */
+ asymbol *def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
+ def->name = name;
+ def->udata = 0;
+ def->flags = flags;
+ def->section = section;
+
+ *def_ptr = def;
+ Q_enter_global_ref(def_ptr);
+ return def;
+}
+
+
+void
+lang_process()
+{
+ lang();
+ lang_phase_2();
+}
+
+
+/* EXPORTED TO YACC */
+void
+lang_section_start(name, address)
+char *name;
+etree_type *address;
+{
+ lang_address_statement_type *ad =new_stat(lang_address_statement, stat_ptr);
+ ad->section_name = name;
+ ad->address = address;
+}
+void lang_add_entry(name)
+char *name;
+{
+ entry_symbol = name;
+}
+
+void
+lang_add_target(name)
+char *name;
+{
+ lang_target_statement_type *new = new_stat(lang_target_statement,
+ stat_ptr);
+ new->target = name;
+
+}
+void
+lang_add_wild(section_name, filename)
+char *section_name;
+char *filename;
+{
+ lang_wild_statement_type *new = new_stat(lang_wild_statement,
+ stat_ptr);
+
+ if (section_name != (char *)NULL && strcmp(section_name,"COMMON") == 0)
+ {
+ placed_commons = true;
+ }
+ new->section_name = section_name;
+ new->filename = filename;
+ lang_list_init(&new->children);
+}
+
+void
+lang_add_map(name)
+char *name;
+{
+ while (*name) {
+ switch (*name) {
+ case 'F':
+ map_option_f = true;
+ break;
+ }
+ name++;
+ }
+}
+
+void lang_add_fill(exp)
+int exp;
+{
+ lang_fill_statement_type *new = new_stat(lang_fill_statement,
+ stat_ptr);
+ new->fill = exp;
+}
+
+void lang_add_data(type, exp)
+int type;
+union etree_union *exp;
+{
+
+ lang_data_statement_type *new = new_stat(lang_data_statement,
+ stat_ptr);
+ new->exp = exp;
+ new->type = type;
+
+}
+void
+lang_add_assignment(exp)
+etree_type *exp;
+{
+ lang_assignment_statement_type *new = new_stat(lang_assignment_statement,
+ stat_ptr);
+ new->exp = exp;
+}
+
+void
+lang_add_attribute(attribute)
+enum statement_enum attribute;
+{
+ new_statement(attribute, sizeof(lang_statement_union_type),stat_ptr);
+}
+
+
+
+void
+lang_startup(name)
+char *name;
+{
+ if (startup_file != (char *)NULL) {
+ info("%P%FMultiple STARTUP files\n");
+ }
+ first_file->filename = name;
+ first_file->local_sym_name = name;
+
+ startup_file= name;
+}
+void
+lang_float(maybe)
+boolean maybe;
+{
+ lang_float_flag = maybe;
+}
+
+void
+lang_leave_output_section_statement(fill, memspec)
+bfd_vma fill;
+char *memspec;
+{
+ current_section->fill = fill;
+ current_section->region = lang_memory_region_lookup(memspec);
+ stat_ptr = &statement_list;
+}
+
+void
+lang_abs_symbol_at_end_of(section, name)
+char *section;
+char *name;
+{
+ extern bfd *output_bfd;
+ extern asymbol *create_symbol();
+ asection *s = bfd_get_section_by_name(output_bfd, section);
+ /* Add a symbol called _end */
+ asymbol *def = create_symbol(name,
+ BSF_GLOBAL | BSF_EXPORT |
+ BSF_ABSOLUTE,
+ (asection *)NULL);
+ if (s != (asection *)NULL) {
+ def->value = s->vma + s->size;
+ }
+ else {
+ def->value = 0;
+ }
+}
+
+void
+lang_statement_append(list, element, field)
+lang_statement_list_type *list;
+lang_statement_union_type *element;
+lang_statement_union_type **field;
+{
+ *(list->tail) = element;
+ list->tail = field;
+}
+
+
+static void
+lang_for_each_statement_worker(func, s)
+void (*func)();
+lang_statement_union_type *s;
+{
+ for (; s != (lang_statement_union_type *)NULL ; s = s->next)
+ {
+ func(s);
+
+ switch (s->header.type) {
+ case lang_output_section_statement_enum:
+ lang_for_each_statement_worker
+ (func,
+ s->output_section_statement.children.head);
+ break;
+ case lang_wild_statement_enum:
+ lang_for_each_statement_worker
+ (func,
+ s->wild_statement.children.head);
+ break;
+ case lang_data_statement_enum:
+ case lang_object_symbols_statement_enum:
+ case lang_output_statement_enum:
+ case lang_target_statement_enum:
+ case lang_common_statement_enum:
+ case lang_input_section_enum:
+ case lang_input_statement_enum:
+ case lang_fill_statement_enum:
+ case lang_assignment_statement_enum:
+ case lang_padding_statement_enum:
+ case lang_address_statement_enum:
+ break;
+ default:
+ FAIL();
+ break;
+ }
+ }
+}
+
+void lang_for_each_statement(func)
+void (*func)();
+{
+ lang_for_each_statement_worker(func,
+ statement_list.head);
+
+}
diff --git a/ld/ldlang.h b/ld/ldlang.h
new file mode 100644
index 0000000..ab102a5
--- /dev/null
+++ b/ld/ldlang.h
@@ -0,0 +1,347 @@
+/* ldlang.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+typedef enum {
+ lang_input_file_is_l_enum,
+ lang_input_file_is_symbols_only_enum,
+ lang_input_file_is_marker_enum,
+ lang_input_file_is_fake_enum,
+lang_input_file_is_search_file_enum,
+ lang_input_file_is_file_enum } lang_input_file_enum_type;
+
+typedef unsigned short fill_type;
+typedef struct statement_list {
+ union lang_statement_union *head;
+ union lang_statement_union **tail;
+} lang_statement_list_type;
+
+
+typedef struct {
+ boolean flag_read;
+ boolean flag_write;
+ boolean flag_executable;
+ boolean flag_loadable;
+} lang_section_flags_type;
+
+typedef struct memory_region_struct {
+ char *name;
+ struct memory_region_struct *next;
+ bfd_vma origin;
+ bfd_offset length;
+ bfd_vma current;
+ lang_section_flags_type flags;
+} lang_memory_region_type ;
+
+typedef struct lang_statement_header_struct
+{
+union lang_statement_union *next;
+ enum statement_enum {
+ lang_output_section_statement_enum,
+ lang_assignment_statement_enum,
+ lang_input_statement_enum,
+ lang_address_statement_enum,
+ lang_wild_statement_enum,
+ lang_input_section_enum,
+ lang_common_statement_enum,
+ lang_object_symbols_statement_enum,
+ lang_fill_statement_enum,
+ lang_data_statement_enum,
+ lang_target_statement_enum,
+ lang_output_statement_enum,
+ lang_padding_statement_enum,
+
+ lang_afile_asection_pair_statement_enum
+ } type;
+
+} lang_statement_header_type;
+
+
+typedef struct
+{
+ lang_statement_header_type header;
+ union etree_union *exp;
+} lang_assignment_statement_type;
+
+
+typedef struct lang_target_statement_struct {
+ lang_statement_header_type header;
+ char *target;
+} lang_target_statement_type;
+
+
+typedef struct lang_output_statement_struct {
+ lang_statement_header_type header;
+ char *name;
+} lang_output_statement_type;
+
+
+typedef struct lang_output_section_statement_struct
+{
+ lang_statement_header_type header;
+ union etree_union *addr_tree;
+ lang_statement_list_type children;
+ char *memspec;
+ union lang_statement_union *next;
+ char *name;
+ unsigned long subsection_alignment;
+ boolean processed;
+
+ asection *bfd_section;
+ lang_section_flags_type flags;
+ struct memory_region_struct *region;
+ size_t block_value;
+ fill_type fill;
+} lang_output_section_statement_type;
+
+
+typedef struct {
+ lang_statement_header_type header;
+} lang_common_statement_type;
+
+typedef struct {
+ lang_statement_header_type header;
+} lang_object_symbols_statement_type;
+
+typedef struct {
+ lang_statement_header_type header;
+fill_type fill;
+} lang_fill_statement_type;
+
+typedef struct {
+ lang_statement_header_type header;
+ unsigned int type;
+ union etree_union *exp;
+ bfd_vma value;
+ asection *output_section;
+ bfd_vma output_vma;
+} lang_data_statement_type;
+
+
+
+
+typedef struct lang_input_statement_struct
+ {
+ lang_statement_header_type header;
+ /* Name of this file. */
+ char *filename;
+ /* Name to use for the symbol giving address of text start */
+ /* Usually the same as filename, but for a file spec'd with -l
+ this is the -l switch itself rather than the filename. */
+ char *local_sym_name;
+
+ /* Describe the layout of the contents of the file */
+
+ /* The file's a.out header. */
+ /* struct exec header;*/
+ /* Offset in file of GDB symbol segment, or 0 if there is none. */
+ int symseg_offset;
+
+ /* Describe data from the file loaded into core */
+
+ bfd *the_bfd;
+
+ boolean closed;
+ file_ptr passive_position;
+
+ /* Symbol table of the file. */
+ asymbol **asymbols;
+ unsigned int symbol_count;
+
+ /* Next two used only if `relocatable_output' or if needed for */
+ /* output of undefined reference line numbers. */
+ /* Text reloc info saved by `write_text' for `coptxtrel'. */
+
+
+ /* Offset in bytes in the output file symbol table
+ of the first local symbol for this file. Set by `write_file_symbols'. */
+ int local_syms_offset;
+
+ /* For library members only */
+
+ /* For a library, points to chain of entries for the library members. */
+ struct lang_input_statement_struct *subfiles;
+ /* For a library member, offset of the member within the archive.
+ Zero for files that are not library members. */
+ /* int starting_offset;*/
+ /* Size of contents of this file, if library member. */
+ int total_size;
+ /* For library member, points to the library's own entry. */
+ struct lang_input_statement_struct *superfile;
+ /* For library member, points to next entry for next member. */
+ struct lang_input_statement_struct *chain;
+ /* Point to the next file - whatever it is, wanders up and down archives */
+ union lang_statement_union *next;
+ /* Point to the next file, but skips archive contents */
+ union lang_statement_union *next_real_file;
+
+ boolean is_archive;
+
+ /* 1 if file's header has been read into this structure. */
+ boolean header_read_flag;
+
+ /* 1 means search a set of directories for this file. */
+ boolean search_dirs_flag;
+
+ /* 1 means this is base file of incremental load.
+ Do not load this file's text or data.
+ Also default text_start to after this file's bss. */
+ boolean just_syms_flag;
+
+ boolean loaded;
+
+
+ /* unsigned int globals_in_this_file;*/
+ char *target;
+ boolean real;
+
+ asection *common_section;
+ asection *common_output_section;
+ } lang_input_statement_type;
+
+typedef struct {
+ lang_statement_header_type header;
+ asection *section;
+ lang_input_statement_type *ifile;
+} lang_input_section_type;
+
+
+typedef struct {
+ lang_statement_header_type header;
+ asection *section;
+ union lang_statement_union *file;
+} lang_afile_asection_pair_statement_type;
+
+typedef struct lang_wild_statement_struct {
+ lang_statement_header_type header;
+ char *section_name;
+ char *filename;
+ lang_statement_list_type children;
+} lang_wild_statement_type;
+
+typedef struct lang_address_statement_struct {
+ lang_statement_header_type header;
+ char *section_name;
+ union etree_union *address;
+} lang_address_statement_type;
+
+typedef struct {
+ lang_statement_header_type header;
+ bfd_vma output_offset;
+ size_t size;
+ asection *output_section;
+ fill_type fill;
+} lang_padding_statement_type;
+
+typedef union lang_statement_union
+{
+ lang_statement_header_type header;
+ union lang_statement_union *next;
+ lang_wild_statement_type wild_statement;
+ lang_data_statement_type data_statement;
+ lang_address_statement_type address_statement;
+ lang_output_section_statement_type output_section_statement;
+ lang_afile_asection_pair_statement_type afile_asection_pair_statement;
+ lang_assignment_statement_type assignment_statement;
+ lang_input_statement_type input_statement;
+ lang_target_statement_type target_statement;
+ lang_output_statement_type output_statement;
+ lang_input_section_type input_section;
+ lang_common_statement_type common_statement;
+ lang_object_symbols_statement_type object_symbols_statement;
+ lang_fill_statement_type fill_statement;
+ lang_padding_statement_type padding_statement;
+} lang_statement_union_type;
+
+
+
+PROTO(void,lang_init,(void));
+PROTO(struct memory_region_struct ,*lang_memory_region_lookup,(char *));
+PROTO(struct lang_output_section_statement_struct *,lang_output_section_find,(char *));
+
+PROTO(void ,lang_map,(struct _iobuf *));
+PROTO(void,lang_set_flags,(lang_section_flags_type *, char *));
+PROTO(void,lang_add_output,(char *));
+
+PROTO(void,lang_final,(void));
+PROTO(struct symbol_cache_entry *,create_symbol,(char *, unsigned int, struct sec_struct *));
+PROTO(void ,lang_process,(void));
+PROTO(void ,lang_section_start,(char *, union etree_union *));
+PROTO(void,lang_add_entry,(char *));
+PROTO(void,lang_add_target,(char *));
+PROTO(void,lang_add_wild,(char *, char *));
+PROTO(void,lang_add_map,(char *));
+PROTO(void,lang_add_fill,(int));
+PROTO(void,lang_add_assignment,(union etree_union *));
+PROTO(void,lang_add_attribute,(enum statement_enum));
+PROTO(void,lang_startup,(char *));
+PROTO(void,lang_float,(enum boolean));
+PROTO(void,lang_leave_output_section_statement,(bfd_vma, char *));
+PROTO(void,lang_abs_symbol_at_end_of,(char *, char *));
+PROTO(void,lang_statement_append,(struct statement_list *, union lang_statement_union *, union lang_statement_union **));
+PROTO(void, lang_for_each_file,(void (*dothis)(lang_input_statement_type *)));
+
+#define LANG_FOR_EACH_ASYMBOL(asymbol) \
+
+#define LANG_FOR_EACH_INPUT_STATEMENT(statement) \
+ extern lang_statement_list_type file_chain; \
+ lang_input_statement_type *statement; \
+ for (statement = (lang_input_statement_type *)file_chain.head;\
+ statement != (lang_input_statement_type *)NULL; \
+ statement = (lang_input_statement_type *)statement->next)\
+
+#define LANG_FOR_EACH_INPUT_SECTION(statement, abfd, section, x) \
+{ extern lang_statement_list_type file_chain; \
+ lang_input_statement_type *statement; \
+ for (statement = (lang_input_statement_type *)file_chain.head;\
+ statement != (lang_input_statement_type *)NULL; \
+ statement = (lang_input_statement_type *)statement->next)\
+ { \
+ asection *section; \
+ bfd *abfd = statement->the_bfd; \
+ for (section = abfd->sections; \
+ section != (asection *)NULL; \
+ section = section->next) { \
+ x; \
+ } \
+ } \
+ }
+
+#define LANG_FOR_EACH_OUTPUT_SECTION(section, x) \
+ { extern bfd *output_bfd; \
+ asection *section; \
+ for (section = output_bfd->sections; \
+ section != (asection *)NULL; \
+ section = section->next) \
+ { x; } \
+ }
+
+
+PROTO(void, lang_process,(void));
+PROTO(void, ldlang_add_file,(lang_input_statement_type *));
+
+PROTO(lang_output_section_statement_type *,lang_output_section_find,());
+
+PROTO(lang_input_statement_type *,
+ lang_add_input_file,(char *name,
+ lang_input_file_enum_type file_type,
+ char *target));
+PROTO(lang_output_section_statement_type *,
+lang_output_section_statement_lookup,(char *name));
diff --git a/ld/ldlex.h b/ld/ldlex.h
new file mode 100644
index 0000000..fe4e017
--- /dev/null
+++ b/ld/ldlex.h
@@ -0,0 +1,26 @@
+/* ldlex.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+PROTO(int, lex_input, (void));
+PROTO(void, lex_unput, (int));
+PROTO(int ,yywrap,(void));
+PROTO(void, parse_args,(int, char **));
+PROTO(void, parse_line,(char*));
+
diff --git a/ld/ldlex.l b/ld/ldlex.l
new file mode 100644
index 0000000..67af46b
--- /dev/null
+++ b/ld/ldlex.l
@@ -0,0 +1,490 @@
+%{
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:50 gumby
+ * Initial revision
+ *
+ * Revision 1.3 1991/03/16 22:27:24 rich
+ * fish
+ *
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:27 chrisb
+ * Initial revision
+ *
+ * Revision 1.6 1991/03/10 09:31:32 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:25:49 sac
+ * Can now parse the -Ur flag
+ *
+ * Revision 1.4 1991/03/06 02:26:04 sac
+ * Added support for constructor sections.
+ * Remove parsing ambiguity.
+ * Lint
+ *
+ * Revision 1.3 1991/02/22 17:15:14 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+
+
+/*SUPPRESS 529*/
+/*SUPPRESS 26*/
+/*SUPPRESS 29*/
+#define LEXDEBUG
+#include "sysdep.h"
+#include "bfd.h"
+
+#include <ctype.h>
+#include "ldlex.h"
+
+#include "ld.h"
+#include "ldexp.h"
+#include "ldgram.tab.h"
+#include "ldmisc.h"
+
+#undef input
+#undef unput
+#define input lex_input
+#define unput lex_unput
+int debug;
+extern boolean ldgram_want_filename;
+extern boolean ldgram_mustbe_filename;
+extern boolean ldgram_mustbe_symbolname;
+static char *command_line;
+
+extern int fgetc();
+extern int yyparse();
+
+typedef struct {
+ char *name;
+int value;
+} keyword_type;
+#define RTOKEN(x) { yylval.token = x; return x; }
+keyword_type keywords[] =
+{
+"MEMORY",MEMORY,
+"ORIGIN",ORIGIN,
+"BLOCK",BLOCK,
+"LENGTH",LENGTH,
+"ALIGN",ALIGN_K,
+"SUBSECTION_ALIGN",SUBSECTION_ALIGN,
+"ADDR",ADDR,
+"ENTRY",ENTRY,
+"NEXT",NEXT,
+"MAP",MAP,
+"SIZEOF",SIZEOF,
+"TARGET",TARGET_K,
+"SEARCH_DIR",SEARCH_DIR,
+"OUTPUT",OUTPUT,
+"INPUT",INPUT,
+"DEFINED",DEFINED,
+"CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS,
+"SECTIONS",SECTIONS,
+"FILL",FILL,
+"STARTUP",STARTUP,
+"HLL",HLL,
+"SYSLIB",SYSLIB,
+"FLOAT",FLOAT,
+"LONG", LONG,
+"SHORT", SHORT,
+"BYTE", BYTE,
+"NOFLOAT",NOFLOAT,
+"o",ORIGIN,
+"org",ORIGIN,
+"l", LENGTH,
+"len", LENGTH,
+0,0};
+unsigned int lineno;
+extern boolean hex_mode;
+FILE *ldlex_input_stack;
+static unsigned int have_pushback;
+#define NPUSHBACK 10
+int pushback[NPUSHBACK];
+int thischar;
+extern char *ldfile_input_filename;
+
+int
+lex_input()
+{
+ /*
+ When we know that the next token must be a filename we force the
+ input routine to return a '#' character, which will cause the special
+ filname regexp to match the following chars even if they don't look
+ much like a filename to any sane person.
+ */
+ if (ldgram_mustbe_filename) {
+ ldgram_mustbe_filename = false;
+ return '#';
+ }
+
+ if (have_pushback > 0)
+ {
+ have_pushback --;
+ return thischar = pushback[have_pushback];
+ }
+ if (ldlex_input_stack) {
+ thischar = fgetc(ldlex_input_stack);
+
+ if (thischar == EOF) {
+ fclose(ldlex_input_stack);
+ ldlex_input_stack = (FILE *)NULL;
+ ldfile_input_filename = (char *)NULL;
+ thischar = lex_input();
+
+ }
+ }
+ else if (command_line && *command_line) {
+ thischar = *(command_line++);
+ }
+ else thischar = 0;
+ if(thischar == '\t') thischar = ' ';
+ return thischar ;
+}
+
+void
+lex_unput(c)
+int c;
+{
+ if (have_pushback > NPUSHBACK) {
+ info("%F%P Too many pushbacks\n");
+ }
+
+ pushback[have_pushback] = c;
+ have_pushback ++;
+}
+
+
+ int
+yywrap()
+ { return 1; }
+/*VARARGS*/
+
+void
+allprint(x)
+int x;
+{
+fprintf(yyout,"%d",x);
+}
+
+void
+sprint(x)
+char *x;
+{
+fprintf(yyout,"%s",x);
+}
+
+int thischar;
+
+void parse_line(arg)
+char *arg;
+{
+ command_line = arg;
+ have_pushback = 0;
+ yyparse();
+}
+
+
+
+void
+parse_args(ac, av)
+int ac;
+char **av;
+{
+ char *p;
+ int i;
+ size_t size = 0;
+ char *dst;
+ debug = 1;
+ for (i= 1; i < ac; i++) {
+ size += strlen(av[i]) + 2;
+ }
+ dst = p = (char *)ldmalloc(size + 2);
+/* Put a space arount each option */
+
+
+ for (i =1; i < ac; i++) {
+
+ unsigned int s = strlen(av[i]);
+ *dst++ = ' ';
+ memcpy(dst, av[i], s);
+ dst[s] = ' ';
+ dst += s + 1;
+ }
+ *dst = 0;
+ parse_line(p);
+
+ free(p);
+
+
+}
+
+long number(text, base)
+char *text;
+int base;
+{
+unsigned long l = 0;
+ char *p;
+ for (p = text; *p != 0; p++) {
+ if (*p == 'K') {
+ l =l * 1024;
+ }
+ else if(*p== 'M') {
+ l =l * 1024 * 1024;
+ }
+ else {
+ l =l * base;
+ if (isdigit(*p)) {
+ l += *p - '0';
+ }
+ else if (islower(*p)) {
+ l += *p - 'a' + 10;
+ }
+ else {
+ l += *p - 'A' + 10;
+ }
+ }
+ }
+ return l;
+}
+%}
+
+%a 4000
+%o 5000
+FILENAMECHAR [a-zA-Z0-9\/\.\-\_\+]
+FILENAME {FILENAMECHAR}+
+
+
+WHITE [ \t]+
+
+%%
+"\n" { lineno++; }
+
+
+"\ -defsym" { return OPTION_defsym; }
+"\ -noinhibit_exec" { return OPTION_noinhibit_exec; }
+"\ -format" { return OPTION_format; }
+"\ -n" { return OPTION_n; }
+"\ -r" { return OPTION_r; }
+"\ -Ur" { return OPTION_Ur; }
+"\ -o" { return OPTION_o; }
+"\ -g" { return OPTION_g; }
+"\ -e" { return OPTION_e; }
+"\ -b" { return OPTION_b; }
+"\ -dc" { return OPTION_dc; }
+"\ -dp" { return OPTION_dp; }
+"\ -d" { return OPTION_d; }
+"\ -v" { return OPTION_v; }
+"\ -M" { return OPTION_M; }
+"\ -t" { return OPTION_t; }
+"\ -X" { return OPTION_X; }
+"\ -x" { return OPTION_x; }
+"\ -c" { return OPTION_c; }
+"\ -s" { return OPTION_s; }
+"\ -S" { return OPTION_S; }
+"\ -l"{FILENAME} {
+ yylval.name = buystring(yytext+3);
+ return OPTION_l;
+ }
+
+"\ -L"{FILENAME} {
+ yylval.name = buystring(yytext+3);
+ return OPTION_L;
+ }
+"\ -Ttext" {
+ yylval.name = ".text";
+ return OPTION_Texp;
+ }
+"\ -Tdata" {
+ yylval.name = ".data";
+ return OPTION_Texp;
+ }
+"\ -Tbss" {
+ yylval.name = ".bss";
+ return OPTION_Texp;
+ }
+
+"\ -T"{FILENAME} {
+ yylval.name = buystring(yytext+3);
+ return OPTION_Tfile;
+ }
+"\ -T" {
+ return OPTION_T;
+ }
+
+"\ -A"{FILENAME} {
+ yylval.name = buystring(yytext+3);
+ return OPTION_Aarch;
+ }
+" " { }
+"<<=" { RTOKEN(LSHIFTEQ);}
+">>=" { RTOKEN(RSHIFTEQ);}
+"||" { RTOKEN(OROR);}
+"==" { RTOKEN(EQ);}
+"!=" { RTOKEN(NE);}
+">=" { RTOKEN(GE);}
+"<=" { RTOKEN(LE);}
+"<<" { RTOKEN(LSHIFT);}
+">>" { RTOKEN(RSHIFT);}
+"+=" { RTOKEN(PLUSEQ);}
+"-=" { RTOKEN(MINUSEQ);}
+"*=" { RTOKEN(MULTEQ);}
+"/=" { RTOKEN(DIVEQ);}
+"&=" { RTOKEN(ANDEQ);}
+"|=" { RTOKEN(OREQ);}
+
+"&&" { RTOKEN(ANDAND);}
+">" { RTOKEN('>');}
+"," { RTOKEN(',');}
+"&" { RTOKEN('&');}
+"|" { RTOKEN('|');}
+"~" { RTOKEN('~');}
+"!" { RTOKEN('!');}
+"?" { RTOKEN('?');}
+"*" { RTOKEN('*');}
+"%" { RTOKEN('%');}
+"<" { RTOKEN('<');}
+"+" { RTOKEN('+');}
+">" { RTOKEN('>');}
+"}" { RTOKEN('}') ; }
+"{" { RTOKEN('{'); }
+")" { RTOKEN(')');}
+"(" { RTOKEN('(');}
+"]" { RTOKEN(']');}
+"[" { RTOKEN('[');}
+":" { RTOKEN(':'); }
+";" { RTOKEN(';');}
+"-" { RTOKEN('-');}
+"=" { RTOKEN('=');}
+
+
+"/*" {
+ while (1) {
+ int ch;
+ ch = input();
+ while (ch != '*') {
+ if (ch == '\n') {lineno++; }
+ ch = input();
+ }
+
+
+
+ if (input() == '/') {
+ break;
+ }
+ unput(yytext[yyleng-1]);
+ }
+}
+
+"\""[^\"]*"\"" {
+
+ yylval.name = buystring(yytext+1);
+ yylval.name[yyleng-2] = 0; /* Fry final quote */
+ return NAME;
+}
+[0][0-7KM]* {
+
+ yylval.integer = number(yytext+1, 8);
+ return INT;
+}
+
+[0-9]+[KM]? {
+ if (hex_mode == true) {
+ yylval.integer = number(yytext, 16);
+ }
+ else {
+ yylval.integer = number(yytext, 10);
+ }
+ return INT;
+}
+
+0[Xx][0-9a-fA-FKM]+ {
+
+ yylval.integer = number(yytext+2,16);
+ return INT;
+}
+
+"\#"{WHITE}*{FILENAMECHAR}+ {
+ char *p = yytext+1;
+ while(*p ==' ' || *p == '\t') p++;
+ yylval.name = buystring(p);
+ return NAME;
+}
+
+
+{FILENAMECHAR} {
+
+int ch;
+ keyword_type *k;
+ if (yytext[0] == '/' && ldgram_mustbe_symbolname)
+ { RTOKEN('/');}
+ ch = input();
+ while (true) {
+ if (isalpha(ch) || isdigit(ch) || ch == '.' || ch == '_') {
+ yytext[yyleng++] = ch;
+ }
+ else if (ch == '-' && ldgram_want_filename == true) {
+ yytext[yyleng++] = ch;
+ }
+ else if (ch == '+' && ldgram_want_filename == true) {
+ yytext[yyleng++] = ch;
+ }
+
+ else if (ch == '/' && ldgram_want_filename == true) {
+ yytext[yyleng++] = ch;
+ }
+
+ else break;
+ ch = input();
+ }
+
+ yytext[yyleng] = 0;
+ unput(ch);
+
+ for(k = keywords; k ->name != (char *)NULL; k++) {
+
+ if (strcmp(k->name, yytext)==0) {
+ yylval.token = k->value;
+ return k->value;
+ }
+ }
+ yylval.name = buystring(yytext);
+ return NAME;
+}
+
+
+
+
+
+%%
diff --git a/ld/ldmain.c b/ld/ldmain.c
new file mode 100644
index 0000000..3f9db08
--- /dev/null
+++ b/ld/ldmain.c
@@ -0,0 +1,806 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Written by Steve Chamberlain steve@cygnus.com
+ *
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:52 gumby
+ * Initial revision
+ *
+ * Revision 1.1 1991/03/13 00:48:27 chrisb
+ * Initial revision
+ *
+ * Revision 1.7 1991/03/10 19:15:45 sac
+ * Fixed a prototype problem
+ *
+ * Revision 1.6 1991/03/10 09:31:32 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:31:02 sac
+ * After a fatal info message, the output file is deleted.
+ *
+ * Revision 1.4 1991/03/06 02:28:31 sac
+ * Fixed partial linking and error messages.
+ *
+ * Revision 1.3 1991/02/22 17:15:02 sac
+ * Added RCS keywords and copyrights
+ *
+ *
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "config.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldwrite.h"
+#include "ldgram.h"
+#include "ldsym.h"
+#include "ldlang.h"
+#include "ld-emul.h"
+#include "ldlex.h"
+#include "ldfile.h"
+
+/* IMPORTS */
+extern boolean lang_has_input_file;
+
+/* EXPORTS */
+
+char *default_target;
+char *output_filename = "a.out";
+/* Name this program was invoked by. */
+char *program_name;
+
+/* The file that we're creating */
+bfd *output_bfd;
+
+extern boolean option_v;
+
+/* The local symbol prefix */
+char lprefix = 'L';
+
+/* Count the number of global symbols multiply defined. */
+int multiple_def_count;
+
+
+/* Count the number of symbols defined through common declarations.
+ This count is referenced in symdef_library, linear_library, and
+ modified by enter_global_ref.
+
+ It is incremented when a symbol is created as a common, and
+ decremented when the common declaration is overridden
+
+ Another way of thinking of it is that this is a count of
+ all ldsym_types with a ->scoms field
+*/
+unsigned int commons_pending;
+
+
+/* Count the number of global symbols referenced and not defined.
+ common symbols are not included in this count.
+ */
+
+unsigned int undefined_global_sym_count;
+
+
+
+/* Count the number of warning symbols encountered. */
+int warning_count;
+
+/* have we had a load script ? */
+extern boolean had_script;
+
+
+
+/* Nonzero means print names of input files as processed. */
+boolean trace_files;
+
+
+
+/* 1 => write load map. */
+boolean write_map;
+
+
+int unix_relocate;
+
+
+
+
+
+
+
+
+/* Force the make_executable to be output, even if there are non-fatal
+ errors */
+boolean force_make_executable;
+
+
+/* A count of the total number of local symbols ever seen - by adding
+ the symbol_count field of each newly read afile.*/
+
+
+unsigned int total_symbols_seen;
+
+/* A count of the number of read files - the same as the number of elements
+ in file_chain
+ */
+unsigned int total_files_seen;
+
+
+/* IMPORTS */
+args_type command_line;
+ld_config_type config;
+int
+main (argc, argv)
+ char **argv;
+ int argc;
+{
+ char *emulation;
+ program_name = argv[0];
+ output_filename = "a.out";
+
+ emulation = getenv(EMULATION_ENVIRON);
+
+ /* Initialize the data about options. */
+ strip_symbols = STRIP_NONE;
+ trace_files = false;
+ discard_locals = DISCARD_NONE;
+
+ write_map = false;
+ config.relocateable_output = false;
+ unix_relocate = 0;
+ command_line.force_common_definition = false;
+
+ ldfile_add_arch("");
+
+ config.make_executable = true;
+ force_make_executable = false;
+
+
+ /* Initialize the cumulative counts of symbols. */
+ undefined_global_sym_count = 0;
+ warning_count = 0;
+ multiple_def_count = 0;
+ commons_pending = 0;
+
+ config.magic_demand_paged = true ;
+ config.make_executable = true;
+
+ if (emulation == (char *)NULL) {
+ emulation= DEFAULT_EMULATION;
+ }
+ ldemul_choose_mode(emulation);
+
+ default_target = ldemul_choose_target();
+
+ lang_init();
+ ldemul_before_parse();
+
+ lang_has_input_file = false;
+ parse_args(argc, argv);
+
+ if (lang_has_input_file == false) {
+ info("%P%F: No input files\n");
+ }
+
+ ldemul_after_parse();
+
+ lang_process();
+
+
+
+
+ /* Print error messages for any missing symbols, for any warning
+ symbols, and possibly multiple definitions */
+
+ /* Print a map, if requested. */
+
+ if (write_map) {
+ ldsym_print_symbol_table ();
+ lang_map(stdout);
+ }
+
+
+ if (config.relocateable_output) {
+ output_bfd->flags &= ~( D_PAGED);
+ output_bfd->flags |= EXEC_P;
+ ldwrite();
+ bfd_close(output_bfd);
+ }
+ else {
+ output_bfd->flags |= EXEC_P;
+
+ ldwrite();
+ bfd_close(output_bfd);
+ if (config.make_executable == false && force_make_executable == false) {
+ unlink(output_filename);
+ }
+ return (!config.make_executable);
+ }
+
+ return(0);
+} /* main() */
+
+
+void
+Q_read_entry_symbols (desc, entry)
+ bfd *desc;
+ struct lang_input_statement_struct *entry;
+{
+ if (entry->asymbols == (asymbol **)NULL) {
+ size_t table_size = get_symtab_upper_bound(desc);
+ entry->asymbols = (asymbol **)ldmalloc(table_size);
+
+ entry->symbol_count = bfd_canonicalize_symtab(desc, entry->asymbols) ;
+ }
+}
+
+
+/*
+ * turn this item into a reference
+ */
+static void
+refize(sp, nlist_p)
+ldsym_type *sp;
+asymbol **nlist_p;
+{
+ asymbol *sym = *nlist_p;
+ sym->value = 0;
+ sym->flags = BSF_UNDEFINED;
+ sym->section = (asection *)NULL;
+ sym->udata =(void *)( sp->srefs_chain);
+ sp->srefs_chain = nlist_p;
+}
+/*
+This function is called for each name which is seen which has a global
+scope. It enters the name into the global symbol table in the correct
+symbol on the correct chain. Remember that each ldsym_type has three
+chains attatched, one of all definitions of a symbol, one of all
+references of a symbol and one of all common definitions of a symbol.
+
+When the function is over, the supplied is left connected to the bfd
+to which is was born, with its udata field pointing to the next member
+on the chain in which it has been inserted.
+
+A certain amount of jigery pokery is necessary since commons come
+along and upset things, we only keep one item in the common chain; the
+one with the biggest size seen sofar. When another common comes along
+it either bumps the previous definition into the ref chain, since it
+is bigger, or gets turned into a ref on the spot since the one on the
+common chain is already bigger. If a real definition comes along then
+the common gets bumped off anyway.
+
+Whilst all this is going on we keep a count of the number of multiple
+definitions seen, undefined global symbols and pending commons.
+*/
+
+
+void
+Q_enter_global_ref (nlist_p)
+ asymbol **nlist_p;
+
+{
+ asymbol *sym = *nlist_p;
+ char *name = sym->name;
+ ldsym_type *sp = ldsym_get (name);
+
+ flagword this_symbol_flags = sym->flags;
+
+
+ ASSERT(sym->udata == 0);
+
+ /* Just place onto correct chain */
+ if (flag_is_common(this_symbol_flags)) {
+ /* If we have a definition of this symbol already then
+ * this common turns into a reference. Also we only
+ * ever point to the largest common, so if we
+ * have a common, but it's bigger that the new symbol
+ * the turn this into a reference too.
+ */
+ if (sp->sdefs_chain)
+ {
+ /* This is a common symbol, but we already have a definition
+ for it, so just link it into the ref chain as if
+ it were a reference
+ */
+ refize(sp, nlist_p);
+ }
+ else if (sp->scoms_chain) {
+ /* If we have a previous common, keep only the biggest */
+ if ( (*(sp->scoms_chain))->value > sym->value) {
+ /* other common is bigger, throw this one away */
+ refize(sp, nlist_p);
+ }
+ else if (sp->scoms_chain != nlist_p) {
+ /* other common is smaller, throw that away */
+ refize(sp, sp->scoms_chain);
+ sp->scoms_chain = nlist_p;
+ }
+ }
+ else {
+ /* This is the first time we've seen a common, so
+ * remember it - if it was undefined before, we know it's defined now
+ */
+ if (sp->srefs_chain)
+ undefined_global_sym_count--;
+
+ commons_pending++;
+ sp->scoms_chain = nlist_p;
+ }
+ }
+
+ else if (flag_is_defined(this_symbol_flags)) {
+ /* This is the definition of a symbol, add to def chain */
+ if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) {
+ /* Multiple definition */
+ asymbol *sy = *(sp->sdefs_chain);
+ lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
+ lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
+ asymbol ** stat1_symbols = stat1 ? stat1->asymbols: 0;
+ asymbol ** stat_symbols = stat ? stat->asymbols:0;
+
+ multiple_def_count++;
+ info("%C: multiple definition of `%T'\n",
+ sym->the_bfd,
+ sym->section,
+ stat1_symbols,
+ sym->value,
+ sym);
+
+ info("%C: first seen here\n",
+ sy->the_bfd,
+ sy->section,
+ stat_symbols,
+ sy->value);
+ }
+ else {
+ sym->udata =(void *)( sp->sdefs_chain);
+ sp->sdefs_chain = nlist_p;
+ }
+ /* A definition overrides a common symbol */
+ if (sp->scoms_chain) {
+ refize(sp, sp->scoms_chain);
+ sp->scoms_chain = 0;
+ commons_pending--;
+ }
+ else if (sp->srefs_chain) {
+ /* If previously was undefined, then remember as defined */
+ undefined_global_sym_count--;
+ }
+ }
+ else {
+ if (sp->scoms_chain == (asymbol **)NULL
+ && sp->srefs_chain == (asymbol **)NULL
+ && sp->sdefs_chain == (asymbol **)NULL) {
+ /* And it's the first time we've seen it */
+ undefined_global_sym_count++;
+
+ }
+
+ refize(sp, nlist_p);
+ }
+
+ ASSERT(sp->sdefs_chain == 0 || sp->scoms_chain == 0);
+ ASSERT(sp->scoms_chain ==0 || (*(sp->scoms_chain))->udata == 0);
+
+
+}
+
+static void
+Q_enter_file_symbols (entry)
+lang_input_statement_type *entry;
+{
+ asymbol **q ;
+ entry->common_section =
+ bfd_make_section(entry->the_bfd, "COMMON");
+
+ ldlang_add_file(entry);
+
+
+ if (trace_files || option_v) {
+ info("%I\n", entry);
+ }
+
+ total_symbols_seen += entry->symbol_count;
+ total_files_seen ++;
+ for (q = entry->asymbols; *q; q++)
+ {
+ asymbol *p = *q;
+
+ if (flag_is_undefined_or_global_or_common(p->flags))
+ {
+
+ Q_enter_global_ref(q);
+ }
+ ASSERT(p->flags != 0);
+ }
+}
+
+
+
+/* Searching libraries */
+
+struct lang_input_statement_struct *decode_library_subfile ();
+void linear_library (), symdef_library ();
+
+/* Search the library ENTRY, already open on descriptor DESC.
+ This means deciding which library members to load,
+ making a chain of `struct lang_input_statement_struct' for those members,
+ and entering their global symbols in the hash table. */
+
+void
+search_library (entry)
+ struct lang_input_statement_struct *entry;
+{
+
+ /* No need to load a library if no undefined symbols */
+ if (!undefined_global_sym_count) return;
+
+ if (bfd_has_map(entry->the_bfd))
+ symdef_library (entry);
+ else
+ linear_library (entry);
+
+}
+
+
+void
+Q_read_file_symbols (entry)
+struct lang_input_statement_struct *entry;
+{
+ if (entry->asymbols == (asymbol **)NULL
+ &&entry->real == true
+ && entry->filename != (char *)NULL)
+ {
+ ldfile_open_file (entry);
+
+ if (bfd_check_format(entry->the_bfd, bfd_object))
+ {
+ entry->the_bfd->usrdata = (void*)entry;
+
+
+ Q_read_entry_symbols (entry->the_bfd, entry);
+ Q_enter_file_symbols (entry);
+ }
+ else if (bfd_check_format(entry->the_bfd, bfd_archive))
+ {
+ entry->the_bfd->usrdata = (void *)entry;
+
+ entry->subfiles = (lang_input_statement_type *)NULL;
+ search_library (entry);
+ }
+ else
+ {
+ info("%F%I: malformed input file (not rel or archive) \n", entry);
+ }
+ }
+
+}
+
+
+/* Construct and return a lang_input_statement_struct for a library member.
+ The library's lang_input_statement_struct is library_entry,
+ and the library is open on DESC.
+ SUBFILE_OFFSET is the byte index in the library of this member's header.
+ We store the length of the member into *LENGTH_LOC. */
+
+lang_input_statement_type *
+decode_library_subfile (library_entry, subfile_offset)
+ struct lang_input_statement_struct *library_entry;
+ bfd *subfile_offset;
+{
+ register struct lang_input_statement_struct *subentry;
+ subentry = (struct lang_input_statement_struct *) ldmalloc (sizeof (struct lang_input_statement_struct));
+ subentry->filename = subfile_offset -> filename;
+ subentry->local_sym_name = subfile_offset->filename;
+ subentry->asymbols = 0;
+ subentry->the_bfd = subfile_offset;
+ subentry->subfiles = 0;
+ subentry->next = 0;
+ subentry->superfile = library_entry;
+ subentry->is_archive = false;
+ subentry->header_read_flag = false;
+ subentry->just_syms_flag = false;
+ subentry->loaded = false;
+ subentry->chain = 0;
+
+ return subentry;
+}
+
+boolean subfile_wanted_p ();
+void
+clear_syms(entry, offset)
+struct lang_input_statement_struct *entry;
+file_ptr offset;
+{
+ carsym *car;
+ unsigned long indx = bfd_get_next_mapent(entry->the_bfd,
+ BFD_NO_MORE_SYMBOLS,
+ &car);
+ while (indx != BFD_NO_MORE_SYMBOLS) {
+ if (car->file_offset == offset) {
+ car->name = 0;
+ }
+ indx = bfd_get_next_mapent(entry->the_bfd, indx, &car);
+ }
+
+}
+
+/* Search a library that has a map
+ */
+void
+symdef_library (entry)
+ struct lang_input_statement_struct *entry;
+
+{
+ register struct lang_input_statement_struct *prev = 0;
+
+ boolean not_finished = true;
+
+
+ while (not_finished == true)
+ {
+ carsym *exported_library_name;
+ bfd *prev_archive_member_bfd = 0;
+
+ int idx = bfd_get_next_mapent(entry->the_bfd,
+ BFD_NO_MORE_SYMBOLS,
+ &exported_library_name);
+
+ not_finished = false;
+
+ while (idx != BFD_NO_MORE_SYMBOLS && undefined_global_sym_count)
+ {
+
+ if (exported_library_name->name)
+ {
+
+ ldsym_type *sp = ldsym_get_soft (exported_library_name->name);
+
+ /* If we find a symbol that appears to be needed, think carefully
+ about the archive member that the symbol is in. */
+ /* So - if it exists, and is referenced somewhere and is
+ undefined or */
+ if (sp && sp->srefs_chain && !sp->sdefs_chain)
+ {
+ bfd *archive_member_bfd = bfd_get_elt_at_index(entry->the_bfd, idx);
+ struct lang_input_statement_struct *archive_member_lang_input_statement_struct;
+
+ if (archive_member_bfd && bfd_check_format(archive_member_bfd, bfd_object))
+ {
+
+ /* Don't think carefully about any archive member
+ more than once in a given pass. */
+ if (prev_archive_member_bfd != archive_member_bfd)
+ {
+
+ prev_archive_member_bfd = archive_member_bfd;
+
+ /* Read the symbol table of the archive member. */
+
+ if (archive_member_bfd->usrdata != (void *)NULL) {
+
+ archive_member_lang_input_statement_struct =(lang_input_statement_type *) archive_member_bfd->usrdata;
+ }
+ else {
+
+ archive_member_lang_input_statement_struct =
+ decode_library_subfile (entry, archive_member_bfd);
+ archive_member_bfd->usrdata = (void *) archive_member_lang_input_statement_struct;
+
+ }
+
+ if (archive_member_lang_input_statement_struct == 0) {
+ info ("%F%I contains invalid archive member %s\n",
+ entry,
+ sp->name);
+ }
+
+ if (archive_member_lang_input_statement_struct->loaded == false)
+ {
+
+ Q_read_entry_symbols (archive_member_bfd, archive_member_lang_input_statement_struct);
+ /* Now scan the symbol table and decide whether to load. */
+
+
+ if (subfile_wanted_p (archive_member_lang_input_statement_struct) == true)
+
+ {
+ /* This member is needed; load it.
+ Since we are loading something on this pass,
+ we must make another pass through the symdef data. */
+
+ not_finished = true;
+
+ Q_enter_file_symbols (archive_member_lang_input_statement_struct);
+
+ if (prev)
+ prev->chain = archive_member_lang_input_statement_struct;
+ else
+ entry->subfiles = archive_member_lang_input_statement_struct;
+
+
+ prev = archive_member_lang_input_statement_struct;
+
+
+ /* Clear out this member's symbols from the symdef data
+ so that following passes won't waste time on them. */
+ clear_syms(entry, exported_library_name->file_offset);
+ archive_member_lang_input_statement_struct->loaded = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ idx = bfd_get_next_mapent(entry->the_bfd, idx, &exported_library_name);
+ }
+ }
+}
+
+void
+linear_library (entry)
+struct lang_input_statement_struct *entry;
+{
+ boolean more_to_do = true;
+ register struct lang_input_statement_struct *prev = 0;
+
+ while (more_to_do) {
+
+ bfd * archive = bfd_openr_next_archived_file(entry->the_bfd,0);
+
+ more_to_do = false;
+ while (archive) {
+ if (bfd_check_format(archive, bfd_object))
+ {
+ register struct lang_input_statement_struct *subentry;
+
+ subentry = decode_library_subfile (entry,
+ archive);
+
+ archive->usrdata = (void *) subentry;
+ if (!subentry) return;
+ if (subentry->loaded == false) {
+ Q_read_entry_symbols (archive, subentry);
+
+ if (subfile_wanted_p (subentry) == true)
+ {
+ Q_enter_file_symbols (subentry);
+
+ if (prev)
+ prev->chain = subentry;
+ else
+ entry->subfiles = subentry;
+ prev = subentry;
+
+ more_to_do = true;
+ subentry->loaded = true;
+ }
+ }
+ }
+ archive = bfd_openr_next_archived_file(entry->the_bfd,archive);
+
+ }
+
+ }
+}
+
+ /* ENTRY is an entry for a library member.
+ Its symbols have been read into core, but not entered.
+ Return nonzero if we ought to load this member. */
+
+boolean
+subfile_wanted_p (entry)
+struct lang_input_statement_struct *entry;
+{
+ asymbol **q;
+
+ for (q = entry->asymbols; *q; q++)
+ {
+ asymbol *p = *q;
+
+ /* If the symbol has an interesting definition, we could
+ potentially want it. */
+
+ if (p->flags & BSF_FORT_COMM
+ || p->flags & BSF_GLOBAL)
+ {
+ register ldsym_type *sp = ldsym_get_soft (p->name);
+
+
+ /* If this symbol has not been hashed,
+ we can't be looking for it. */
+ if (sp != (ldsym_type *)NULL
+ && sp->sdefs_chain == (asymbol **)NULL) {
+ if (sp->srefs_chain != (asymbol **)NULL
+ || sp->scoms_chain != (asymbol **)NULL)
+ {
+ /* This is a symbol we are looking for. It is either
+ not yet defined or common. */
+
+ if (flag_is_common(p->flags))
+ {
+ /* This libary member has something to
+ say about this element. We should
+ remember if its a new size */
+ /* Move something from the ref list to the com list */
+ if(sp->scoms_chain) {
+ /* Already a common symbol, maybe update it */
+ if (p->value > (*(sp->scoms_chain))->value) {
+ (*(sp->scoms_chain))->value = p->value;
+ }
+ }
+ else {
+ /* Take a value from the ref chain
+ Here we are moving a symbol from the owning bfd
+ to another bfd. We must set up the
+ common_section portion of the bfd thing */
+
+
+
+ sp->scoms_chain = sp->srefs_chain;
+ sp->srefs_chain =
+ (asymbol **)((*(sp->srefs_chain))->udata);
+ (*(sp->scoms_chain))->udata = (void*)NULL;
+
+ (*( sp->scoms_chain))->flags = BSF_FORT_COMM;
+ commons_pending++;
+ undefined_global_sym_count--;
+ } {
+ asymbol *com = *(sp->scoms_chain);
+ if (((lang_input_statement_type *)
+ (com->the_bfd->usrdata))->common_section ==
+ (asection *)NULL) {
+ ((lang_input_statement_type *)
+ (com->the_bfd->usrdata))->common_section =
+ bfd_make_section(com->the_bfd, "COMMON");
+ }
+ }
+ ASSERT(p->udata == 0);
+ }
+
+ else {
+ if (write_map)
+ {
+ info("%I needed due to %s\n",entry, sp->name);
+ }
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/ld/ldmain.h b/ld/ldmain.h
new file mode 100644
index 0000000..9f3fa1a
--- /dev/null
+++ b/ld/ldmain.h
@@ -0,0 +1,23 @@
+/* ldmain.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+PROTO(void, Q_enter_global_ref,(asymbol **));
+PROTO(void, Q_read_file_symbols,(struct lang_input_statement_struct *));
+
diff --git a/ld/ldmisc.c b/ld/ldmisc.c
new file mode 100644
index 0000000..2f73066
--- /dev/null
+++ b/ld/ldmisc.c
@@ -0,0 +1,303 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:55 gumby
+ * Initial revision
+ *
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:30 chrisb
+ * Initial revision
+ *
+ * Revision 1.7 1991/03/10 09:31:34 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.6 1991/03/09 03:31:01 sac
+ * After a fatal info message, the output file is deleted.
+ *
+ * Revision 1.5 1991/03/06 21:59:54 sac
+ * Made %C print function name if available
+ *
+ * Revision 1.4 1991/03/06 02:27:45 sac
+ * Added support for linenumber printing via %C
+ *
+ * Revision 1.3 1991/02/22 17:15:03 sac
+ * Added RCS keywords and copyrights
+ *
+ */
+
+/*
+ ldmisc.c
+
+*/
+
+#include "sysdep.h"
+#include <varargs.h>
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+
+/* IMPORTS */
+
+extern char *program_name;
+
+extern FILE *ldlex_input_stack;
+extern char *ldfile_input_filename;
+extern ld_config_type config;
+
+void
+yyerror(arg)
+char *arg;
+{
+ info("%P%F: %S %s\n",arg);
+}
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+/*
+ %F error is fatal
+ %P print progam name
+ %S print script file and linenumber
+ %E current bfd error or errno
+ %I filename from a lang_input_statement_type
+ %B filename from a bfd
+ %T symbol table entry
+ %X no object output, fail return
+ %V hex bfd_vma
+ %C Clever filename:linenumber
+ %
+*/
+void info(va_alist)
+va_dcl
+{
+ char *fmt;
+ boolean fatal = false;
+ va_list arg;
+ va_start(arg);
+ fmt = va_arg(arg, char *);
+ while (*fmt) {
+ while (*fmt != '%' && *fmt != '\0') {
+ fputc(*fmt, stderr);
+ fmt++;
+ }
+ if (*fmt == '%') {
+ fmt ++;
+ switch (*fmt++) {
+ case 'X':
+ config.make_executable = false;
+ break;
+ case 'V':
+ fprintf(stderr,"%08lx", va_arg(arg, bfd_vma));
+ break;
+ case 'T':
+ {
+ asymbol *symbol = va_arg(arg, asymbol *);
+ if (symbol) {
+ asection *section = symbol->section;
+ if ((symbol->flags & BSF_UNDEFINED) == 0) {
+ char *section_name = section == (asection *)NULL ?
+ "absolute" : section->name;
+ fprintf(stderr,"%s (%s)", symbol->name, section_name);
+ }
+ else {
+ fprintf(stderr,"%s", symbol->name);
+ }
+ }
+ else {
+ fprintf(stderr,"no symbol");
+ }
+ }
+ break;
+ case 'B':
+ {
+ bfd *abfd = va_arg(arg, bfd *);
+ if (abfd->my_archive) {
+ fprintf(stderr,"%s(%s)", abfd->my_archive->filename,
+ abfd->filename);
+ }
+ else {
+ fprintf(stderr,"%s", abfd->filename);
+
+ }
+ }
+ break;
+ case 'F':
+ fatal = true;
+ break;
+ case 'P':
+ fprintf(stderr,"%s", program_name);
+ break;
+ case 'E':
+ /* Replace with the most recent errno explanation */
+
+
+ fprintf(stderr, bfd_errmsg(bfd_error));
+
+
+ break;
+ case 'I':
+ {
+ lang_input_statement_type *i =
+ va_arg(arg,lang_input_statement_type *);
+
+ fprintf(stderr,"%s", i->local_sym_name);
+ }
+ break;
+ case 'S':
+ /* Print source script file and line number */
+
+ if (ldlex_input_stack) {
+ extern unsigned int lineno;
+ if (ldfile_input_filename == (char *)NULL) {
+ fprintf(stderr,"command line");
+ }
+ else {
+ fprintf(stderr,"%s:%u", ldfile_input_filename, lineno + 1);
+ }
+ }
+ else {
+ fprintf(stderr,"command line ");
+ }
+ break;
+ case 'C':
+ {
+ char *filename;
+ char *functionname;
+ unsigned int linenumber;
+ bfd *abfd = va_arg(arg, bfd *);
+ asection *section = va_arg(arg, asection *);
+ asymbol **symbols = va_arg(arg, asymbol **);
+ bfd_vma offset = va_arg(arg, bfd_vma);
+
+ if (bfd_find_nearest_line(abfd,
+ section,
+ symbols,
+ offset,
+ &filename,
+ &functionname,
+ &linenumber))
+ {
+ if (filename == (char *)NULL)
+ filename = abfd->filename;
+ if (functionname != (char *)NULL)
+ fprintf(stderr,"%s:%u: (%s)", filename, linenumber, functionname);
+ else if (linenumber != 0)
+ fprintf(stderr,"%s:%u", filename, linenumber);
+ else
+ fprintf(stderr,"%s", filename);
+
+ }
+ else {
+ fprintf(stderr,"%s", abfd->filename);
+ }
+ }
+ break;
+
+ case 's':
+ fprintf(stderr,"%s", va_arg(arg, char *));
+ break;
+ case 'd':
+ fprintf(stderr,"%d", va_arg(arg, int));
+ break;
+ default:
+ fprintf(stderr,"%s", va_arg(arg, char *));
+ break;
+ }
+ }
+ }
+ if (fatal == true) {
+ extern char *output_filename;
+ if (output_filename)
+ unlink(output_filename);
+ exit(1);
+ }
+ va_end(arg);
+}
+
+
+void
+info_assert(file, line)
+char *file;
+unsigned int line;
+{
+ info("%F%P internal error %s %d\n", file,line);
+}
+
+/* Return a newly-allocated string
+ whose contents concatenate those of S1, S2, S3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ size_t len1 = strlen (s1);
+ size_t len2 = strlen (s2);
+ size_t len3 = strlen (s3);
+ char *result = ldmalloc (len1 + len2 + len3 + 1);
+
+ if (len1 != 0)
+ memcpy(result, s1, len1);
+ if (len2 != 0)
+ memcpy(result+len1, s2, len2);
+ if (len3 != 0)
+ memcpy(result+len1+len2, s2, len3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+
+
+char *ldmalloc (size)
+size_t size;
+{
+ char * result = malloc (size);
+
+ if (result == (char *)NULL && size != 0)
+ info("%F%P virtual memory exhausted\n");
+
+ return result;
+}
+
+
+
+char *buystring(x)
+char *x;
+{
+ size_t l = strlen(x)+1;
+ char *r = ldmalloc(l);
+ memcpy(r, x,l);
+ return r;
+}
diff --git a/ld/ldmisc.h b/ld/ldmisc.h
new file mode 100644
index 0000000..e3463d1
--- /dev/null
+++ b/ld/ldmisc.h
@@ -0,0 +1,34 @@
+/* ldmisc.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+/* VARARGS*/
+PROTO(void,info,());
+PROTO(void,info_assert,(char *, unsigned int));
+PROTO(void,yyerror,(char *));
+PROTO(char *,concat,(char *, char *, char *));
+PROTO(char *, ldmalloc,(size_t));
+PROTO(char *,buystring,(char *));
+#define ASSERT(x) \
+{ if (!(x)) info_assert(__FILE__,__LINE__); }
+
+#define FAIL() \
+{ info_assert(__FILE__,__LINE__); }
diff --git a/ld/ldsym.c b/ld/ldsym.c
new file mode 100644
index 0000000..796060c
--- /dev/null
+++ b/ld/ldsym.c
@@ -0,0 +1,452 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:28:58 gumby
+ * Initial revision
+ *
+ * Revision 1.1 1991/03/13 00:48:32 chrisb
+ * Initial revision
+ *
+ * Revision 1.4 1991/03/10 09:31:36 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3 1991/03/06 02:28:56 sac
+ * Cleaned up
+ *
+ * Revision 1.2 1991/02/22 17:15:06 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ Written by Steve Chamberlain steve@cygnus.com
+
+ All symbol handling for the linker
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldsym.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+/* IMPORT */
+
+extern bfd *output_bfd;
+/* Head and tail of global symbol table chronological list */
+
+ldsym_type *symbol_head = (ldsym_type *)NULL;
+ldsym_type **symbol_tail_ptr = &symbol_head;
+
+/*
+ incremented for each symbol in the ldsym_type table
+ no matter what flavour it is
+*/
+unsigned int global_symbol_count;
+
+/* IMPORTS */
+
+extern boolean option_longmap ;
+
+/* LOCALS */
+#define TABSIZE 1009
+static ldsym_type *global_symbol_hash_table[TABSIZE];
+
+/* Compute the hash code for symbol name KEY. */
+
+int
+hash_string (key)
+ char *key;
+{
+ register char *cp;
+ register int k;
+
+ cp = key;
+ k = 0;
+ while (*cp)
+ k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
+
+ return k;
+}
+
+/* Get the symbol table entry for the global symbol named KEY.
+ Create one if there is none. */
+ldsym_type *
+ldsym_get (key)
+ char *key;
+{
+ register int hashval;
+ register ldsym_type *bp;
+
+ /* Determine the proper bucket. */
+
+ hashval = hash_string (key) % TABSIZE;
+
+ /* Search the bucket. */
+
+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+ if (! strcmp (key, bp->name))
+ return bp;
+
+ /* Nothing was found; create a new symbol table entry. */
+
+ bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
+ bp->srefs_chain = (asymbol **)NULL;
+ bp->sdefs_chain = (asymbol **)NULL;
+ bp->scoms_chain = (asymbol **)NULL;
+ bp->name = (char *) ldmalloc (strlen (key) + 1);
+ strcpy (bp->name, key);
+
+
+
+
+ /* Add the entry to the bucket. */
+
+ bp->link = global_symbol_hash_table[hashval];
+ global_symbol_hash_table[hashval] = bp;
+
+ /* Keep the chronological list up to date too */
+ *symbol_tail_ptr = bp;
+ symbol_tail_ptr = &bp->next;
+ bp->next = 0;
+ global_symbol_count++;
+
+ return bp;
+}
+
+/* Like `ldsym_get' but return 0 if the symbol is not already known. */
+
+ldsym_type *
+ldsym_get_soft (key)
+ char *key;
+{
+ register int hashval;
+ register ldsym_type *bp;
+
+ /* Determine which bucket. */
+
+ hashval = hash_string (key) % TABSIZE;
+
+ /* Search the bucket. */
+
+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+ if (! strcmp (key, bp->name))
+ return bp;
+
+ return 0;
+}
+
+
+
+
+
+static void
+list_file_locals (entry)
+lang_input_statement_type *entry;
+{
+ asymbol **q;
+ fprintf (stderr, "\nLocal symbols of ");
+ info("%I", entry);
+ fprintf (stderr, ":\n\n");
+ if (entry->asymbols) {
+ for (q = entry->asymbols; *q; q++)
+ {
+ asymbol *p = *q;
+ /* If this is a definition,
+ update it if necessary by this file's start address. */
+ if (p->flags & BSF_LOCAL)
+ info(" %V %s\n",p->value, p->name);
+ }
+ }
+}
+
+
+static void
+print_file_stuff(f)
+lang_input_statement_type *f;
+{
+ fprintf (stderr, " %s", f->filename);
+ fprintf (stderr, " ");
+ if (f->just_syms_flag)
+ {
+ fprintf (stderr, " symbols only\n");
+ }
+ else
+ {
+ asection *s;
+ if (option_longmap) {
+ for (s = f->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
+ s->output_offset,
+ (unsigned)s->size, s->alignment_power, s->name);
+ }
+ }
+ else {
+ for (s = f->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ fprintf (stderr, "%s %lx(%x) ",
+ s->name,
+ s->output_offset,
+ (unsigned) s->size);
+ }
+ fprintf (stderr, "hex \n");
+ }
+ }
+}
+
+void
+ldsym_print_symbol_table ()
+{
+ fprintf (stderr, "\nFiles:\n\n");
+
+ lang_for_each_file(print_file_stuff);
+
+ fprintf (stderr, "\nGlobal symbols:\n\n");
+ {
+ register ldsym_type *sp;
+
+ for (sp = symbol_head; sp; sp = sp->next)
+ {
+ if (sp->sdefs_chain)
+ {
+ asymbol *defsym = *(sp->sdefs_chain);
+ asection *defsec = bfd_get_section(defsym);
+ fprintf(stderr,"%08lx ",defsym->value);
+ if (defsec)
+ {
+ fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
+ fprintf(stderr,
+ "%7s",
+ bfd_section_name(output_bfd,
+ defsec));
+
+ }
+ else
+ {
+ fprintf(stderr," .......");
+ }
+
+ }
+ else {
+ fprintf(stderr,"undefined");
+ }
+
+
+ if (sp->scoms_chain) {
+ fprintf(stderr, " common size %5lu %s",
+ (*(sp->scoms_chain))->value, sp->name);
+ }
+ if (sp->sdefs_chain) {
+ fprintf(stderr, " symbol def %08lx %s",
+ (*(sp->sdefs_chain))->value,
+ sp->name);
+ }
+ else {
+ fprintf(stderr, " undefined %s",
+ sp->name);
+ }
+ fprintf(stderr, "\n");
+
+ }
+ }
+ lang_for_each_file(list_file_locals);
+}
+
+extern lang_output_section_statement_type *create_object_symbols;
+extern char lprefix;
+static asymbol **
+write_file_locals(output_buffer)
+asymbol **output_buffer;
+{
+LANG_FOR_EACH_INPUT_STATEMENT(entry)
+ {
+ /* Run trough the symbols and work out what to do with them */
+ unsigned int i;
+
+ /* Add one for the filename symbol if needed */
+ if (create_object_symbols
+ != (lang_output_section_statement_type *)NULL) {
+ asection *s;
+ for (s = entry->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ if (s->output_section == create_object_symbols->bfd_section) {
+ /* Add symbol to this section */
+ asymbol * newsym =
+ (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
+ newsym->name = entry->local_sym_name;
+ /* The symbol belongs to the output file's text section */
+
+ /* The value is the start of this section in the output file*/
+ newsym->value = 0;
+ newsym->flags = BSF_LOCAL;
+ newsym->section = s;
+ *output_buffer++ = newsym;
+ break;
+ }
+ }
+ }
+ for (i = 0; i < entry->symbol_count; i++)
+ {
+ asymbol *p = entry->asymbols[i];
+
+ if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
+ {
+ /* We are only interested in outputting
+ globals at this stage in special circumstances */
+ if (p->the_bfd == entry->the_bfd
+ && flag_is_not_at_end(p->flags)) {
+ /* And this is one of them */
+ *(output_buffer++) = p;
+ p->flags |= BSF_KEEP;
+ }
+ }
+ else {
+ if (flag_is_ordinary_local(p->flags))
+ {
+ if (discard_locals == DISCARD_ALL)
+ { }
+ else if (discard_locals == DISCARD_L &&
+ (p->name[0] == lprefix))
+ { }
+ else if (p->flags == BSF_WARNING)
+ { }
+ else
+ { *output_buffer++ = p; }
+ }
+ else if (flag_is_debugger(p->flags))
+ {
+ /* Only keep the debugger symbols if no stripping required */
+ if (strip_symbols == STRIP_NONE) {
+ *output_buffer++ = p;
+ }
+ }
+ else if (flag_is_undefined(p->flags))
+ { /* This must be global */
+ }
+ else if (flag_is_common(p->flags)) {
+ /* And so must this */
+ }
+ else if (p->flags & BSF_CTOR) {
+ /* Throw it away */
+ }
+else
+ {
+ FAIL();
+ }
+ }
+ }
+
+
+ }
+ return output_buffer;
+}
+
+
+static asymbol **
+write_file_globals(symbol_table)
+asymbol **symbol_table;
+{
+ FOR_EACH_LDSYM(sp)
+ {
+ if (sp->sdefs_chain != (asymbol **)NULL) {
+ asymbol *bufp = (*(sp->sdefs_chain));
+
+ if ((bufp->flags & BSF_KEEP) ==0) {
+ ASSERT(bufp != (asymbol *)NULL);
+
+ bufp->name = sp->name;
+
+ if (sp->scoms_chain != (asymbol **)NULL)
+
+ {
+ /*
+ defined as common but not allocated, this happens
+ only with -r and not -d, write out a common
+ definition
+ */
+ bufp = *(sp->scoms_chain);
+ }
+ *symbol_table++ = bufp;
+ }
+ }
+ else if (sp->scoms_chain != (asymbol **)NULL) {
+ /* This symbol is a common - just output */
+ asymbol *bufp = (*(sp->scoms_chain));
+ *symbol_table++ = bufp;
+ }
+ else if (sp->srefs_chain != (asymbol **)NULL) {
+ /* This symbol is undefined but has a reference */
+ asymbol *bufp = (*(sp->srefs_chain));
+ *symbol_table++ = bufp;
+ }
+ else {
+ /*
+ This symbol has neither defs nor refs, it must have come
+ from the command line, since noone has used it it has no
+ data attatched, so we'll ignore it
+ */
+ }
+ }
+ return symbol_table;
+}
+
+
+
+void
+ldsym_write()
+{
+ if (strip_symbols != STRIP_ALL) {
+ /* We know the maximum size of the symbol table -
+ it's the size of all the global symbols ever seen +
+ the size of all the symbols from all the files +
+ the number of files (for the per file symbols)
+ +1 (for the null at the end)
+ */
+ extern unsigned int total_files_seen;
+ extern unsigned int total_symbols_seen;
+
+ asymbol ** symbol_table = (asymbol **)
+ ldmalloc ((size_t)(global_symbol_count +
+ total_files_seen +
+ total_symbols_seen + 1) * sizeof (asymbol *));
+ asymbol ** tablep = write_file_locals(symbol_table);
+
+ tablep = write_file_globals(tablep);
+
+ *tablep = (asymbol *)NULL;
+ bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
+ }
+}
diff --git a/ld/ldwrite.c b/ld/ldwrite.c
new file mode 100644
index 0000000..a4282b3
--- /dev/null
+++ b/ld/ldwrite.c
@@ -0,0 +1,441 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GLD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 1991/03/21 21:29:04 gumby
+ * Initial revision
+ *
+ * Revision 1.2 1991/03/15 18:45:55 rich
+ * foo
+ *
+ * Revision 1.1 1991/03/13 00:48:37 chrisb
+ * Initial revision
+ *
+ * Revision 1.7 1991/03/10 19:15:03 sac
+ * Took out the abort() which had been put in the wrong place
+ * Updated the version #.
+ *
+ * Revision 1.6 1991/03/10 09:31:41 rich
+ * Modified Files:
+ * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5 1991/03/09 03:25:08 sac
+ * Added support for LONG, SHORT and BYTE keywords in scripts
+ *
+ * Revision 1.4 1991/03/06 21:59:34 sac
+ * Completed G++ support
+ *
+ * Revision 1.3 1991/03/06 02:29:52 sac
+ * Added support for partial linking.
+ *
+ * Revision 1.2 1991/02/22 17:15:11 sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/*
+ This module writes out the final image by reading sections from the
+ input files, relocating them and writing them out
+
+ There are two main paths through this module, one for normal
+ operation and one for partial linking.
+
+ During normal operation, raw section data is read along with the
+ associated relocation information, the relocation info applied and
+ the section data written out on a section by section basis.
+
+ When partially linking, all the relocation records are read to work
+ out how big the output relocation vector will be. Then raw data is
+ read, relocated and written section by section.
+
+ Written by Steve Chamberlain steve@cygnus.com
+
+*/
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ldlang.h"
+#include "ld.h"
+#include "ldwrite.h"
+#include "ldmisc.h"
+#include "ldsym.h"
+#include "ldgram.tab.h"
+
+
+
+char *ldmalloc();
+/* Static vars for do_warnings and subroutines of it */
+int list_unresolved_refs; /* List unresolved refs */
+int list_warning_symbols; /* List warning syms */
+int list_multiple_defs; /* List multiple definitions */
+extern int errno;
+extern char *sys_errlist[];
+
+extern unsigned int undefined_global_sym_count;
+
+extern bfd *output_bfd;
+
+extern struct lang_output_section_statement_struct * create_object_symbols;
+
+extern char lprefix;
+
+#ifdef __STDC__
+void lang_for_each_statement(void (*func)());
+#else /* __STDC__ */
+void lang_for_each_statement();
+#endif /* __STDC__ */
+
+extern size_t largest_section;
+ld_config_type config;
+
+extern unsigned int global_symbol_count;
+
+boolean trace_files;
+
+static void perform_relocation(input_bfd,
+ input_section,
+ data,
+ symbols)
+bfd *input_bfd;
+asection *input_section;
+void *data;
+asymbol **symbols;
+{
+ static asymbol *error_symbol = (asymbol *)NULL;
+ static unsigned int error_count = 0;
+#define MAX_ERRORS_IN_A_ROW 5
+ size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
+
+ arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
+ arelent **parent;
+ bfd *ob = output_bfd;
+ asection *os = input_section->output_section;
+ if (config.relocateable_output == false) ob = (bfd *)NULL;
+
+ if (bfd_canonicalize_reloc(input_bfd,
+ input_section,
+ reloc_vector,
+ symbols) )
+ {
+ for (parent = reloc_vector; *parent; parent++)
+ {
+
+ bfd_reloc_status_enum_type r=
+ bfd_perform_relocation(input_bfd,
+ *parent,
+ data,
+ input_section,
+ ob);
+
+ if (r == bfd_reloc_ok) {
+ if (ob != (bfd *)NULL) {
+ /* A parital link, so keep the relocs */
+ os->orelocation[os->reloc_count] = *parent;
+ os->reloc_count++;
+ }
+ }
+ else
+ {
+ asymbol *s;
+ arelent *p = *parent;
+
+ if (ob != (bfd *)NULL) {
+ /* A parital link, so keep the relocs */
+ os->orelocation[os->reloc_count] = *parent;
+ os->reloc_count++;
+ }
+
+ if (p->sym_ptr_ptr != (asymbol **)NULL) {
+ s = *(p->sym_ptr_ptr);
+ }
+ else {
+ s = (asymbol *)NULL;
+ }
+ switch (r)
+ {
+ case bfd_reloc_undefined:
+ /* We remember the symbol, and never print more than
+ a reasonable number of them in a row */
+ if (s == error_symbol) {
+ error_count++;
+ }
+ else {
+ error_count = 0;
+ error_symbol = s;
+ }
+ if (error_count < MAX_ERRORS_IN_A_ROW) {
+ info("%C: undefined reference to `%T'\n",
+ input_bfd,
+ input_section,
+ symbols,
+ (*parent)->address,
+ s);
+ config.make_executable = false;
+ }
+ else if (error_count == MAX_ERRORS_IN_A_ROW) {
+ info("%C: more undefined references to `%T' follow\n",
+ input_bfd,
+ input_section,
+ symbols,
+ (*parent)->address,
+ s);
+ }
+ else {
+ /* Don't print any more */
+ }
+ break;
+ case bfd_reloc_dangerous:
+ info("%B: relocation may be wrong `%T'\n",
+ input_bfd,
+ s);
+ break;
+ case bfd_reloc_outofrange:
+ info("%B:%s relocation address out of range %T (%x)\n",
+ input_bfd,
+ input_section->name,
+ s,
+ p->address);
+ break;
+ case bfd_reloc_overflow:
+ info("%B:%s relocation overflow in %T reloc type %d\n",
+ input_bfd,
+ input_section->name,
+ s,
+ p->howto->type);
+ break;
+ default:
+ info("%F%B: relocation error, symbol `%T'\n",
+ input_bfd,
+ s);
+ break;
+ }
+ }
+ }
+ }
+ free((char *)reloc_vector);
+}
+
+
+
+
+
+
+void *data_area;
+
+static void
+copy_and_relocate(statement)
+lang_statement_union_type *statement;
+{
+ switch (statement->header.type) {
+ case lang_fill_statement_enum:
+ {
+#if 0
+ bfd_byte play_area[SHORT_SIZE];
+ unsigned int i;
+ bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
+ /* Write out all entire shorts */
+ for (i = 0;
+ i < statement->fill_statement.size - SHORT_SIZE + 1;
+ i+= SHORT_SIZE)
+ {
+ bfd_set_section_contents(output_bfd,
+ statement->fill_statement.output_section,
+ play_area,
+ statement->data_statement.output_offset +i,
+ SHORT_SIZE);
+
+ }
+
+ /* Now write any remaining byte */
+ if (i < statement->fill_statement.size)
+ {
+ bfd_set_section_contents(output_bfd,
+ statement->fill_statement.output_section,
+ play_area,
+ statement->data_statement.output_offset +i,
+ 1);
+
+ }
+#endif
+ }
+ break;
+ case lang_data_statement_enum:
+ {
+ bfd_vma value = statement->data_statement.value;
+ bfd_byte play_area[LONG_SIZE];
+ unsigned int size;
+ switch (statement->data_statement.type) {
+ case LONG:
+ bfd_putlong(output_bfd, value, play_area);
+ size = LONG_SIZE;
+ break;
+ case SHORT:
+ bfd_putshort(output_bfd, value, play_area);
+ size = SHORT_SIZE;
+ break;
+ case BYTE:
+ bfd_putchar(output_bfd, value, play_area);
+ size = BYTE_SIZE;
+ break;
+ }
+
+ bfd_set_section_contents(output_bfd,
+ statement->data_statement.output_section,
+ play_area,
+ statement->data_statement.output_vma,
+ size);
+
+
+
+
+ }
+ break;
+ case lang_input_section_enum:
+ {
+
+ asection *i = statement->input_section.section;
+ asection *output_section = i->output_section;
+ lang_input_statement_type *ifile = statement->input_section.ifile;
+ bfd *inbfd = ifile->the_bfd;
+ if (output_section->flags & SEC_LOAD && i->size != 0)
+ {
+ if(bfd_get_section_contents(inbfd,
+ i,
+ data_area,
+ 0L,
+ i->size) == false)
+ {
+ info("%F%B error reading section contents %E\n",
+ inbfd);
+ }
+ perform_relocation (inbfd, i, data_area, ifile->asymbols);
+
+
+ if(bfd_set_section_contents(output_bfd,
+ output_section,
+ data_area,
+ (file_ptr)i->output_offset,
+ i->size) == false)
+ {
+ info("%F%B error writing section contents of %E\n",
+ output_bfd);
+ }
+
+ }
+ }
+ break;
+
+ default:
+ /* All the other ones fall through */
+ ;
+
+ }
+}
+
+void
+write_norel()
+{
+ /* Output the text and data segments, relocating as we go. */
+ lang_for_each_statement(copy_and_relocate);
+}
+
+
+static void read_relocs(abfd, section, symbols)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+{
+ /* Work out the output section ascociated with this input section */
+ asection *output_section = section->output_section;
+
+ size_t reloc_size = get_reloc_upper_bound(abfd, section);
+ arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
+
+ if (bfd_canonicalize_reloc(abfd,
+ section,
+ reloc_vector,
+ symbols)) {
+ output_section->reloc_count += section->reloc_count;
+ }
+}
+
+
+static void
+write_rel()
+{
+ /*
+ Run through each section of each file and work work out the total
+ number of relocation records which will finally be in each output
+ section
+ */
+
+ LANG_FOR_EACH_INPUT_SECTION
+ (statement, abfd, section,
+ (read_relocs(abfd, section, statement->asymbols)));
+
+
+
+ /*
+ Now run though all the output sections and allocate the space for
+ all the relocations
+ */
+ LANG_FOR_EACH_OUTPUT_SECTION
+ (section,
+ (section->orelocation =
+ (arelent **)ldmalloc((size_t)(sizeof(arelent **)*
+ section->reloc_count)),
+ section->reloc_count = 0,
+ section->flags |= SEC_HAS_CONTENTS));
+
+
+ /*
+ Copy the data, relocating as we go
+ */
+ lang_for_each_statement(copy_and_relocate);
+}
+
+void
+ldwrite ()
+{
+ data_area = (void*) ldmalloc(largest_section);
+ if (config.relocateable_output == true)
+ {
+ write_rel();
+ }
+ else
+ {
+ write_norel();
+ }
+ free(data_area);
+ /* Output the symbol table (both globals and locals). */
+ ldsym_write ();
+
+}
+
diff --git a/ld/ldwrite.h b/ld/ldwrite.h
new file mode 100644
index 0000000..2658801
--- /dev/null
+++ b/ld/ldwrite.h
@@ -0,0 +1,24 @@
+/* ldwrite.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+
+PROTO(void, ldwrite, (void));