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]; };