setup.c revision 75e7992ad4e186443b61dab39f79c9d79802f295
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Run time linker common setup.
*
* Called from _setup to get the process going at startup.
*/
#include "_synonyms.h"
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/sysconfig.h>
#include <debug.h>
#include <conv.h>
#include "_rtld.h"
#include "_audit.h"
#include "_elf.h"
#include "_a.out.h"
#include "msg.h"
extern void _init(void);
extern int _brk_unlocked(void *);
#ifndef SGS_PRE_UNIFIED_PROCESS
/* needed for _brk_unlocked() */
#endif
/*
* Define for the executable's interpreter.
* Usually it is ld.so.1, but for the first release of ICL binaries
* it is libc.so.1. We keep this information so that we don't end
* up mapping libc twice if it is the interpreter.
*/
static int
{
return (0);
/*
* Establish the flags for loading each object. If we're called via
* lddstub, then the first shared object is the object being inspected
* by ldd(1). This object should not be marked as an interposer, as
* it is intended to act like the first object of the process.
*/
else
do {
/*
* If this a secure application, then preload errors are
* reduced to warnings, as the errors are non-fatal.
*/
if (rtld_flags & RT_FL_SECURE)
if (pnp)
if (rtld_flags & RT_FL_SECURE)
nlmp = 0;
/*
* Establish state for the next preloadable object. If no
* error occurred with loading this object, indicate that this
* link-map list contains an interposer.
*/
flags |= FLG_RT_OBJINTPO;
if (nlmp == 0) {
if ((lmflags & LML_FLG_TRC_ENABLE) ||
(rtld_flags & RT_FL_SECURE))
continue;
else
return (0);
}
/*
* If we're tracing shared objects via lddstub, establish a
* binding between the initial shared object and lddstub so that
* the shared object isn't called out from unused() processing.
* After the first object is loaded increment the caller to the
* initial preloaded object to provide intuitive ldd -v and -s
* diagnostics
*/
if ((lmflags & LML_FLG_TRC_ENABLE) &&
(LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED))) {
continue;
}
}
return (1);
}
Rt_map *
{
/*
* Now that ld.so has relocated itself, initialize our own 'environ' so
* magic (libc/sparc/crt/hwmuldiv.o).
*/
_init();
/*
* Far the most common application execution revolves around appending
* the application name to the users PATH definition, thus a full name
* is passed to exec() which will in turn be returned via
* AT_SUN_EXECNAME. Applications may also be invoked from the current
* working directory, or via a relative name.
*
* Determine whether the kernel has supplied a AT_SUN_EXECNAME aux
* vector. This vector points to the full pathname, on the stack, of
* the object that started the process. If this is null, then
* AT_SUN_EXECNAME isn't supported (if the pathname exceeded the system
* limit (PATH_MAX) the exec would have failed). This flag is used to
* determine whether we can call resolvepath().
*/
if (execname)
/*
* Determine how ld.so.1 has been executed.
*/
/*
* If we received neither the AT_EXECFD nor the AT_PHDR aux
* vector, ld.so.1 must have been invoked directly from the
* command line.
*/
ldsoexec = 1;
/*
* AT_SUN_EXECNAME provides the most precise name, if it is
* available, otherwise fall back to argv[0]. At this time,
* there is no process name.
*/
if (execname)
else if (argv[0])
else
} else {
/*
* Otherwise, we have a standard process. AT_SUN_EXECNAME
* provides the most precise name, if it is available,
* otherwise fall back to argv[0]. Provided the application
* is already mapped, the process is the application, so
* simplify the application name for use in any diagnostics.
*/
if (execname)
else if (argv[0])
else
if (fd == -1) {
else
}
/*
* At this point, we don't know the runtime linkers full path
* name. The _rtldname passed to us is the SONAME of the
* what the full path is. Use this for now, we'll reset the
* runtime linkers name once the application is analyzed.
*/
if (_rtldname) {
else
} else
}
/*
* Initialize any global variables.
*/
if (dz_fd != FD_UNAVAIL)
/*
* If pagesize is unspecified find its value.
*/
fmap_setup();
/*
* Add the unused portion of the last data page to the free space list.
* The page size must be set before doing this. Here, _end refers to
* the end of the runtime linkers bss. Note that we do not use the
* unused data pages from any included .so's to supplement this free
* space as badly behaved .os's may corrupt this data space, and in so
* doing ruin our data.
*/
if (esize) {
}
/*
* Establish initial link-map list flags, and link-map list alists.
*/
AL_CNT_LMLISTS) == 0)
return (0);
AL_CNT_LMLISTS) == 0)
return (0);
/*
* Determine whether we have a secure executable.
*/
/*
* Initialize a hardware capability descriptor for use in comparing
* each loaded object.
*/
#ifdef AT_SUN_AUXFLAGS
if (auxflags & AF_SUN_HWCAPVERIFY) {
}
#endif
/*
* Look for environment strings (allows things like LD_NOAUDIT to be
* established, although debugging isn't enabled until later).
*/
return (0);
/*
* Create a mapping descriptor for ld.so.1. We can determine our
* two segments information from known symbols.
*/
return (0);
/*
* Create a link map structure for ld.so.1.
*/
return (0);
}
/*
* Initialize the runtime linkers information.
*/
/*
* If ld.so.1 has been invoked directly, process its arguments.
*/
if (ldsoexec) {
/*
* Process any arguments that are specific to ld.so.1, and
* reorganize the process stack to effectively remove ld.so.1
* from it. Reinitialize the environment pointer, as this may
* have been shifted after skipping ld.so.1's arguments.
*/
return (0);
}
/*
* Open the object that ld.so.1 is to execute.
*/
return (0);
}
}
/*
* Map in the file, if exec has not already done so. If it has,
* simply create a new link map structure for the executable.
*/
if (fd != -1) {
/*
* Find out what type of object we have.
*/
return (0);
}
/*
* Map in object.
*/
return (0);
/*
* We now have a process name for error diagnostics.
*/
else
if (ldsoexec) {
/*
* Since ld.so.1 was the primary executed object - the
* brk() base has not yet been initialized, we need to
* initialize it. For an executable, initialize it to
* the end of the object. For a shared object (ET_DYN)
* initialize it to the first page in memory.
*/
int i;
/*
* We scan the program headers to find the tail
* of the memory image. We can't use MSIZE()
* since that's already been page aligned.
*/
}
}
if (!brkbase)
}
}
/*
* The object has now been mmaped, we no longer need the file
* descriptor.
*/
} else {
/*
* Set up function ptr and arguments according to the type
* of file class the executable is. (Currently only supported
* types are ELF and a.out format.) Then create a link map
* for the executable.
*/
if (aoutdyn) {
#ifdef A_OUT
aoutdyn, 0, 0, ALIST_OFF_DATA)) == 0)
return (0);
/*
* Set the memory size. Note, we only know the end of
* text, and although we could find the _end by looking
* up the symbol, this may not be present. We should
* set ADDR to MAIN_BASE, but presently all the a.out
* relocation code assumes ADDR is 0 for the dynamic
* executable. (these data items are only used for
* dladdr(3x), and there aren't many a.out dladdr(3x)
* users to warrant spending much time on this :-).
*/
/*
* Disable any object configuration cache (BCP apps
* bring in sbcp which can benefit from any object
* cache, but both the app and sbcp can't use the same
* objects).
*/
/*
* Make sure no-direct bindings are in effect.
*/
#else
return (0);
#endif
} else if (phdr) {
int i;
/*
* Using the executables phdr address determine the base
* address of the input file. NOTE, this assumes the
* program headers and elf header are part of the same
* mapped segment. Although this has held for many
* years now, it might be more flexible if the kernel
* gave use the ELF headers start address, rather than
* the Program headers.
*
* Determine from the ELF header if we're been called
* from a shared object or dynamic executable. If the
* latter, then any addresses within the object are used
* as is. Addresses within shared objects must be added
* to the process's base address.
*/
/*
* Allocate a mapping array to retain mapped segment
* information.
*/
return (0);
/*
* Extract the needed information from the segment
* headers.
*/
}
if (!firstptr)
(i_offset <=
i_offset = 0;
}
else
perm |= PROT_WRITE;
/*
* Retain segments mapping info. Round
* each segment to a page boundary, as
* this insures addresses are suitable
* for mprotect() if required.
*/
mmapcnt++;
unwindphdr = pptr;
}
}
mmapcnt)) == 0) {
return (0);
}
if (tlsphdr &&
return (0);
if (unwindphdr)
if (cap)
}
}
/*
* Establish the interpretors name as that defined within the initial
* object (executable). This provides for ORIGIN processing of ld.so.1
* dependencies.
*/
if (ldsoexec == 0) {
}
else
/*
* Having established the true runtime linkers name, simplify the name
* for error diagnostics.
*/
else
/*
* Expand the fullpath name of the application. This typically occurs
* as a part of loading an object, but as the kernel probably mapped
* it in, complete this processing now.
*/
/*
* Some troublesome programs will change the value of argv[0]. Dupping
* the process string protects us, and insures the string is left in
* any core files.
*/
return (0);
/*
* If the kernel has provided hardware capabilities information, and
* the executable contains hardware capabilities information, make
* sure it's a valid object.
*/
const char *str =
} else {
return (0);
}
}
}
/*
* It's the responsibility of MAIN(crt0) to call it's _init and _fini
* collected during tsort processing. And, if the application has no
* initarray or finiarray we can economize on establishing bindings.
*/
/*
* Identify lddstub if necessary.
*/
/*
* Retain our argument information for use in dlinfo.
*/
(void) enter();
/*
* Add our two main link-maps to the dynlm_list
*/
return (0);
return (0);
/*
* Reset the link-map counts for both lists. The init count is used to
* track how many objects have pending init sections, this gets incre-
* mented each time an object is relocated. Since ld.so.1 relocates
* itself, it's init count will remain zero.
* The object count is used to track how many objects have pending fini
* sections, as ld.so.1 handles its own fini we can zero its count.
*/
/*
* Initialize debugger information structure. Some parts of this
* structure were initialized statically.
*/
if (platform)
/*
* load_so() checking for those who might dlopen(a.out).
*/
}
/*
* Initialize any configuration information.
*/
if (!(rtld_flags & RT_FL_NOCFG)) {
return (0);
}
/*
* Establish the modes of the initial object. These modes are
* propagated to any preloaded objects and explicit shared library
* dependencies.
*
* If we're generating a configuration file using crle(1), remove
* any RTLD_NOW use, as we don't want to trigger any relocation proc-
* essing during crle(1)'s first past (this would just be unnecessary
* overhead). Any filters are explicitly loaded, and thus RTLD_NOW is
* not required to trigger filter loading.
*
* Note, RTLD_NOW may have been established during analysis of the
* application had the application been built -z now.
*/
if (rtld_flags & RT_FL_CONFGEN) {
}
if (rtld_flags2 & RT_FL2_BINDNOW)
else
}
/*
* If debugging was requested initialize things now that any cache has
* been established. A user can specify LD_DEBUG=help to discover the
* list of debugging tokens available without running the application.
* However, don't allow this setting from a configuration file.
*
* Note, to prevent recursion issues caused by loading and binding the
* debugging libraries themselves, a local debugging descriptor is
* initialized. Once the debugging setup has completed, this local
* descriptor is copied to the global descriptor which effectively
* enables diagnostic output.
*/
if (rpl_debug) {
return (0);
if (ret == 0)
}
if (prm_debug)
}
/*
* Now that debugging is enabled generate any diagnostics from any
* previous events.
*/
if (hwcap)
if (features)
features));
if (DBG_ENABLED) {
} else {
}
}
/*
* Enable auditing.
*/
int ndx;
const char *aud[3];
/*
* Any global auditing (set using LD_AUDIT or LD_PROFILE) that
* can't be established is non-fatal.
*/
return (0);
return (0);
}
}
}
/*
* Any object required auditing (set with a DT_DEPAUDIT dynamic
* entry) that can't be established is fatal.
*/
/*
* If this object requires global auditing, use the
* local auditing information to set the global
* auditing descriptor. The effect is that a
* DT_DEPAUDIT act as an LD_AUDIT.
*/
if ((auditors == 0) &&
return (0);
return (0);
/*
* Clear the local auditor information.
*/
} else {
/*
* Establish any local auditing.
*/
return (0);
}
}
/*
* Explicitly add the initial object and ld.so.1 to those objects being
* audited. Note, although the ld.so.1 link-map isn't auditable,
* establish a cookie for ld.so.1 as this may be bound to via the
* dl*() family.
*/
return (0);
}
/*
* Map in any preloadable shared objects. Note, it is valid to preload
* a 4.x shared object with a 5.0 executable (or visa-versa), as this
* functionality is required by ldd(1).
*/
return (0);
return (0);
/*
* Load all dependent (needed) objects.
*/
return (0);
/*
* Relocate all the dependencies we've just added.
*
* If this process has been established via crle(1), the environment
* variable LD_CONFGEN will have been set. crle(1) may create this
* process twice. The first time crle only needs to gather dependency
* information. The second time, is to dldump() the images.
*
* If we're only gathering dependencies, relocation is unnecessary.
* As crle(1) may be building an arbitrary family of objects, they may
* not fully relocate either. Hence the relocation phase is not carried
* out now, but will be called by crle(1) once all objects have been
* loaded.
*/
if ((rtld_flags & RT_FL_CONFGEN) == 0) {
return (0);
/*
* Inform the debuggers we're here and stable. Newer debuggers
* can indicate their presence by setting the DT_DEBUG entry in
* the dynamic executable (see elf_new_lm()). In this case call
* getpid() so the debugger can catch the system call. This
* handshake allows the debugger to initialize, and consequently
* allows the user to set break points in .init code.
*/
if (rtld_flags & RT_FL_DEBUGGER) {
(void) getpid();
}
}
/*
* Indicate preinit activity, and call any auditing routines. These
* routines are called before initializing any threads via libc, or
* before collecting the complete set of .inits on the primary link-map.
* Although most libc interfaces are encapsulated in local routines
* within libc, they have been known to escape (ie. call a .plt). As
* the appcert auditor uses preinit as a trigger to establish some
* external interfaces to the main link-maps libc, we need to activate
* this trigger before exercising any code within libc. Additionally,
* I wouldn't put it past an auditor to add additional objects to the
* primary link-map. Hence, we collect .inits after the audit call.
*/
/*
* If we're creating initial configuration information, we're done
* now that the auditing step has been called.
*/
if (rtld_flags & RT_FL_CONFGEN) {
return (mlmp);
}
/*
* Sort the .init sections of all objects we've added. If we're
* tracing we only need to execute this under ldd(1) with the -i or -u
* options.
*/
if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
return (0);
}
/*
* If we are tracing we're done. This is the one legitimate use of a
* direct call to rtldexit() rather than return, as we don't want to
* return and jump to the application.
*/
if (lmflags & LML_FLG_TRC_ENABLE) {
}
/*
* Establish any static TLS for this primary link-map. Note, regardless
* of whether TLS is available, an initial handshake occurs with libc to
* indicate we're processing the primary link-map. Having identified
* the primary link-map, initialize threads.
*/
return (0);
return (0);
/*
* Fire all dependencies .init sections. Identify any unused
* dependencies, and leave the runtime linker - effectively calling
* the dynamic executables entry point.
*/
if (tobj)
return (mlmp);
}