/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <libelf.h>
#include <dlfcn.h>
#include "machdep.h"
#include "reloc.h"
#include "msg.h"
#include "_librtld.h"
#include "alist.h"
/*
* Process all relocation records. A new `Reloc' structure is allocated to
* cache the processing decisions deduced, and these will be applied during
* update_reloc().
* A count of the number of null relocations (i.e., relocations that will be
* fixed and whoes records will be nulled out), data and function relocations
* is maintained. This allows the relocation records themselves to be
* rearranged (localized) later if necessary. Note that the number of function
* relocations, although coounted, shouldn't differ from the original file,
* the index of a .plt must be maintained to the index of its relocation record
* within the associated relocation section.
*
* The intention behind this file is to maintain as much relocation logic as
* possible in a generic form.
*/
int
{
const char *strs;
/*
* Determine the number of relocation entries we'll be dealing with.
*/
/*
* Allocate a relocation structure for this relocation section.
*/
return (1);
/*
* Determine the relocations associated symbol and string table.
*/
/*
* Loop through the relocation table.
*/
const char *name;
/* LINTED */
if (type == M_R_JMP_SLOT)
/*
* Analyze the case where no relocations are to be applied.
*/
if ((flags & RTLD_REL_ALL) == 0) {
/*
* Don't apply any relocations to the new image but
* insure their offsets are incremented to reflect any
* new fixed address.
*/
/*
* Undo any relocations that might have already been
* applied to the memory image.
*/
if (flags & RTLD_MEMORY) {
/*
* If a copy relocation is involved we'll need
* to know the size of the copy.
*/
else
}
/*
* Save the objects new address.
*/
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*data)++;
continue;
}
/*
* Determine the symbol binding of the relocation. Don't assume
* that relative relocations are simply M_R_RELATIVE. Although
* a pic generated shared object can normally be viewed as
* having relative and non-relative relocations, a non-pic
* shared object will contain a number of relocations against
* local symbols (normally sections). If a relocation is
* against a local symbol it qualifies as a relative relocation.
*/
else
bind = STB_GLOBAL;
/*
* Analyze the case where only relative relocations are to be
* applied.
*/
if (flags & RTLD_MEMORY) {
/*
* Save the relative relocations from
* the memory image. The data itself
* might already have been relocated,
* thus clear the relocation record so
* that it will not be performed again.
*/
(*null)++;
} else {
/*
* Any non-relative relocation must be
* undone, and the relocation records
* offset updated to any new fixed
* address.
*/
(FLG_R_UNDO | FLG_R_INC);
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*data)++;
}
} else {
/*
* Apply relative relocation to the
* file image. Clear the relocation
* record so that it will not be
* performed again.
*/
(FLG_R_APPLY | FLG_R_CLR);
if (IS_PC_RELATIVE(type))
if (unknown == 0)
unknown =
(*null)++;
} else {
/*
* Any non-relative relocation should be
* left alone, but its offset should be
* updated to any new fixed address.
*/
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*data)++;
}
}
continue;
}
/*
* Analyze the case where more than just relative relocations
* are to be applied.
*/
if (flags & RTLD_MEMORY) {
/*
* Save the relative relocations from the memory
* image. The data itself has already been
* relocated, thus clear the relocation record
* so that it will not be performed again.
*/
} else {
/*
* Apply relative relocation to the file image.
* Clear the relocation record so that it will
* not be performed again.
*/
if (IS_PC_RELATIVE(type))
if (unknown == 0)
}
(*null)++;
continue;
}
/*
* At this point we're dealing with a non-relative relocation
* that requires the symbol definition.
*/
/*
* Find the symbol. As the object being investigated is already
* a part of this process, the symbol lookup will likely
* succeed. However, because of lazy binding, there is still
* the possibility of a dangling .plt relocation. dldump()
* users might be encouraged to set LD_FLAGS=loadavail (crle(1)
* does this for them).
*
* Initialize the symbol lookup, and symbol result, data
* structures.
*/
/*
* Determine from the various relocation requirements
* whether this binding is appropriate. If we're called
* from crle(1), RTLD_CONFSET is set, then only inspect
* objects selected from the configuration file
* (FL1_RT_CONFSET was set during load()).
*/
if (!(flags & RTLD_CONFSET) ||
((flags & RTLD_REL_EXEC) &&
((flags & RTLD_REL_DEPENDS) &&
((flags & RTLD_REL_PRELOAD) &&
((flags & RTLD_REL_SELF) &&
_bound = 1;
/*
* If this symbol is explicitly defined
* as nodirect, don't allow any local
* binding.
*/
ndx)) {
_bound = 0;
break;
}
}
}
}
} else {
/*
* If this is a weak reference and we've been asked to
* bind unresolved weak references consider ourself
* bound. This category is typically set by clre(1) for
* an application cache.
*/
(flags & RTLD_REL_WEAK))
}
if (flags & RTLD_MEMORY) {
if (_bound) {
/*
* We know that all data relocations will have
* been performed at process startup thus clear
* the relocation record so that it will not be
* performed again. However, we don't know what
* function relocations have been performed
* because of lazy binding - regardless, we can
* leave all the function relocation records in
* place, because if the function has already
* been bound the record won't be referenced
* anyway. In the case of using LD_BIND_NOW,
* a function may be bound twice - so what.
*/
if (type == M_R_JMP_SLOT) {
(*func)++;
} else {
(*null)++;
}
} else {
/*
* Clear any unrequired relocation.
*/
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*data)++;
}
} else {
if (_bound) {
/*
* Apply the global relocation to the file
* image. Clear the relocation record so that
* it will not be performed again.
*/
if (_weak) {
} else {
if (IS_PC_RELATIVE(type))
}
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*null)++;
} else {
/*
* Do not apply any unrequired relocations.
*/
if (type == M_R_JMP_SLOT)
(*func)++;
else
(*data)++;
}
}
}
return (0);
}
/*
* Perform any relocation updates to the new image using the information from
* the `Reloc' structure constructed during count_reloc().
*/
void
{
/*
* Set up to read the output relocation table.
*/
/*
* Loop through the relocation table.
*/
/* LINTED */
/*
* Ignore null relocations (these may have been created from a
* previous dldump() of this image).
*/
(*null)++;
continue;
}
/*
* Determine the section being relocated if we haven't already
* done so (we may have had to skip over some null relocation to
* get to the first valid offset). The System V ABI states that
* a relocation sections sh_info field indicates the section
* that must be relocated. However, on Intel it seems that the
* .rel.plt sh_info records the section index of the .plt, when
* in fact it's the .got that gets relocated. In addition we
* now create combined relocation sections with -zcomreloc. To
* generically be able to cope with these anomalies, search for
* the appropriate section to be relocated by comparing the
* offset of the first relocation record against each sections
* offset and size.
*/
/* BEGIN CSTYLED */
#if !defined(__lint)
#else
/*
* lint sees `bgn' and `end' as potentially referenced
* before being set.
*/
#endif
_icache++;
_icache++) {
break;
}
}
/* END CSTYLED */
/*
* Determine the relocation location of both the input and
* output data. Take into account that an input section may be
* NOBITS (ppc .plt for example).
*/
else
iaddr = 0;
/*
* Apply the relocation to the new output image. Any base
* address, or symbol value, will have been saved in the reloc
* structure during count_reloc().
*/
/*
* Undo any relocation that might already been applied to the
* memory image by the runtime linker. Using the original
* file, determine the relocation offset original value and
* restore the new image to that value.
*/
/*
* If a relocation has been applied then the relocation record
* should be cleared so that the relocation isn't applied again
* when the new image is used.
*/
if (type == M_R_JMP_SLOT) {
clear_reloc(*func);
} else {
clear_reloc(*null);
}
}
/*
* If a relocation isn't applied, update the relocation record
* to take into account the new address of the image.
*/
if (type == M_R_JMP_SLOT) {
} else {
}
}
}
}