summaryrefslogtreecommitdiff
path: root/ld/linksyms.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/linksyms.c')
-rw-r--r--ld/linksyms.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/ld/linksyms.c b/ld/linksyms.c
new file mode 100644
index 0000000..b5304a3
--- /dev/null
+++ b/ld/linksyms.c
@@ -0,0 +1,84 @@
+
+/* linksyms.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+FORWARD void linkrefs P((struct modstruct *modptr));
+PUBLIC bool_t reloc_output = 0;
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef REL_OUTPUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NUL_PTR)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_main")) != NUL_PTR)
+ entrysym(symptr);
+ do
+ {
+ if ((elptr = entryfirst) == NUL_PTR)
+ fatalerror("no start symbol");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = FALSE;
+ for (; elptr != NUL_PTR; elptr = elptr->elnext)
+ linkrefs(elptr->elsymptr->modptr);
+ if ((symptr = findsym("start")) != NUL_PTR)
+ linkrefs(symptr->modptr);
+ needlink = FALSE;
+ {
+ struct redlist *prlptr = 0;
+ struct redlist *rlptr;
+
+ for (rlptr = redfirst; rlptr != NUL_PTR;
+ rlptr = (prlptr = rlptr)->rlnext)
+ if (rlptr->rlmodptr->loadflag &&
+ rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class)
+ {
+ rlptr->rlsymptr->modptr = rlptr->rlmodptr;
+ rlptr->rlsymptr->value = rlptr->rlvalue;
+ if (rlptr == redfirst)
+ redfirst = rlptr->rlnext;
+ else
+ prlptr->rlnext = rlptr->rlnext;
+ needlink = TRUE;
+ }
+ }
+ }
+ while (needlink);
+}
+
+PRIVATE void linkrefs(modptr)
+struct modstruct *modptr;
+{
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ modptr->loadflag = TRUE;
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr->loadflag == FALSE)
+ linkrefs(symptr->modptr);
+}
+