libs.c revision 6b3ba5bde920961dbf915c89b7736f96ff487d20
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Library processing
*/
#include <stdio.h>
#include <string.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
/*
* Archive members are typically extracted to resolve an existing undefined
* reference. However, other symbol definitions can cause archive members to
* be processed to determine if the archive member provides a more appropriate
* definition. This routine processes the archive member to determine if the
* member is really required.
*
* i. Tentative symbols may cause the extraction of an archive member.
* If the archive member has a strong defined symbol it will be used.
* If the archive member simply contains another tentative definition,
* or a defined function symbol, then it will not be used.
*
* ii. A symbol reference may define a hidden or protected visibility. The
* reference can only be bound to a definition within a relocatable object
* for this restricted visibility to be satisfied. If the archive member
* provides a definition of the same symbol type, this definition is
* taken. The visibility of the defined symbol is irrelevant, as the most
* restrictive visibility of the reference and the definition will be
* applied to the final symbol.
*/
static int
{
char *strs;
/*
* Find the first symbol table in the archive member, obtain its
* data buffer and determine the number of global symbols (Note,
* there must be a symbol table present otherwise the archive would
* never have been able to generate its own symbol entry for this
* member).
*/
return (0);
}
break;
}
return (0);
}
/*
* Get the data for the associated string table.
*/
NULL) {
return (0);
}
return (0);
}
/*
* Initialize the archive member structure in case we have to
* come through here again.
*/
} else {
}
/*
* Loop through the symbol table entries looking for a match for the
* original symbol.
*/
continue;
/*
* Determine whether a tentative symbol definition
* should be overridden.
*/
continue;
/*
* A historic detail requires that a weak definition
* within an archive will not override a strong
* definition (see sym_realtent() resolution and ABI
* symbol binding description - page 4-27).
*/
continue;
} else {
/*
* Determine whether a restricted visibility reference
* should be overridden. Don't worry about the
* visibility of the archive member definition, nor
* whether it is weak or global. Any definition is
* better than a binding to an external shared object
* (which is the only event that must presently exist
* for us to be here looking for a better alternative).
*/
continue;
}
return (1);
}
return (0);
}
/*
* Create an archive descriptor. By maintaining a list of archives any
* duplicate occurrences of the same archive specified by the user enable us to
* pick off where the last processing finished.
*/
Ar_desc *
{
/*
* Get the archive symbol table. If this fails, we will
* ignore this file with a warning message.
*/
if (elf_errno()) {
} else
return (0);
}
/*
* As this is a new archive reference establish a new descriptor.
*/
/*
* Retain any command line options that are applicable to archive
* extraction in case we have to rescan this archive later.
*/
ofl->ofl_arscnt++;
/*
* Add this new descriptor to the list of archives.
*/
else
return (adp);
}
/*
* For each archive descriptor, maintain an `Ar_aux' table to parallel the
* archive symbol table (returned from elf_getarsym(3e)). Use this table to
* hold a `Sym_desc' for each symbol (thus reducing the number of
* ld_sym_find()'s), and to hold the `Ar_mem' pointer. The `Ar_mem' element
* can have one of three values indicating the state of the archive member
* associated with the offset for this symbol table entry:
*
* 0 indicates that the member has not been processed.
*
* FLG_ARMEM_PROC
* indicates that the member has been processed.
*
* addr indicates that the member has been investigated to determine if
* it contained a symbol definition we need, but was found not to
* be a candidate for extraction. In this case the members
* structure is maintained for possible later use.
*
* Each time we process an archive member we use its offset value to scan this
* `Ar_aux' list. If the member has been extracted, each entry with the same
* offset has its `Ar_mem' pointer set to FLG_ARMEM_PROC. Thus if we cycle back
* through the archive symbol table we will ignore these symbols as they will
* have already been added to the output image. If a member has been processed
* but found not to contain a symbol we need, each entry with the same offset
* has its `Ar_mem' pointer set to the member structures address.
*/
void
{
do {
_arsym--;
_aup--;
break;
}
do {
break;
_arsym++;
_aup++;
}
/*
* Data structure to indicate whether a symbol is visible for the purpose
* of archive extraction.
*/
static const Boolean
TRUE, /* STV_DEFAULT */
FALSE, /* STV_INTERNAL */
FALSE, /* STV_HIDDEN */
FALSE, /* STV_PROTECTED */
TRUE, /* STV_EXPORTED */
TRUE, /* STV_SINGLETON */
FALSE /* STV_ELIMINATE */
};
#error "STV_NUM has grown. Update sym_vis[]."
#endif
/*
* Read the archive symbol table. For each symbol in the table, determine
* whether that symbol satisfies an unresolved reference, tentative reference,
* or a reference that expects hidden or protected visibility. If so, the
* corresponding object from the archive is processed. The archive symbol
* table is searched until we go through a complete pass without satisfying any
* unresolved symbols
*/
{
/*
* If a fatal error condition has been set there's really no point in
* processing the archive further. Having got to this point we have at
* least established that the archive exists (thus verifying that the
* command line options that got us to this archive are correct). Very
* large archives can take a significant time to process, therefore
* continuing on from here may significantly delay the fatal error
* message the user is already set to receive.
*/
return (1);
/*
* If this archive was processed with -z allextract, then all members
* have already been extracted.
*/
return (1);
/*
* Loop through archive symbol table until we make a complete pass
* without satisfying an unresolved reference. For each archive
* symbol, see if there is a symbol with the same name in ld's
* symbol table. If so, and if that symbol is still unresolved or
* tentative, process the corresponding archive member.
*/
do {
/*
* If the auxiliary members value indicates that this
* member has been processed then this symbol will have
* been added to the output file image already or the
* object was rejected in which case we don't want to
* process it again.
*/
continue;
/*
* If the auxiliary symbol element is non-zero lookup
* the symbol from the internal symbol table.
* (But you skip this if allextract is specified.)
*/
/* LINTED */
continue;
}
}
/*
* With '-z allextract', all members will be extracted.
*
* This archive member is a candidate for extraction if
* the internal symbol originates from an explicit file,
* and represents an undefined or tentative symbol.
*
* By default, weak references do not cause archive
* extraction, however the -zweakextract flag overrides
* this default.
*
* If this symbol has already been bound to a versioned
* shared object, but the shared objects version is not
* available, then a definition of this symbol from
* within the archive is a better candidate. Similarly,
* if this symbol has been bound to a shared object, but
* the original reference expected hidden or protected
* visibility, then a definition of this symbol from
* within the archive is a better candidate.
*/
if (allexrt == 0) {
if (ifl->ifl_vercnt) {
FLG_VER_AVAIL) == 0)
}
}
continue;
}
}
/*
* Determine if we have already extracted this member,
* and if so reuse the Ar_mem information.
*/
} else {
/*
* Set up a new elf descriptor for this member.
*/
return (0);
}
return (0);
}
/*
* Construct the member filename.
*/
return (0);
}
/*
* Construct the members full pathname, using
* the format "%s(%s)".
*/
return (S_ERROR);
/*
* Determine whether the support library wishes
* to process this open. See comments in
* ld_process_open().
*/
/*
* An ELF descriptor of zero indicates that
* the archive member should be ignored.
*/
continue;
}
}
/*
* The symbol for which this archive member is being
* processed may provide a better alternative to the
* symbol that is presently known. Two cases are
* covered:
*
* i. The present symbol represents tentative data.
* The archive member may provide a data
* definition symbol.
* ii. The present symbol represents a reference that
* has seen a definition within a shared object
* dependency, but the reference expects to be
* reduced to hidden or protected visibility.
*/
if ((allexrt == 0) &&
/*
* If we don't already have a member structure
* allocate one.
*/
if (!amp) {
1)) == 0)
return (S_ERROR);
}
return (S_ERROR);
/*
* If it turns out that we don't need this
* member simply initialize all other auxiliary
* entries that match this offset with this
* members address. In this way we can resuse
* this information if we recurse back to this
* symbol.
*/
if (err == 0) {
continue;
}
}
/*
* Process the archive member. Retain any error for
* return to the caller.
*/
return (S_ERROR);
/*
* If this member is rejected maintain the first
* rejection error for possible later display. Keep the
* member as extracted so that we don't try and process
* it again on a rescan.
*/
}
continue;
}
/*
* Indicate that the extracted member is in use. This
* enables debugging diags, and indicates that a further
* rescan of all archives may be necessary.
*/
found = 1;
/*
* If not under '-z allextract' signal the need to
* rescan this archive.
*/
if (allexrt == 0)
again = 1;
}
} while (again);
/*
* If no objects have been found in the archive test for any rejections
* and if one had occurred issue a warning - its possible a user has
* pointed at an archive containing the wrong class of elf members.
*/
}
/*
* If this archive was extracted by -z allextract, the ar_aux table
* and elf descriptor can be freed. Set ad_elf to NULL to mark the
* archive is completely processed.
*/
if (allexrt) {
}
return (1);
}