files.c revision d840867f3a8b0ba209ef90762b3f9c72a5f92cc5
/*
* 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 (c) 1988 AT&T
* All Rights Reserved
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Processing of relocatable objects and shared objects.
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <link.h>
#include <limits.h>
#include <sys/systeminfo.h>
#include <debug.h>
#include <msg.h>
#include <_libld.h>
/*
* Decide if we can link against this input file.
*/
static int
{
/*
* Check the validity of the elf header information for compatibility
* with this machine and our own internal elf library.
*/
return (0);
}
return (0);
}
return (0);
}
return (1);
}
/*
* Check sanity of file header and allocate an infile descriptor
* for the file being processed.
*/
static Ifl_desc *
{
}
return (0);
}
/*
* Is this file using 'extended Section Indexes'. If so, use the
* e_shnum & e_shstrndx which can be found at:
*
* e_shnum == Shdr[0].sh_size
* e_shstrndx == Shdr[0].sh_link
*/
}
}
else
} else {
}
sizeof (Is_desc *))) == 0)
/*
* Record this new input file on the shared object or relocatable
* object input file list.
*/
} else {
}
return (ifl);
}
/*
* Process a generic section. The appropriate section information is added
* to the files input descriptor list.
*/
static uintptr_t
{
/*
* Create a new input section descriptor. If this is a NOBITS
* section elf_getdata() will still create a data buffer (the buffer
* will be null and the size will reflect the actual memory size).
*/
return (S_ERROR);
/* LINTED */
return (0);
}
}
/*
* Add the new input section to the files input section list and
* to the output section list (some sections like .strtab and
* .shstrtab are not added to the output section list).
*
* If the section has the SHF_ORDERED flag on, do the ld_place_section()
* after all input sections from this file are read in.
*/
ident, 0));
}
}
return (1);
}
/*
* Determine the software capabilities of the object being built from the
* capabilities of the input relocatable objects. One software capability
*
* SF1_SUNW_FPUSED the frame pointer is in use.
*
* The resolution of the present fame pointer state, and the capabilities
* provided by a new input relocatable object are:
*
* new input relocatable object
*
* present | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | <unknown>
* state | SF1_SUNW_FPUSED | |
* ---------------------------------------------------------------------------
* SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN
* SF1_SUNW_FPUSED | SF1_SUNW_FPUSED | | SF1_SUNW_FPUSED
* ---------------------------------------------------------------------------
* SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN
* | | |
* ---------------------------------------------------------------------------
* <unknown> | SF1_SUNW_FPKNWN | SF1_SUNW_FPKNWN | <unknown>
* | SF1_SUNW_FPUSED | |
*/
static void
{
/*
* If a mapfile has established definitions to override any input
* capabilities, ignore any new input capabilities.
*/
return;
}
/*
* If this object doesn't specify any capabilities, ignore it, and
* leave the state as is.
*/
if (val == 0)
return;
/*
* Make sure we only accept known software capabilities. Note, that
* an F1_SUNW_FPUSED by itself is viewed as bad practice.
*/
val &= SF1_SUNW_MASK;
}
if (val == SF1_SUNW_FPUSED) {
return;
}
/*
* Determine the resolution of the present frame pointer and the
* new input relocatable objects frame pointer.
*/
(SF1_SUNW_FPKNWN | SF1_SUNW_FPUSED)) {
/*
* If the new relocatable object isn't using a frame pointer,
* reduce the present state to unused.
*/
/*
* If the present state is unknown, take the new relocatable
* object frame pointer usage.
*/
}
}
/*
* Determine the hardware capabilities of the object being built from the
* capabilities of the input relocatable objects. There's really little to
* do here, other than to offer diagnostics, hardware capabilities are simply
* additive.
*/
static void
{
/*
* If a mapfile has established definitions to override any input
* capabilities, ignore any new input capabilities.
*/
return;
}
/*
* If this object doesn't specify any capabilities, ignore it, and
* leave the state as is.
*/
if (val == 0)
return;
}
/*
* updating the global capabilities variables as necessary.
*/
static void
{
/*
* The capabilities are supposed to be terminated with a CA_SUNW_NULL
* entry. However, the compilers have been known to not follow this
* convention. Use the section information to determine the number
* of capabilities, and skip any CA_SUNW_NULL entries.
*/
case CA_SUNW_HW_1:
break;
case CA_SUNW_SF_1:
break;
case CA_SUNW_NULL:
break;
default:
}
}
}
/*
* Simply process the section so that we have pointers to the data for use
* in later routines, however don't add the section to the output section
* list as we will be creating our own replacement sections later (ie.
* symtab and relocation).
*/
static uintptr_t
/* ARGSUSED5 */
{
}
/*
* Keep a running count of relocation entries from input relocatable objects for
* sizing relocation buckets later. If we're building an executable, save any
* relocations from shared objects to determine if any copy relocation symbol
* has a displacement relocation against it.
*/
static uintptr_t
/* ARGSUSED5 */
{
return (S_ERROR);
/* LINTED */
ofl->ofl_relocincnt +=
return (S_ERROR);
}
return (1);
}
/*
* Process a string table section. A valid section contains an initial and
* final null byte.
*/
static uintptr_t
{
char *data;
/*
* Never include .stab.excl sections in any output file.
* If the -s flag has been specified strip any .stab sections.
*/
return (1);
/*
* If we got here to process a .shstrtab or .dynstr table, `ident' will
* be null. Otherwise make sure we don't have a .strtab section as this
* should not be added to the output section list either.
*/
if ((ident != M_ID_NULL) &&
ident = M_ID_NULL;
return (error);
/*
* String tables should start and end with a NULL byte. Note, it has
* been known for the assembler to create empty string tables, so check
* the size before attempting to verify the data itself.
*/
if (size) {
} else
return (1);
}
/*
* Invalid sections produce a warning and are skipped.
*/
static uintptr_t
/* ARGSUSED3 */
{
return (1);
}
/*
* Process a progbits section.
*/
static uintptr_t
{
int stab_index = 0;
/*
* Never include .stab.excl sections in any output file.
* If the -s flag has been specified strip any .stab sections.
*/
MSG_SCN_STAB_SIZE) == 0)) {
MSG_ORIG(MSG_SCN_EXCL)) == 0))
return (1);
MSG_ORIG(MSG_SCN_INDEX)) == 0)
stab_index = 1;
}
MSG_SCN_DEBUG_SIZE) == 0) ||
return (1);
}
/*
* Update the ident to reflect the type of section we've got.
*
* If there is any .plt or .got section to generate we'll be creating
* our own version, so don't allow any input sections of these types to
* be added to the output section list (why a relocatable object would
* have a .plt or .got is a mystery, but stranger things have occurred).
*/
if (ident) {
ident = M_ID_TLS;
(SHF_ALLOC | SHF_EXECINSTR))
ident = M_ID_TEXT;
ident = M_ID_NULL;
else if (stab_index) {
/*
* This is a work-around for x86 compilers that
* have set SHF_ALLOC for the .stab.index
* section.
*
* Because of this, make sure that the
* .stab.index does not end up as the last
* section in the text segment. Older linkers
* can produce segmentation violations when they
* strip (ld -s) against a shared object whose
* last section in the text segment is a .stab.
*/
ident = M_ID_INTERP;
} else
ident = M_ID_DATA;
} else
ident = M_ID_NOTE;
}
}
/*
* Handles the SHT_SUNW_{DEBUG,DEBUGSTR) sections.
*/
static uintptr_t
{
/*
* Debug information is discarded when the 'ld -s' flag is invoked.
*/
return (1);
}
}
/*
* Process a nobits section.
*/
static uintptr_t
{
if (ident) {
ident = M_ID_TLSBSS;
ident = M_ID_LBSS;
#endif
else
ident = M_ID_BSS;
}
}
/*
* Process a SHT_*_ARRAY section.
*/
static uintptr_t
{
if (ident)
ident = M_ID_ARRAY;
return (S_ERROR);
return (0);
(ofl->ofl_osfiniarray == 0))
(ofl->ofl_osinitarray == 0))
(ofl->ofl_ospreinitarray == 0))
return (1);
}
/*
* Process a SHT_SYMTAB_SHNDX section.
*/
static uintptr_t
{
return (S_ERROR);
/*
* Have we already seen the related SYMTAB - if so verify it now.
*/
return (S_ERROR);
}
}
return (1);
}
/*
* Final processing for SHT_SYMTAB_SHNDX section.
*/
static uintptr_t
/* ARGSUSED2 */
{
return (S_ERROR);
}
}
return (1);
}
/*
* Process .dynamic section from a relocatable object.
*
* Note: That the .dynamic section is only considered interesting when
* dlopen()ing a relocatable object (thus FLG_OF1_RELDYN can only get
* set when libld is called from ld.so.1).
*/
/*ARGSUSED*/
static uintptr_t
{
char *str;
/*
* Process .dynamic sections from relocatable objects ?
*/
return (1);
/*
* Find the string section associated with the .dynamic section.
*/
return (0);
}
/*
* And get the .dynamic data
*/
case DT_NEEDED:
case DT_USED:
if (((difl =
return (S_ERROR);
break;
case DT_RPATH:
case DT_RUNPATH:
(const char *)S_ERROR)
return (S_ERROR);
break;
case DT_VERSYM:
/*
* The Solaris ld does not put DT_VERSYM in the
* dynamic section. If the object has DT_VERSYM,
* then it must have been produced by the GNU ld,
* and is using the GNU style of versioning.
*/
break;
}
}
return (1);
}
/*
* Expand implicit references. Dependencies can be specified in terms of the
* $ORIGIN, $PLATFORM, $OSREL and $OSNAME tokens, either from their needed name,
* or via a runpath. In addition runpaths may also specify the $ISALIST token.
*
* Probably the most common reference to explicit dependencies (via -L) will be
* sufficient to find any associated implicit dependencies, but just in case we
* expand any occurrence of these known tokens here.
*
* Note, if any errors occur we simply return the original name.
*
*/
static char *platform = 0;
static size_t platform_sz = 0;
static char *
{
const char *optr;
while (*optr) {
if (nrem == 0)
return ((char *)name);
if (*optr != '$') {
continue;
}
_expanded = 0;
MSG_STR_ORIGIN_SIZE) == 0) {
char *eptr;
/*
* For $ORIGIN, expansion is really just a concatenation
* of the parents directory name. For example, an
*/
*nptr++ = '.';
nrem--;
} else {
return ((char *)name);
}
MSG_STR_PLATFORM_SIZE) == 0) {
/*
* Establish the platform from sysconf - like uname -i.
*/
if ((platform == 0) && (platform_sz == 0)) {
long size;
if ((size != -1) &&
} else
platform_sz = 1;
}
if (platform != 0) {
if (platform_sz >= nrem)
return ((char *)name);
nrem -= platform_sz;
}
MSG_STR_OSNAME_SIZE) == 0) {
/*
* Establish the os name - like uname -s.
*/
if (uts == 0)
return ((char *)name);
uts->uts_osnamesz);
}
MSG_STR_OSREL_SIZE) == 0) {
/*
* Establish the os release - like uname -r.
*/
if (uts == 0)
return ((char *)name);
uts->uts_osrelsz);
}
/*
* Establish instruction sets from sysconf. Note that
* this is only meaningful from runpaths.
*/
if (isa == 0)
isa = conv_isalist();
char *lptr;
opt->isa_namesz);
/*
* As ISALIST expands to a number of elements,
* establish a new list to return to the caller.
* This will contain the present path being
* processed redefined for each isalist option,
* plus the original remaining list entries.
*/
if (*next)
return (0);
opt->isa_namesz);
*lptr++ = ':';
}
if (*next)
else
*--lptr = '\0';
}
}
/*
* If no expansion occurred skip the $ and continue.
*/
if (_expanded == 0)
}
/*
* If any ISALIST processing has occurred not only do we return the
* expanded node we're presently working on, but we must also update the
* remaining list so that it is effectively prepended with this node
* expanded to all remaining isalist options. Note that we can only
* handle one ISALIST per node. For more than one ISALIST to be
* processed we'd need a better algorithm than above to replace the
* newly generated list. Whether we want to encourage the number of
* pathname permutations this would provide is another question. So, for
* now if more than one ISALIST is encountered we return the original
* node untouched.
*/
if (isaflag) {
if (isaflag == 1)
else
return ((char *)name);
}
*nptr = '\0';
if (expanded) {
return ((char *)name);
return (nptr);
}
return ((char *)name);
}
/*
* The Solaris ld does not put DT_VERSYM in the dynamic section, but the
* GNU ld does, and it is used by the runtime linker to implement their
* versioning scheme. Use this fact to determine if the sharable object
* was produced by the GNU ld rather than the Solaris one, and to set
* FLG_IF_GNUVER if so. This needs to be done before the symbols are
* processed, since the answer determines whether we interpret the
* symbols versions according to Solaris or GNU rules.
*/
/*ARGSUSED*/
static uintptr_t
{
return (S_ERROR);
/* Get the .dynamic data */
break;
}
}
return (1);
}
/*
* Process a dynamic section. If we are processing an explicit shared object
* then we need to determine if it has a recorded SONAME, if so, this name will
* be recorded in the output file being generated as the NEEDED entry rather
* than the shared objects filename itself.
* If the mode of the link-edit indicates that no undefined symbols should
* remain, then we also need to build up a list of any additional shared object
* dependencies this object may have. In this case save any NEEDED entries
* together with any associated run-path specifications. This information is
* recorded on the `ofl_soneed' list and will be analyzed after all explicit
* file processing has been completed (refer finish_libs()).
*/
static uintptr_t
{
/*
* First loop through the dynamic section looking for a run path.
*/
continue;
continue;
break;
}
}
/*
* Now look for any needed dependencies (which may use the rpath)
* or a new SONAME.
*/
continue;
/*
* Update the input file structure with this new name.
*/
continue;
continue;
/*
* Determine if this needed entry is already recorded on
* the shared object needed list, if not create a new
* definition for later processing (see finish_libs()).
*/
return (S_ERROR);
}
/*
* Record the runpath (Note that we take the first
* runpath which is exactly what ld.so.1 would do during
* its dependency processing).
*/
/*
* Record audit string as DT_DEPAUDIT.
*/
(const char *)S_ERROR)
return (S_ERROR);
/*
* If a library has the SUNW_RTLDINF .dynamic entry
* then we must not permit lazyloading of this library.
* This is because critical startup information (TLS
* routines) are provided as part of these interfaces
* and we must have them as part of process startup.
*/
}
}
/*
* Perform some SONAME sanity checks.
*/
/*
* Determine if anyone else will cause the same SONAME to be
* used (this is either caused by two different files having the
* same SONAME, or by one file SONAME actually matching another
* file basename (if no SONAME is specified within a shared
* library its basename will be used)). Probably rare, but some
* idiot will do it.
*/
/*
* Determine the basename of each file. Perhaps
* there are multiple copies of the same file
* being brought in using different -L search
* paths, and if so give an extra hint in the
* error message.
*/
else
iflb++;
else
siflb++;
else
return (0);
}
}
/*
* If the SONAME is the same as the name the user wishes to
* record when building a dynamic library (refer -h option),
* we also have a name clash.
*/
if (ofl->ofl_soname &&
ifl->ifl_soname);
return (0);
}
}
return (1);
}
/*
* Process a relocation entry. At this point all input sections from this
* input file have been assigned an input section descriptor which is saved
* in the `ifl_isdesc' array.
*/
static uintptr_t
{
/*
* Make sure this is a valid relocation we can handle.
*/
return (0);
}
/*
* From the relocation section header information determine which
* section needs the actual relocation. Determine which output section
* this input section has been assigned to and add to its relocation
* list. Note that the relocation section may be null if it is not
* required (ie. .debug, .stabs, etc).
*/
/*
* Broken input file.
*/
return (0);
}
if (rndx == 0) {
return (S_ERROR);
/*
* Discard relocations if they are against a section
* which has been discarded.
*/
return (1);
/*
* This section is processed later
* in sunwmove_preprocess() and
* reloc_init().
*/
isc) == 0)
return (S_ERROR);
return (1);
}
return (0);
}
return (S_ERROR);
}
return (1);
}
/*
* SHF_EXCLUDE flags is set for this section.
*/
static uintptr_t
{
/*
* Sections SHT_SYMTAB and SHT_DYNDYM, even if SHF_EXCLUDE is on, might
* be needed for ld processing. These sections need to be in the
* internal table. Later it will be determined whether they can be
* eliminated or not.
*/
return (0);
/*
* Other checks
*/
/*
* A conflict, issue an warning message, and ignore the section.
*/
return (0);
}
/*
* This sections is not going to the output file.
*/
}
static uintptr_t
{
return (S_ERROR);
/*
* When producing a relocatable object - just collect the sections.
*/
return (1);
/*
* If producing a executable or shared library, keep track of all the
* output UNWIND sections to allow the creation of the appropriate
* frame_hdr information.
*
* If the section hasn't been placed in the output file, then there's
* nothing for us to do.
*/
return (1);
/*
* Check to see if this output section is already on the list, and if
* not, add it.
*/
return (1);
return (S_ERROR);
return (1);
}
#endif
/*
* Section processing state table. `Initial' describes the required initial
* procedure to be called (if any), `Final' describes the final processing
* procedure (ie. things that can only be done when all required sections
* have been collected).
*/
/* ET_REL ET_DYN */
};
};
#define MAXNDXSIZE 10
/*
* Process an elf file. Each section is compared against the section state
* table to determine whether it should be processed (saved), ignored, or
* is invalid for the type of input file being processed.
*/
static uintptr_t
{
int ident;
Word ordered_cnt = 0;
/*
* First process the .shstrtab section so that later sections can
* reference their name.
*/
return (0);
}
return (0);
}
NULL) {
return (0);
}
return (S_ERROR);
/*
* Reset the name since the shdr->sh_name could have been changed as
* part of ld_sup_input_section(). If there is no name, fabricate one
* using the section index.
*/
return (S_ERROR);
return (0);
}
return (error);
/*
* Determine the state table column from the input file type. Note,
* shared library sections are not added to the output section list.
*/
column = 1;
ofl->ofl_soscnt++;
ident = M_ID_NULL;
} else {
column = 0;
ofl->ofl_objscnt++;
ident = M_ID_UNKNOWN;
}
ndx = 0;
ndx++;
/*
* As we've already processed the .shstrtab don't do it again.
*/
continue;
return (0);
}
return (S_ERROR);
/*
* Reset the name since the shdr->sh_name could have been
* changed as part of ld_sup_input_section(). If there is no
* name, fabricate one using the section index.
*/
return (S_ERROR);
} else
/*
* If the section has the SHF_EXCLUDE flag on, and we're not
* generating a relocatable object, exclude the section.
*/
return (S_ERROR);
if (error == 1)
continue;
}
/*
* If this is a standard section type process it via the
* appropriate action routine.
*/
return (S_ERROR);
}
} else {
/*
* If this section is below SHT_LOSUNW then we don't
* really know what to do with it, issue a warning
* message but do the basic section processing anyway.
*/
name,
/*
* Handle sections greater than SHT_LOSUNW.
*/
switch (row) {
case SHT_SUNW_dof:
return (S_ERROR);
break;
case SHT_SUNW_cap:
return (S_ERROR);
break;
case SHT_SUNW_DEBUGSTR:
case SHT_SUNW_DEBUG:
return (S_ERROR);
break;
case SHT_SUNW_move:
return (S_ERROR);
break;
case SHT_SUNW_syminfo:
return (S_ERROR);
break;
case SHT_SUNW_ANNOTATE:
case SHT_SUNW_COMDAT:
return (S_ERROR);
break;
case SHT_SUNW_verdef:
return (S_ERROR);
break;
case SHT_SUNW_verneed:
return (S_ERROR);
break;
case SHT_SUNW_versym:
return (S_ERROR);
break;
#if defined(__sparc)
case SHT_SPARC_GOTDATA:
return (S_ERROR);
break;
#endif
case SHT_AMD64_UNWIND:
if (column == 0) {
/*
* column == ET_REL
*/
return (S_ERROR);
}
break;
#endif
default:
if (ident != M_ID_NULL)
ident = M_ID_USER;
return (S_ERROR);
break;
}
}
/*
* If we have any sections that require ORDERED processing,
* remember the index of the first ordered section. This let's
* us know if we need an ORDERED place_section pass, and if so,
* where to start.
*/
ordered_cnt++;
if (ordered_shndx == 0)
ordered_shndx = ndx;
}
}
/*
* Now that all of sections have been placed, scan through any sections
* which have special ordering requirements and place them now.
*/
if (ordered_shndx) {
/* LINTED */
continue;
/*
* If this is an ordered section, process it.
*/
cnt++;
return (S_ERROR);
/*
* If this section is 'ordered' then it was not
* caught in the previous 'place_section' operation.
*
* So - now that we have a OSP section for
* the unwind info - record it.
*/
if (osp &&
return (S_ERROR);
#endif
}
}
/*
* If this is an explicit shared object determine if the user has
* specified a control definition. This descriptor may specify which
* version definitions can be used from this object (it may also update
* the dependency to USED and supply an alternative SONAME).
*/
sdf = 0;
const char *base;
/*
* Use the basename of the input file (typically this is the
* compilation environment name, ie. libfoo.so).
*/
else
base++;
}
}
/*
* capabilities for input relocatable objects. If the object doesn't
* contain any capabilities, any capability state that has already been
* gathered will prevail.
*/
/*
* Process any version dependencies. These will establish shared object
* `needed' entries in the same manner as will be generated from the
* .dynamic's NEEDED entries.
*/
return (S_ERROR);
/*
* Before processing any symbol resolution or relocations process any
* version sections.
*/
if (vsyisp)
if (ifl->ifl_versym &&
return (S_ERROR);
/*
* Having collected the appropriate sections carry out any additional
* processing if necessary.
*/
continue;
/*
* If this is a ST_SUNW_move section from a
* a relocatable file, keep the input section.
*/
return (S_ERROR);
}
/*
* If this is a standard section type process it via the
* appropriate action routine.
*/
return (S_ERROR);
}
}
/*
* After processing any symbol resolution, and if this dependency
* indicates it contains symbols that can't be directly bound to,
* set the symbols appropriately.
*/
(FLG_IF_NEEDED | FLG_IF_NODIRECT)))
return (1);
}
/*
* Process the current input file. There are basically three types of files
* that come through here:
*
* o files explicitly defined on the command line (ie. foo.o or bar.so),
* in this case only the `name' field is valid.
*
* o libraries determined from the -l command line option (ie. -lbar),
* in this case the `soname' field contains the basename of the located
* file.
*
* Any shared object specified via the above two conventions must be recorded
* as a needed dependency.
*
* o libraries specified as dependencies of those libraries already obtained
* in this case the `soname' field contains either a full pathname (if the
* needed entry contained a `/'), or the basename of the located file.
* These libraries are processed to verify symbol binding but are not
* recorded as dependencies of the output file being generated.
*/
Ifl_desc *
{
/*
* If this file was not extracted from an archive obtain its device
* information. This will be used to determine if the file has already
* been processed (rather than simply comparing filenames, the device
* information provides a quicker comparison and detects linked files).
*/
if (!(flags & FLG_IF_EXTRACT))
else {
}
case ELF_K_AR:
/*
* Determine if we've already come across this archive file.
*/
if (!(flags & FLG_IF_EXTRACT)) {
continue;
/*
* We've seen this file before so reuse the
* original archive descriptor and discard the
* new elf descriptor.
*/
}
}
/*
* As we haven't processed this file before establish a new
* archive descriptor.
*/
case ELF_K_ELF:
/*
* Obtain the elf header so that we can determine what type of
* elf ELF_K_ELF file this is.
*/
/*
* Failure could occur for a number of reasons at this
* point. Typically the files class is incorrect (ie.
* user is building 64-bit but managed to pint at 32-bit
* libraries). However any number of elf errors can
* also occur, such as from a truncated or corrupt file.
* Here we try and get the best error message possible.
*/
} else {
}
}
return (0);
}
/*
* Determine if we've already come across this file.
*/
if (!(flags & FLG_IF_EXTRACT)) {
else
/*
* Traverse the appropriate file list and determine if
*/
/*
* Ifl_desc generated via -Nneed, therefore no
* actual file behind it.
*/
continue;
continue;
/*
* Disregard (skip) this image.
*/
/*
* If the file was explicitly defined on the
* command line (this is always the case for
* relocatable objects, and is true for shared
* objects when they weren't specified via -l or
* were dragged in as an implicit dependency),
* then warn the user.
*/
if ((flags & FLG_IF_CMDLINE) ||
const char *errmsg;
/*
* Determine whether this is the same
* file name as originally encountered
* so as to provide the most
* descriptive diagnostic.
*/
errmsg =
else
errmsg =
}
return (ifl);
}
}
/*
* At this point, we know we need the file. Establish an input
* file descriptor and continue processing.
*/
return (ifl);
/*
* If -zignore is in effect, mark this file as a potential
* candidate (the files use isn't actually determined until
* symbol resolution and relocation processing are completed).
*/
case ET_REL:
break;
case ET_DYN:
return (0);
}
/*
* Record any additional shared object information.
* If no soname is specified (eg. this file was
* derived from a explicit filename declaration on the
* command line, ie. bar.so) use the pathname.
* This entry may be overridden if the files dynamic
* section specifies an DT_SONAME value.
*/
else
/*
* If direct bindings, lazy loading, or group
* permissions need to be established, mark this object.
*/
/*
* At this point we know if this file will be
* lazyloaded, or whether bindings to it must be direct.
* In either case, a syminfo section is required.
*/
break;
default:
(void) elf_errno();
}
return (0);
}
break;
default:
(void) elf_errno();
}
return (0);
}
else
return (ifl);
}
/*
* Having successfully opened a file, set up the necessary elf structures to
* process it further. This small section of processing is slightly different
* from the elf initialization required to process a relocatable object from an
* archive (see libs.c: ld_process_archive()).
*/
Ifl_desc *
{
return (0);
}
/*
* Determine whether the support library wishes to process this open.
* The support library may return:
* . a different ELF descriptor (in which case they should have
* closed the original)
* . a different file descriptor (in which case they should have
* closed the original)
* . a different path and file name (presumably associated with
* a different file descriptor)
*
* A file descriptor of -1, or and ELF descriptor of zero indicates
* the file should be ignored.
*/
return (0);
}
/*
* Process a required library (i.e. the dependency of a shared object).
* Combine the directory and filename, check the resultant path size, and try
* opening the pathname.
*/
static Ifl_desc *
{
int fd;
/*
* Determine the sizes of the directory and filename to insure we don't
* exceed our buffer.
*/
dlen = 1;
}
dlen++;
return (0);
}
/*
* Build the entire pathname and try and open the file.
*/
return (0);
else {
char *_path;
if (fd != -1)
return (ifl);
}
}
/*
* Finish any library processing. Walk the list of so's that have been listed
* as "included" by shared objects we have previously processed. Examine them,
* without adding them as explicit dependents of this program, in order to
* complete our symbol definition process. The search path rules are:
*
* o use any user supplied paths, i.e. LD_LIBRARY_PATH and -L, then
*
* o use any RPATH defined within the parent shared object, then
*
* o use the default directories, i.e. LIBPATH or -YP.
*/
{
/*
* Make sure we are back in dynamic mode.
*/
int fd;
/*
* See if this file has already been processed. At the time
* this implicit dependency was determined there may still have
* been more explicit dependencies to process. Note, if we ever
* do parse the command line three times we would be able to
* do all this checking when processing the dynamic section.
*/
continue;
break;
}
}
continue;
/*
* If the current path name element embeds a "/", then it's to
* be taken "as is", with no searching involved. Process all
* "/" occurrences, so that we can deduce the base file name.
*/
if (*path == '/')
}
if (slash) {
} else {
0, &_rej);
if (fd != -1)
return (S_ERROR);
}
conv_reject_desc(&_rej));
} else
}
continue;
}
/*
* Now search for this file in any user defined directories.
*/
return (S_ERROR);
}
}
}
if (ifl) {
break;
}
}
continue;
/*
* Next use the local rules defined within the parent shared
* object.
*/
if (rpath == 0)
return (S_ERROR);
do {
&next);
return (S_ERROR);
}
}
if (ifl) {
break;
}
}
}
continue;
/*
* Finally try the default library search directories.
*/
return (S_ERROR);
}
}
}
if (ifl) {
break;
}
}
continue;
/*
* If we've got this far we haven't found the shared object.
* If an object was found, but was rejected for some reason,
* print a diagnostic to that effect, otherwise generate a
* generic "not found" diagnostic.
*/
} else {
}
}
/*
* Finally, now that all objects have been input, make sure any version
* requirements have been met.
*/
return (ld_vers_verify(ofl));
}