relocate.c revision f3324781c875e2f9865c291e43f86ee710b0c145
* Traverse the relocation entries. * First, check if this symbol is reference symbol * for this relocation entry. * Then check if this relocation entry is relocating * This symbol is truely *disp* relocated, so should * really be fixed by user. * The number of symbols provided by some objects can be very large. Use a * binary search to match the associated value to a symbol table entry. * Given a sorted list of symbols, look for a symbol in which the relocation * offset falls between the [sym.st_value - sym.st_value + sym.st_size]. Since * the symbol list is maintained in sorted order, we can bail once the * relocation offset becomes less than the symbol values. The symbol is * returned for use in error diagnostics. * Sorted symbol values have been uniquified by adding their associated * section offset. Uniquify the relocation offset by adding its * associated section offset, and search for the symbol. * Determine the relocation reference symbol and its type. * If there is no target symbol to match the relocation offset, then the * offset is effectively local data. If the relocation symbol is global * data we have a potential for this displacement relocation to be * invalidated should the global symbol be copied. * If both symbols are local, no copy relocations can occur to * Determine the relocation target symbols type. * If the reference symbol is local, and the target isn't a * data element, then no copy relocations can occur to either * symbol. Note, this catches pc-relative relocations against * the _GLOBAL_OFFSET_TABLE_, which is effectively treated as * Finally, one of the symbols must reference a data element. * We have two global symbols, at least one of which is a data item. * The last case where a displacement relocation can be ignored, is * if the reference symbol is included in the target symbol. * We have a displacement relocation that could be compromised by a * copy relocation of one of the associated data items. * qsort(3C) comparison routine used for the disp_sortsyms(). * Determine whether a displacement relocation is between a local and global * symbol pair. One symbol is used to perform the relocation, and the other * is the destination offset of the relocation. * If the input files symbols haven't been sorted yet, do so. * As symbol resolution has already occurred, various * symbols from this object may have been satisfied * from other objects. Only select symbols from this * object. For the displacement test, we only really * need to observe data definitions, however, later as * part of providing warning disgnostics, relating the * relocation offset to a symbol is desirable. Thus, * collect all symbols that define a memory area. * As a further optimization for later checking, mark * this section if this a global data definition. * Capture the symbol. Within relocatable objects, a * symbols value is its offset within its associated * section. Add the section offset to this value to * Sort the list based on the symbols value (address). * If the reference symbol is local, and the section being relocated * contains no global definitions, neither can be the target of a copy * Otherwise determine whether this relocation symbol and its offset * could be candidates for a copy relocation. * Add an active relocation record. * If no relocation cache structures are available, allocate a new * one and link it into the bucket list. * Typically, when generating an executable or shared object * there will be an active relocation for every input * Any GOT relocation reference requires the creation of a .got table. * Most references to a .got require a .got entry, which is accounted * for with the ofl_gotcnt counter. However, some references are * relative to the .got table, but require no .got entry. This test * insures a .got is created regardless of the type of reference. * If this is a displacement relocation generate a warning. * In the platform specific machrel.XXX.c files, we sometimes write * a value directly into the GOT. This function can be used when * the running linker has the opposite byte order of the object being ((v &
0x0000ff00) <<
40) |
((v &
0x00ff0000) <<
24) |
((v &
0xff000000) <<
8) |
((v >>
8) &
0xff000000) |
((v >>
24) &
0x00ff0000) |
((v >>
40) &
0x0000ff00) |
(v >>
56));
/* Xword is unsigned - 0 bits enter from left */ return (((v <<
24) | ((v &
0xff00) <<
8) |
((v >>
8) &
0xff00) | (v >>
24)));
* If this is the first time we've seen this symbol in a GOT * relocation we need to assign it a GOT token. Once we've got * all of the GOT's assigned we can assign the actual indexes. * Now we initialize the GOT table entry. * Pseudo code to describe the the decisions below: * enter symbol value in GOT table entry * create Relative relocation against symbol * create a GLOB_DAT relocation against symbol * Add a RELATIVE relocation if this is * anything but a ABS symbol. * Perform relocation to GOT table entry. * Perform relocations for PLT's * AMD64 TLS code sequences do not use a unique TLS relocation to * reference the __tls_get_addr() function call. * GNUC IA32 TLS code sequences do not use a unique TLS relocation to * reference the ___tls_get_addr() function call. * if (not PLT yet assigned) * assign PLT index to symbol * build output JMP_SLOT relocation * If this symbol is binding to a LAZYLOADED object then * set the LAZYLD symbol flag. * Perform relocation to PLT table entry. * process GLOBAL undefined and ref_dyn_need symbols. * Reference is to a function so simply create a plt entry for it. * Catch absolutes - these may cause a text relocation. * If -zabsexec is set then promote the ABSOLUTE symbol to * current the current object and perform the relocation now. * If the relocation is against a writable section simply compute the * necessary output relocation. As an optimization, if the symbol has * already been transformed into a copy relocation then we can perform * the relocation directly (copy relocations should only be generated * for references from the text segment and these relocations are * normally carried out before we get to the data segment relocations). * If the reference isn't to an object (normally because a .type * directive hasn't defined in some assembler source), then simply apply * a generic relocation (this has a tendency to result in text * Prepare for generating a copy relocation. * If this symbol is one of an alias pair, we need to insure both * symbols become part of the output (the strong symbol will be used to * maintain the symbols state). And, if we did raise the precedence of * a symbol we need to check and see if this is a weak symbol. If it is * we want to use it's strong counter part. * The results of this logic should be: * rel_usym: assigned to strong * rel_sym: assigned to symbol to perform * copy_reloc against (weak or strong). * As we're going to replicate a symbol from a shared * object, retain its correct binding status. * As we're going to replicate a symbol from a shared * object, retain its correct binding status. * If this is a weak symbol then we want to move the strong * symbol into local .bss. If there is a copy_reloc to be * performed, that should still occur against the WEAK symbol. * If the reference is to an object then allocate space for the object * within the executables .bss. Relocations will now be performed from * this new location. If the original shared objects data is * initialized, then generate a copy relocation that will copy the data * to the executables .bss at runtime. * Indicate that the symbol(s) against which we're relocating * have been moved to the executables common. Also, insure that * the symbol(s) remain marked as global, as the shared object * from which they are copied must be able to relocate to the * new common location within the executable. * Note that even though a new symbol has been generated in the * output files' .bss, the symbol must remain REF_DYN_NEED and * not be promoted to REF_REL_NEED. sym_validate() still needs * to carry out a number of checks against the symbols binding * that are triggered by the REF_DYN_NEED state. * Make sure the symbol has a reference in case of any * error diagnostics against it (perhaps this belongs * to a version that isn't allowable for this build). * The resulting diagnostic (see sym_undef_entry()) * might seem a little bogus, as the symbol hasn't * really been referenced by this file, but has been * promoted as a consequence of its alias reference. * Assign the symbol to the bss and insure sufficient alignment * (we don't know the real alignment so we have to make the * Whether or not the symbol references initialized * data we generate a copy relocation - this differs * from the past where we would not create the COPY_RELOC * if we were binding against .bss. This is done * o If the symbol in the shared object changes to * a initialized data - we need the COPY to pick it * o without the COPY RELOC we can't tell that the * symbol from the COPY'd object has been moved * and all bindings to it should bind here. * Keep this symbol in the copy relocation list * to check the validity later. * If this symbol is a protected symbol, warn it. * All relocations should have been handled by the other routines. This * routine is here as a catch all, if we do enter it we've goofed - but * we'll try and to the best we can. * If building a shared object then put the relocation off * Otherwise process relocation now. * Process relocations when building a relocatable object. Typically, there * aren't many relocations that can be caught at this point, most are simply * passed through to the output relocatable object. * Determine if we can do any relocations at this point. We can if: * this is local_symbol and a non-GOT relocation, and * the relocation is pc-relative, and * the relocation is against a symbol in same section * If -zredlocsym is in effect, translate all local symbol relocations * to be against against section symbols, since section symbols are * the only symbols which will be added to the .symtab. * But if this is PIC code, don't allow it for now. * Indicate that this relocation should be processed the same * as a section symbol. For SPARC and AMD64 (Rela), indicate * that the addend also needs to be applied to this relocation. * Intel (Rel) relocations do not contain an addend. Any addend is * contained within the file at the location identified by the * relocation offset. Therefore, if we're processing a section symbol, * or a -zredlocsym relocation (that basically transforms a local symbol * reference into a section reference), perform an active relocation to * Perform any generic TLS validations before passing control to machine * specific routines. At this point we know we are dealing with an executable * or shared object - relocatable objects have already been processed. * All TLS relocations are illegal in a static executable. * Any TLS relocation must be against a STT_TLS symbol, all others * A dynamic executable can not use the LD or LE reference models to * reference an external symbol. A shared object can not use the LD * reference model to reference an external symbol. * The TLS LE model is only allowed for dynamic executables. The TLS IE * model is allowed for shared objects, but this model has restrictions. * This model can only be used freely in dependencies that are loaded * immediately as part of process initialization. However, during the * initial runtime handshake with libc that establishes the thread * pointer, a small backup TLS reservation is created. This area can * be used by objects that are loaded after threads are initialized. * However, this area is limited in size and may have already been * used. This area is intended for specialized applications, and does * not provide the degree of flexibility dynamic TLS can offer. Under * -z verbose indicate this restriction to the user. * Indicate this symbol is being used for relocation and therefore must * have its output address updated accordingly (refer to update_osym()). * Indicate the section this symbol is defined in has been referenced, * therefor it *is not* a candidate for elimination. * Determine if this symbol is actually an alias to another symbol. If * so, and the alias is not REF_DYN_SEEN, set rel_usym to point to the * weak symbols strong counter-part. The one exception is if the * FLG_SY_MVTOCOMM flag is set on the weak symbol. If this is the case, * the strong is only here because of its promotion, and the weak symbol * should still be used for the relocation reference (see reloc_exec()). * Determine whether this symbol should be bound locally or not. * Symbols are bound locally if one of the following is true: * o the symbol is of type STB_LOCAL. * o the output image is not a relocatable object and the relocation * is relative to the .got. * o the section being relocated is of type SHT_SUNW_dof. These * sections must be bound to the functions in the containing * object and can not be interposed upon. * o the symbol has been reduced (scoped to a local or symbolic) and * reductions are being processed. * o the -Bsymbolic flag is in use when building a shared object, * and the symbol hasn't explicitly been defined as nodirect. * o an executable (fixed address) is being created, and the symbol * is defined in the executable. * o the relocation is against a segment which will not be loaded * into memory. In this case, the relocation must be resolved * now, as ld.so.1 can not process relocations against unmapped * Global symbols may have been individually reduced in * scope. If the whole object is to be self contained, * such as when generating an executable or a symbolic * shared object, make sure all relocation symbol * references (sections too) are treated locally. Note, * explicit no-direct symbols should not be bound to * If this is a PC_RELATIVE relocation, the relocation could be * compromised if the relocated address is later used as a copy * relocated symbol (PSARC 1999/636, bugid 4187211). Scan the input * files symbol table to cross reference this relocation offset. * GOT based relocations must bind to the object being built - since * they are relevant to the current GOT. If not building a relocatable * object - give a appropriate error message. * TLS symbols can only have TLS relocations. * The above test is relaxed if the target section is * Select the relocation to perform. * Given a relocation that references a local symbol from a discarded * COMDAT (or SHF_GROUP) section, replace the symbol with the * corresponding symbol from the section that was kept. * orig_sdp - Symbol to be replaced. Must be a local symbol (STB_LOCAL). * Returns address of replacement symbol descriptor if one was * found, and NULL otherwise. * [Note that I'm using the word "COMDAT" here loosely, to refer * to actual COMDAT sections as well as to groups tied together * with an SHF_GROUP section. SHF_GROUP is simply a more advanced * version of the same idea: That multiple versions of the same thing * can come in, but only one of them is used for the output.] * In principle, this sort of sloppy relocation remapping is * a questionable practice. All self-referential sections should * be in a common SHF_GROUP so that they are all kept or removed * together. The problem is that there is no way to ensure that the * two sections are similar enough that the replacement section will * really supply the correct information. However, we see a couple of * situations where it is useful to do this: (1) Older Sun C compilers * generated DWARF sections that would refer to one of the COMDAT * sections, and (2) gcc, when its COMDAT feature is enabled. * It turns out that the GNU ld does these sloppy remappings. * The GNU ld takes an approach that hard wires special section * names and treats them specially. We avoid that practice and * try to get the necessary work done relying only on the ELF * attributes of the sections and symbols involved. This means * that our heuristic is somewhat different than theirs, but the * end result is close enough to solve the same problem. * It is our hope that gcc will eventually phase out the need * for sloppy relocations, and this won't be needed. In the * meantime, the option allows us to interoperate. * Here is how we do it: The symbol points at the input section, * and the input section points at the output section to which it * is assigned. The output section contains a list of all of the * input sections that have been mapped to it, including the * corresponding COMDAT section that was kept. The kept COMDAT * section contains a reference to its input file, where we can find * the array of all the symbols in that file. From the input file, * we then locate the corresponding symbol that references the kept * ld_place_section() can alter the section name if it contains * a '%' character. We need to use the original name in this * 1) The caller is required to ensure that the input symbol is * local. We don't check for that here. * 2) If the discarded section has not been assigned to an * output section, we won't be able to continue. * 3) This operation only applies to SHT_SUNW_COMDAT sections * or sections contained within a COMDAT group (SHF_GROUP). * Examine each input section assigned to this output section. * The replacement section must: * - Have the same name as the original * - Not have been discarded * - Have the same section type (and note that this type may * - Have the same SHF_GROUP flag setting (either on or off) * - Must be a COMDAT section of one form or the other. * We found the kept COMDAT section. Now, look at all of the * symbols from the input file that contains it to find the * symbol that corresponds to the one we started with: * - Hasn't been discarded * - Has section index of kept section * - If one symbol has a name, the other must have * the same name. The st_name field of a symbol * is 0 if there is no name, and is a string * table offset otherwise. The string table * offsets may well not agree --- it is the * actual string that matters. * - Type and binding attributes match (st_info) * - Values match (st_value) * - Sizes match (st_size) * - Visibility matches (st_other) /* If didn't return above, we didn't find it */ * Generate relocation descriptor and dispatch * Make sure the relocation is in the valid range. * Special case: a register symbol associated with symbol index 0 is * initialized (i.e., relocated) to a constant from the r_addend field * rather than from a symbol value. * Determine whether we're dealing with a named symbol. Note, bogus * relocations can result in a null symbol descriptor (sdp), the error * condition should be caught below after determining whether a valid * If for some reason we have a null relocation record issue a * warning and continue (the compiler folks can get into this * state some time). Normal users should never see this error. * If we are here, we know that the relocation requires reference * symbol. If no symbol is assigned, this is a fatal error. * If this symbol is part of a DISCARDED section attempt to find another * If "-z relaxreloc", then check to see if * this is a reference to a discarded COMDAT * section that can be replaced with the * If this is a global symbol, determine whether its visibility needs * Ignore any relocation against a section that will not be in the * output file (has been stripped). * If the input section exists, but the section has not been associated * to an output section, then this is a little suspicious. * If the symbol for this relocation is invalid (which should have * generated a message during symbol processing), or the relocation * record's symbol reference is in any other way invalid, then it's * Size relocations against section symbols are presently unsupported. * There is a question as to whether the input section size, or output * section size would be used. Until an explicit requirement is * established for either case, we'll punt. Rel *
rend;
/* end of relocation section data */ Rel *
reloc;
/* current relocation entry */ Xword rsize;
/* size of relocation section data */ * Build up the basic information in for the Rel_desc structure. * Initialize the relocation record information and process * the individual relocation. Reinitialize the flags to * insure we don't carry any state over from the previous * relocation records processing. * Determine the input section that this * relocation information refers to. * Do not process relocations against sections * which are being discarded (COMDAT) * Check for relocations against non-writable * Move Section related function * Set info for the target move section * If this is an illgal entry, retun NULL. * Relocation against Move Table. * Go through the relocation entries. * Initialize the relocation record information. * This function is similar to reloc_init(). * This function is called when the SHT_SUNW_move table is expanded * and there were relocation against the SHT_SUNW_move section. * Count the number of output relocation entries, global offset table entries, * and procedure linkage table entries. This function searches the segment and * outsect lists and passes each input reloc section to process_reloc(). * It allocates space for any output relocations needed. And builds up * the relocation structures for later processing. * At this point we have finished processing all input symbols. Make * sure we add any absolute (internal) symbols before continuing with * any relocation processing. * First process all of the relocations against NON-writable * segments followed by relocations against the writeable segments. * This separation is so that when the writable segments are processed * we know whether or not a COPYRELOC will be produced for any symbols. * If relocations aren't processed in this order, a COPYRELOC and a * regular relocation can be produced against the same symbol. The * regular relocation would be redundant. * Process any extra relocations. These are relocation sections that * If there were relocation against move table, * process the relocation sections. * Now all the relocations are pre-processed, * check the validity of copy relocations. * If there were no displacement relocation * in this file, don't worry about it. * GOT sections are created for dynamic executables and shared objects * if the FLG_OF_BLDGOT is set, or explicit reference has been made to * Simple comparison routine to be used by qsort() for * the sorting of the output relocation list. * The reloc_compare() routine results in a relocation * table which is located on: * file referenced (NEEDED NDX) * This provides the most efficient traversal of the relocation * first - sort on neededndx * At this point we fall back to key2 (offsets) to * sort the output relocations. Ideally this will * make for the most efficient processing of these * relocations at run-time. * All but the PLT output relocations are sorted in the output file * based upon their sym_desc. By doing this multiple relocations * against the same symbol are grouped together, thus when the object * is later relocated by ld.so.1 it will take advantage of the symbol * cache that ld.so.1 has. This can significantly reduce the runtime * relocation cost of a dynamic object. * PLT relocations are not sorted because the order of the PLT * relocations is used by ld.so.1 to determine what symbol a PLT * If it's a PLT relocation we output it now in the * order that it was originally processed. * All output relocations have now been sorted, go through * and process each relocation. * Process relocations. Finds every input relocation section for each output * section and invokes reloc_sec() to relocate that section. * Determine the index of the symbol table that will be referenced by * the relocation entries. * Re-initialize counters. These are used to provide relocation * offsets within the output buffers. * Now that the output file is created and symbol update has occurred, * process the relocations collected in process_reloc(). * Process the relocation sections: * o for each relocation section generated for the output * image update its shdr information to reflect the * symbol table it needs (sh_link) and the section to * which the relocation must be applied (sh_info). * Since the .rel[a] section is not tied to any specific * section, we'd not have found it above. * We only have two relocation sections here, (PLT's, * coalesced) so just hit them directly instead of stepping * over the output sections. * If the -z text option was given, and we have output relocations * against a non-writable, allocatable section, issue a diagnostic and * return (the actual entries that caused this error would have been * output during the relocating section phase). * Finally, initialize the first got entry with the address of the * .dynamic section (_DYNAMIC). * Now that any GOT information has been written, display the debugging * information if required. * If the -z text option was given, and we have output relocations against a * non-writable, allocatable section, issue a diagnostic. Print offending * symbols in tabular form similar to the way undefined symbols are presented. * Called from reloc_count(). The actual fatal error condition is triggered on * in reloc_process() above. * Note. For historic reasons -ztext is not a default option (however all OS * shared object builds use this option). It can be argued that this option * should also be default when generating an a.out (see 1163979). However, if * an a.out contains text relocations it is either because the user is creating * something pretty weird (they've used the -b or -znodefs options), or because * the library against which they're building wasn't constructed correctly (ie. * a function has a NOTYPE type, in which case the a.out won't generate an * associated plt). In the latter case the builder of the a.out can't do * anything to fix the error - thus we've chosen not to give the user an error, * or warning, for this case. * Only give relocation errors against loadable read-only segments. * If we are in -ztextwarn mode, it's a silent error if a relocation is * due to a 'WEAK REFERENCE'. This is because if the symbol is not * provided at run-time we will not perform a text-relocation. * If building with '-ztext' then emit a fatal error. If * building a executable then only emit a 'warning'. * Generic encapsulation for generating a TLS got index. * If this is a local LE TLS symbol, then the symbol won't be * available at runtime. The value of the local symbol will * be placed in the associated got entry, and the got * relocation is reassigned to a section symbol. * Move Section related function * Search for matching move entry * This should never happen. * We are relocating the move table itself. * We are expanding the partial symbol. So we are generating * the relocation entry relocating the expanded partial symbol. * Partially Initialized Symbol Handling routines * For sparc architecture, the second argument is reld->rel_raddend. * For i386 acrchitecure, the second argument is the value stored * at the relocation target address. for (i =
1; i <
nlocs; i++) {
* Because of the combinations of 32-bit lib providing 64-bit support, and * visa-versa, the use of krtld's dorelocs can result in differing message * requirements that make msg.c/msg.h creation and chkmsg "interesting". * Thus the actual message files contain a couple of entries to satisfy * each architectures build. Here we add dummy calls to quieten chkmsg. * chkmsg: MSG_INTL(MSG_REL_NOFIT) * chkmsg: MSG_INTL(MSG_REL_NONALIGN)