Inline expansion of index_adjust() and compute_origins().
authorduk <none@none>
Thu, 10 Jan 1985 13:19:47 +0000 (13:19 +0000)
committerduk <none@none>
Thu, 10 Jan 1985 13:19:47 +0000 (13:19 +0000)
Section table now allocated statically.

util/led/extract.c [new file with mode: 0644]

diff --git a/util/led/extract.c b/util/led/extract.c
new file mode 100644 (file)
index 0000000..1b186f3
--- /dev/null
@@ -0,0 +1,234 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+#include "out.h"
+#include "const.h"
+#include "debug.h"
+#include "defs.h"
+#include "memory.h"
+#include "orig.h"
+#include "scan.h"
+
+/*
+ * Get section sizes and symboltable information from present module.
+ */
+extract()
+{
+       struct outhead  head;
+
+       get_modul();
+       /*
+        * Copy head because we need it so often but it can change place,
+        * so we can't trust a pointer to it.
+        */
+       head = *(struct outhead *)modulptr(IND_HEAD);
+       get_names(&head);
+       process(&head);
+       skip_modul(&head);
+}
+
+ushort NLocals = 0;    /* Number of local names to be saved. */
+ushort NGlobals = 0;   /* Number of global names. */
+
+/*
+ * Walk through the nametable of this module, counting the locals that must
+ * appear in the final output file if this module is linked.
+ * That number will be returned.
+ */
+static
+get_names(head)
+       register struct outhead *head;
+{
+       register int    nnames;
+       register ind_t  sectindex, nameindex, charindex;
+       register ind_t  charoff;
+       extern int      flagword;
+
+       nnames = head->oh_nname;
+       sectindex = IND_SECT(*head);
+       nameindex = IND_NAME(*head);
+       charindex = IND_CHAR(*head);
+       charoff = OFF_CHAR(*head);
+       while (nnames--) {
+               register struct outsect *sects;
+               struct outname          name;   /* A local copy. */
+               /*
+                * Because savelocal/getexternal might relocate the modules
+                * we have to compute the core addresses again.
+                */
+               sects = (struct outsect *)modulptr(sectindex);
+               name = *(struct outname *)modulptr(nameindex);
+               /*
+                * Change the offset in file into an offset in the memory area.
+                * There will always be at least a header before the string
+                * area, so we don't have to be afraid to confuse "no name"
+                * with "the first name".
+                */
+               if (name.on_foff)
+                       name.on_foff += charindex - charoff;
+               namerelocate(&name, sects);
+               if (name.on_type & S_EXT) {
+                       getexternal(&name);
+               } else {
+                       /*
+                        * The only thing we want to know about locals is
+                        * whether they must appear in the output file.
+                        */
+                       if (!(flagword & SFLAG) && mustsavelocal(&name)) {
+                               NLocals++;
+                               savelocal(&name);
+                       }
+               }
+               nameindex += sizeof(struct outname);
+       }
+}
+
+extern struct orig     relorig[];
+
+static
+process(head)
+       register struct outhead *head;
+{
+       register struct outsect *sects;
+       register struct outsect *outsp;
+       register int            nsect;
+       register struct orig    *orig = relorig;
+       extern struct outhead   outhead;
+       extern struct outsect   outsect[];
+
+       outhead.oh_nrelo += head->oh_nrelo;
+       outhead.oh_nemit += head->oh_nemit;
+       if (head->oh_nsect > outhead.oh_nsect)
+               outhead.oh_nsect = head->oh_nsect;
+       sects = (struct outsect *)modulptr(IND_SECT(*head));
+       nsect = head->oh_nsect;
+       outsp = outsect;
+       while (nsect--) {
+               outsp->os_size += sects->os_size;
+               outsp->os_flen += sects->os_flen;
+               /*
+                * Add all flen's and all (size - flen == zero)'s of
+                * preceding sections with the same number.
+                */
+               orig->org_flen += sects->os_flen;
+               orig->org_zero += sects->os_size - sects->os_flen;
+               orig++; outsp++; sects++;
+       }
+}
+
+/*
+ * Add relocation constant for names in user defined sections.
+ * The value of a common name indicates a size instead of an offset,
+ * and hence shouldn't be relocated.
+ * The value of a name in the zero part of a section is relative from the
+ * beginning of the section, not from the beginning of the zero part; but
+ * all zero parts will be put after the normal section contents, so we
+ * must subtract the flen of its section from the value (and later on add
+ * the total flen of its section) and add the accumulated size of all
+ * zero parts in preceding sections with the same number.
+ * Otherwise we just add the accumulated size of all normal parts in preceding
+ * sections with the same size.
+ */
+namerelocate(name, sects)
+       register struct outname *name;
+       struct outsect          *sects;
+{
+       register int    type = name->on_type;
+       register int    sectindex;
+
+       if ((type & S_TYP) == S_UND || (type & S_TYP) == S_ABS)
+               return;
+       if (type & S_COM)
+               return;
+
+       sectindex = (type & S_TYP) - S_MIN;
+       if (name->on_valu >= sects[sectindex].os_flen) {
+               name->on_type |= S_ZER;
+               name->on_valu -= sects[sectindex].os_flen;
+               name->on_valu += relorig[sectindex].org_zero;
+       } else {
+               name->on_valu += relorig[sectindex].org_flen;
+       }
+}
+
+/*
+ * If we see this name for the first time, we must remember it for
+ * we might need it later on. Otherwise it must confirm to what we already
+ * know about it, and eventually add to that knowledge.
+ */
+static
+getexternal(name)
+       register struct outname *name;
+{
+       register char           *string;
+       register int            h;
+       register struct outname *old;
+       extern int              hash();
+       extern struct outname   *searchname();
+
+       string = modulptr((ind_t)name->on_foff);
+       h = hash(string);
+       old = searchname(string, h);
+       if (old == (struct outname *)0) {
+               NGlobals++;
+               entername(name, h);
+       } else if (!ISUNDEFINED(name)) {
+               if (ISUNDEFINED(old)) {
+                       transfer(name, old);
+               } else {
+                       name->on_mptr = string; /* Just for convenience. */
+                       redefine(name, old);
+               }
+       }
+}
+
+/*
+ * Handle the redefinition of `new' in the current module.
+ * A name can be defined in three ways, in increasing priority:
+ *     undefined,
+ *     common,
+ *     defined in a section.
+ * A name may become "higher" when defined, but not "lower".
+ * A redefinition as common is allowed. It is ignored, but a warning is given
+ * when the desired section of `new' doesn't correspond with the section of
+ * `old'. If a common definition is given again for a name, we take the
+ * greatest value so that the common declared name always has enough space.
+ * If a common is defined as a not-common, the old definition is ignored.
+ */
+static
+redefine(new, old)
+       register struct outname *new, *old;
+{
+       if (!ISCOMMON(old)) {
+               if (!ISCOMMON(new))
+                       error("%s: multiply defined", new->on_mptr);
+
+               if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
+                       warning("%s: sections differ", new->on_mptr);
+       } else {
+               /* `Old' is common. */
+               if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
+                       warning("%s: sections differ", new->on_mptr);
+
+               if (ISCOMMON(new)) {
+                       if (new->on_valu > old->on_valu)
+                               old->on_valu = new->on_valu;
+               } else {
+                       transfer(new, old);
+               }
+       }
+}
+
+/*
+ * Transfer things we want to know from `src' to `dst'.
+ */
+static
+transfer(src, dst)
+       register struct outname *src, *dst;
+{
+       debug("%s defined here\n", src->on_mptr, 0, 0, 0);
+       dst->on_valu = src->on_valu;
+       dst->on_type = src->on_type;
+       dst->on_desc = src->on_desc;
+}