The following C structures illustrate how the dynamic linking works
(these are copied from __load.c).  There are essentially two phases to
the dynamic linking.  First we go through and fix all of the __GOT_
entries and the jump table and once we have done this then we go and
fix places where the address of variables is used as an initializer
for a variable.

	The functions __dynamic_resolve and __do_fixups are called
with a pointer to an image_fixuplist structure.

/* This list is generated by the linker - it corresponds to the SETD
   list generated in conjunction with the variable __SHARABLE_CONFLICTS__.
   The linker does not do anything special with this symbol - it simply
   puts together the pieces that are needed.  The list of fixups to local
   variables is generated internally by the linker, and ld fills in this
   one field as a special case before writing the image.  The array size
   is listed as 1, but it would actually be  ->size - 2.  __load.c will
   pick up this pointer and pass it to __dynamic_resolve() and __do_fixups().
*/

struct fixuplist{  /* This list is generated by the linker */
  int size;
  int * magic;  /* Used for verification purposes */
  struct image_fixuplist * list;  /* Fixups to local variables */
  struct fixuplist *** shrlib_list[1];  /* One for each sharable
	        library this program is linked to.  The sharable libraries
		are linked to other sharable libraries, so we have to walk
		this tree and resolve all of the fixups. */
};			


/* This is a linker-generated list of fixups.  The linker essentially
   watches for	multiple definitions of symbols, and if there is a
   __GOT__ symbol then it does not flag an error condition.  Instead, it
   adds a fixup to the fixuplist which will correct the __GOT__ that 
   appears later on the link command line.  The number of pointer pairs
   is always specified by the size field, and after the last pointer pair
   is the pointer to the builtin_fixups.
   */

struct image_fixuplist{
  int size;
  struct elemental_fixup{
    union{
      int  newaddr;
      struct builtin_fixup* bifu;
    }un;
    int * fixaddr;
  } fix[1];
};

/* Each link image (sharable libraries are each considered a sharable
   link image) will have a list of builtin fixups as well, as many as one
   for each source file that went into the link image.  These lists
   are generated by jumpas as needed (perhaps one per source file), and a SETD
   symbol __BUILTIN_FIXUPS__.  These will never appear in a user program -
   only in a shared library.  This structure contains a series of pointers
   to these different lists, and we need to walk through and apply all
   of the fixups.  The array size is listed as 1, but it can be any number
 */

struct builtin_fixup{
	int len;
	struct file_fixup * fixpnt[1];  /* Potentially one for every source
					    file that was linked */
};


/* Each source file can potentially have one of these beasts.  There
   are a series of pointer pairs, terminated by a NULL.  The idea here is
   that we are supposed to copy the number out of gotaddr  and store it at
   fixaddr.  This is the list that is generated by the jumpas tool.
   This is listed with an array size of 1, but it can be any number.
 */

struct file_fixup{
  struct builtin_elemental_fixup{
    int * gotaddr;
    int * fixaddr;
  } fixup[1];
};
