setup.c revision 5aefb6555731130ca4fd295960123d71f2d21fe8
e07d9cb85217949d497b02d7211de8a197d2f2ebzf/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * CDDL HEADER START
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * The contents of this file are subject to the terms of the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Common Development and Distribution License (the "License").
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * You may not use this file except in compliance with the License.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * or http://www.opensolaris.org/os/licensing.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * See the License for the specific language governing permissions
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * and limitations under the License.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * When distributing Covered Code, include this CDDL HEADER in each
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If applicable, add the following below this CDDL HEADER, with the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * fields enclosed by brackets "[]" replaced with your own identifying
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * information: Portions Copyright [yyyy] [name of copyright owner]
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * CDDL HEADER END
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf/*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Copyright (c) 1988 AT&T
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * All Rights Reserved
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Use is subject to license terms.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#pragma ident "%Z%%M% %I% %E% SMI"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang/*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Run time linker common setup.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Called from _setup to get the process going at startup.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "_synonyms.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <stdlib.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <fcntl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <stdio.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <sys/types.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <sys/stat.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <sys/mman.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <string.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <stdio.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <unistd.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <dlfcn.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <sys/sysconfig.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <sys/auxv.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <debug.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include <conv.h>
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "_rtld.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "_audit.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "_elf.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "_a.out.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#include "msg.h"
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzfextern int _end, _edata, _etext;
e07d9cb85217949d497b02d7211de8a197d2f2ebzfextern void _init(void);
e07d9cb85217949d497b02d7211de8a197d2f2ebzfextern int _brk_unlocked(void *);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#ifndef SGS_PRE_UNIFIED_PROCESS
e07d9cb85217949d497b02d7211de8a197d2f2ebzf/* needed for _brk_unlocked() */
e07d9cb85217949d497b02d7211de8a197d2f2ebzfvoid *_nd = &_end;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#endif
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf/*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Define for the executable's interpreter.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Usually it is ld.so.1, but for the first release of ICL binaries
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * it is libc.so.1. We keep this information so that we don't end
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * up mapping libc twice if it is the interpreter.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzfstatic Interp _interp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzfstatic int
e07d9cb85217949d497b02d7211de8a197d2f2ebzfpreload(const char *str, Rt_map *lmp)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf{
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Rt_map *clmp = lmp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf char *objs, *ptr, *next;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Word lmflags = lml_main.lm_flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf uint_t flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((objs = strdup(str)) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Establish the flags for loading each object. If we're called via
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * lddstub, then the first shared object is the object being inspected
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * by ldd(1). This object should not be marked as an interposer, as
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * it is intended to act like the first object of the process.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lmflags & LML_FLG_TRC_ENABLE) && (FLAGS1(lmp) & FL1_RT_LDDSTUB))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf flags = FLG_RT_PRELOAD;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf flags = (FLG_RT_PRELOAD | FLG_RT_INTRPOSE);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ptr = strtok_r(objs, MSG_ORIG(MSG_STR_DELIMIT), &next);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf do {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Pnode *pnp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Rt_map *nlmp = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_file_preload(&lml_main, ptr));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If this a secure application, then preload errors are
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * reduced to warnings, as the errors are non-fatal.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_flags & RT_FL_SECURE)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags2 |= RT_FL2_FTL2WARN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((pnp = expand_paths(clmp, ptr, PN_SER_EXTLOAD, 0)) != 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf nlmp = load_one(&lml_main, ALO_DATA, pnp, clmp,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(lmp), flags, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (pnp)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf remove_pnode(pnp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_flags & RT_FL_SECURE)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags2 &= ~RT_FL2_FTL2WARN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (nlmp && (bind_one(clmp, nlmp, BND_NEEDED) == 0))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf nlmp = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Establish state for the next preloadable object. If no
020c47705d28102a8df83a43ddf08e34dde21f22ql * error occurred with loading this object, indicate that this
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * link-map list contains an interposer.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf flags |= FLG_RT_INTRPOSE;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (nlmp == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lmflags & LML_FLG_TRC_ENABLE) ||
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (rtld_flags & RT_FL_SECURE))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf continue;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_flags |= LML_FLG_INTRPOSE;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If we're tracing shared objects via lddstub, establish a
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * binding between the initial shared object and lddstub so that
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the shared object isn't called out from unused() processing.
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang * After the first object is loaded increment the caller to the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * initial preloaded object to provide intuitive ldd -v and -s
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * diagnostics
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lmflags & LML_FLG_TRC_ENABLE) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (FLAGS1(lmp) & FL1_RT_LDDSTUB)) {
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang if ((lmp == clmp) && (lmflags &
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED))) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (bind_one(clmp, nlmp, BND_REFER) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf continue;
fe3e6e3a98f98e7ab1a751934c0116fb914b9c82Quaker Fang }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf clmp = (Rt_map *)NEXT(lmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } while ((ptr = strtok_r(NULL,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSG_ORIG(MSG_STR_DELIMIT), &next)) != NULL);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf free(objs);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (1);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf}
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzfRt_map *
e07d9cb85217949d497b02d7211de8a197d2f2ebzfsetup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf char *_rtldname, Dyn *dyn_ptr, ulong_t ld_base, ulong_t interp_base, int fd,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Phdr *phdr, char *execname, char **argv, int dz_fd, uid_t uid,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf uid_t euid, gid_t gid, gid_t egid, void *aoutdyn, int auxflags,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf uint_t hwcap_1)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf{
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang Rt_map *rlmp, *mlmp, **tobj = 0;
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang Ehdr *ehdr;
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang struct stat status;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int features = 0, ldsoexec = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer size_t eaddr, esize;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer char *str, *argvname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Mmap *mmaps;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Now that ld.so has relocated itself, initialize our own 'environ' so
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * as to establish an address suitable for libc's hardware mul/div
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * magic (libc/sparc/crt/hwmuldiv.o).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf _environ = (char **)((ulong_t)auxv - sizeof (char *));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf _init();
e07d9cb85217949d497b02d7211de8a197d2f2ebzf _environ = envp;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang * Far the most common application execution revolves around appending
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang * the application name to the users PATH definition, thus a full name
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang * is passed to exec() which will in turn be returned via
5644143a6cf1e70bc2e78d5140970830aae0e8cdQuaker Fang * AT_SUN_EXECNAME. Applications may also be invoked from the current
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * working directory, or via a relative name.
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Determine whether the kernel has supplied a AT_SUN_EXECNAME aux
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * vector. This vector points to the full pathname, on the stack, of
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the object that started the process. If this is null, then
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * AT_SUN_EXECNAME isn't supported (if the pathname exceeded the system
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * limit (PATH_MAX) the exec would have failed). This flag is used to
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * determine whether we can call resolvepath().
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (execname)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags |= RT_FL_EXECNAME;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Determine how ld.so.1 has been executed.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((fd == -1) && (phdr == 0)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If we received neither the AT_EXECFD nor the AT_PHDR aux
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * vector, ld.so.1 must have been invoked directly from the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * command line.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ldsoexec = 1;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * AT_SUN_EXECNAME provides the most precise name, if it is
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * available, otherwise fall back to argv[0]. At this time,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * there is no process name.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (execname)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = execname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else if (argv[0])
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = argv[0];
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Otherwise, we have a standard process. AT_SUN_EXECNAME
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * provides the most precise name, if it is available,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * otherwise fall back to argv[0]. Provided the application
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * is already mapped, the process is the application, so
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * simplify the application name for use in any diagnostics.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (execname)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname = execname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else if (argv[0])
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname = execname = argv[0];
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname = execname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (fd == -1) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((str = strrchr(argvname, '/')) != 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf procname = ++str;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf procname = argvname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang * At this point, we don't know the runtime linkers full path
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * name. The _rtldname passed to us is the SONAME of the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * runtime linker, which is typically /lib/ld.so.1 no matter
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * what the full path is. Use this for now, we'll reset the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * runtime linkers name once the application is analyzed.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (_rtldname) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((str = strrchr(_rtldname, '/')) != 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = ++str;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = _rtldname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang * Initialize any global variables.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf at_flags = _flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (dz_fd != FD_UNAVAIL)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf dz_init(dz_fd);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf platform = _platform;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If pagesize is unspecified find its value.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((syspagsz = _syspagsz) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf syspagsz = _sysconfig(_CONFIG_PAGESIZE);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf fmap_setup();
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Add the unused portion of the last data page to the free space list.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * The page size must be set before doing this. Here, _end refers to
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the end of the runtime linkers bss. Note that we do not use the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * unused data pages from any included .so's to supplement this free
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * space as badly behaved .os's may corrupt this data space, and in so
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * doing ruin our data.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eaddr = S_DROUND((size_t)&_end);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf esize = eaddr % syspagsz;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (esize) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf esize = syspagsz - esize;
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang addfree((void *)eaddr, esize);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Establish initial link-map list flags, and link-map list alists.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (alist_append(&lml_main.lm_lists, 0, sizeof (Lm_cntl),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf AL_CNT_LMLISTS) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_flags |= LML_FLG_BASELM;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_lmid = LM_ID_BASE;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_BASE);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (alist_append(&lml_rtld.lm_lists, 0, sizeof (Lm_cntl),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf AL_CNT_LMLISTS) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_NOAUDIT |
e07d9cb85217949d497b02d7211de8a197d2f2ebzf LML_FLG_HOLDLOCK);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_rtld.lm_lmid = LM_ID_LDSO;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_rtld.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_LDSO);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Determine whether we have a secure executable.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf security(uid, euid, gid, egid, auxflags);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang * Initialize a hardware capability descriptor for use in comparing
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * each loaded object.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#ifdef AT_SUN_AUXFLAGS
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (auxflags & AF_SUN_HWCAPVERIFY) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags2 |= RT_FL2_HWCAP;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf hwcap = (ulong_t)hwcap_1;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#endif
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Look for environment strings (allows things like LD_NOAUDIT to be
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * established, although debugging isn't enabled until later).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((readenv_user((const char **)envp, &(lml_main.lm_flags),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf &(lml_main.lm_tflags), (aoutdyn != 0))) == 1)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Create a mapping descriptor for ld.so.1. We can determine our
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * two segments information from known symbols.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mmaps = calloc(3, sizeof (Mmap))) == 0)
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[0].m_vaddr = (caddr_t)M_PTRUNC(ld_base);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[0].m_msize = (size_t)((caddr_t)&_etext - mmaps[0].m_vaddr);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[0].m_fsize = mmaps[0].m_msize;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[0].m_perm = (PROT_READ | PROT_EXEC);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[1].m_vaddr = (caddr_t)M_PTRUNC((ulong_t)&r_debug);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[1].m_msize = (size_t)((caddr_t)&_end - mmaps[1].m_vaddr);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[1].m_fsize = (size_t)((caddr_t)&_edata - mmaps[1].m_vaddr);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[1].m_perm = (PROT_READ | PROT_WRITE | PROT_EXEC);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Create a link map structure for ld.so.1.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((rlmp = elf_new_lm(&lml_rtld, _rtldname, rtldname, dyn_ptr, ld_base,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)&_etext, ALO_DATA, (ulong_t)(eaddr - ld_base), 0, ld_base,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)(eaddr - ld_base), mmaps, 2)) == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(rlmp) |= (RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS(rlmp) |= (FLG_RT_ANALYZED | FLG_RT_RELOCED | FLG_RT_INITDONE |
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLG_RT_INITCLCT | FLG_RT_FINICLCT | FLG_RT_MODESET);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Initialize the runtime linkers information.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf interp = &_interp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf interp->i_name = NAME(rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf interp->i_faddr = (caddr_t)ADDR(rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ldso_plt_init(rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If ld.so.1 has been invoked directly, process its arguments.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ldsoexec) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Process any arguments that are specific to ld.so.1, and
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * reorganize the process stack to effectively remove ld.so.1
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * from it. Reinitialize the environment pointer, as this may
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * have been shifted after skipping ld.so.1's arguments.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_getopt(argv, &envp, &auxv, &(lml_main.lm_flags),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf &(lml_main.lm_tflags), (aoutdyn != 0)) == 1) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_NONE, MSG_INTL(MSG_USG_BADOPT));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf _environ = envp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Open the object that ld.so.1 is to execute.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname = execname = argv[0];
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((fd = open(argvname, O_RDONLY)) == -1) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int err = errno;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname, strerror(err));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Map in the file, if exec has not already done so. If it has,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * simply create a new link map structure for the executable.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (fd != -1) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Rej_desc rej;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Fct *ftp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Find out what type of object we have.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) fstat(fd, &status);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((ftp = are_u_this(&rej, fd, &status, argvname)) == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_FATAL,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSG_INTL(err_reject[rej.rej_type]), argvname,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf conv_reject_desc(&rej));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Map in object.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mlmp = (ftp->fct_map_so)(&lml_main, ALO_DATA, execname,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argvname, fd)) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * We now have a process name for error diagnostics.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((str = strrchr(argvname, '/')) != 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf procname = ++str;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf procname = argvname;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ldsoexec) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Addr brkbase = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Since ld.so.1 was the primary executed object - the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * brk() base has not yet been initialized, we need to
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * initialize it. For an executable, initialize it to
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the end of the object. For a shared object (ET_DYN)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * initialize it to the first page in memory.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ehdr = (Ehdr *)ADDR(mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((FCT(mlmp) == &elf_fct) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ehdr->e_type == ET_EXEC)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int i;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Phdr * _phdr = (Phdr *)((uintptr_t)ADDR(mlmp) +
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ehdr->e_phoff);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * We scan the program headers to find the tail
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * of the memory image. We can't use MSIZE()
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * since that's already been page aligned.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf for (i = 0; i < ehdr->e_phnum; i++, _phdr++) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (_phdr->p_type == PT_LOAD)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf brkbase = _phdr->p_vaddr +
e07d9cb85217949d497b02d7211de8a197d2f2ebzf _phdr->p_memsz;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (!brkbase)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf brkbase = syspagsz;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (_brk_unlocked((void *)brkbase) == -1) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int err = errno;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_FATAL,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSG_INTL(MSG_SYS_BRK), argvname,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf strerror(err));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * The object has now been mmaped, we no longer need the file
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * descriptor.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) close(fd);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Set up function ptr and arguments according to the type
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * of file class the executable is. (Currently only supported
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * types are ELF and a.out format.) Then create a link map
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * for the executable.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (aoutdyn) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#ifdef A_OUT
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mlmp = aout_new_lm(&lml_main, execname, argvname,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf aoutdyn, 0, 0, ALO_DATA)) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Set the memory size. Note, we only know the end of
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * text, and although we could find the _end by looking
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * up the symbol, this may not be present. We should
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * set ADDR to MAIN_BASE, but presently all the a.out
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * relocation code assumes ADDR is 0 for the dynamic
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * executable. (these data items are only used for
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * dladdr(3x), and there aren't many a.out dladdr(3x)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * users to warrant spending much time on this :-).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSIZE(mlmp) = MAIN_BASE + ETEXT(mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Disable any object configuration cache (BCP apps
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * bring in sbcp which can benefit from any object
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * cache, but both the app and sbcp can't use the same
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang * objects).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags |= RT_FL_NOOBJALT;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Make sure no-direct bindings are in effect.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_tflags |= LML_TFLG_NODIRECT;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_FATAL,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSG_INTL(MSG_ERR_REJ_UNKFILE), argvname);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf#endif
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else if (phdr) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Phdr *pptr, *firstptr = 0, *lastptr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Phdr *tlsphdr = 0, *unwindphdr = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Dyn *dyn = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Cap *cap = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Off i_offset = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Addr base = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ulong_t memsize, phsize, entry, etext;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf uint_t mmapcnt = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int i;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Using the executables phdr address determine the base
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * address of the input file. NOTE, this assumes the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * program headers and elf header are part of the same
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * mapped segment. Although this has held for many
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * years now, it might be more flexible if the kernel
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * gave use the ELF headers start address, rather than
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the Program headers.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
1a932f2eab9b00d713acc4205d96ca2485bf2712Quaker Fang * Determine from the ELF header if we're been called
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * from a shared object or dynamic executable. If the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * latter, then any addresses within the object are used
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * as is. Addresses within shared objects must be added
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * to the process's base address.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ehdr = (Ehdr *)((Addr)phdr - phdr->p_offset);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf phsize = ehdr->e_phentsize;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ehdr->e_type == ET_DYN)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf base = (Addr)ehdr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Allocate a mapping array to retain mapped segment
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * information.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mmaps = calloc(ehdr->e_phnum, sizeof (Mmap))) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Extract the needed information from the segment
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * headers.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf for (i = 0, pptr = phdr; i < ehdr->e_phnum; i++) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (pptr->p_type == PT_INTERP) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf i_offset = pptr->p_offset;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf interp->i_faddr =
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (caddr_t)interp_base;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((pptr->p_type == PT_LOAD) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (pptr->p_filesz || pptr->p_memsz)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int perm = (PROT_READ | PROT_EXEC);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf size_t off;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (!firstptr)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf firstptr = pptr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lastptr = pptr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (i_offset && pptr->p_filesz &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (i_offset >= pptr->p_offset) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (i_offset <=
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (pptr->p_memsz + pptr->p_offset))) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf interp->i_name = (char *)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr->p_vaddr + i_offset -
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr->p_offset + base;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf i_offset = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((pptr->p_flags &
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (PF_R | PF_W)) == PF_R)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf etext = pptr->p_vaddr +
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr->p_memsz + base;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf perm |= PROT_WRITE;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Retain segments mapping info. Round
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * each segment to a page boundary, as
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * this insures addresses are suitable
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * for mprotect() if required.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf off = pptr->p_vaddr + base;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[mmapcnt].m_vaddr =
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (caddr_t)M_PTRUNC(off);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf off -= (size_t)mmaps[mmapcnt].m_vaddr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[mmapcnt].m_msize =
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr->p_memsz + off;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[mmapcnt].m_fsize =
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr->p_filesz + off;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmaps[mmapcnt].m_perm = perm;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf mmapcnt++;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else if (pptr->p_type == PT_DYNAMIC)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf dyn = (Dyn *)(pptr->p_vaddr + base);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else if (pptr->p_type == PT_TLS)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf tlsphdr = pptr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else if (pptr->p_type == PT_SUNW_UNWIND)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf unwindphdr = pptr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else if (pptr->p_type == PT_SUNWCAP)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf cap = (Cap *)(pptr->p_vaddr + base);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf pptr = (Phdr *)((ulong_t)pptr + phsize);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf memsize = (lastptr->p_vaddr + lastptr->p_memsz) -
e07d9cb85217949d497b02d7211de8a197d2f2ebzf S_ALIGN(firstptr->p_vaddr, syspagsz);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf entry = ehdr->e_entry;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ehdr->e_type == ET_DYN)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf entry += (ulong_t)ehdr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mlmp = elf_new_lm(&lml_main, execname, argvname,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf dyn, (Addr)ehdr, etext, ALO_DATA, memsize, entry,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)ehdr, memsize, mmaps, mmapcnt)) == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (tlsphdr) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf PTTLS(mlmp) = tlsphdr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf tls_assign_soffset(mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (unwindphdr)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf PTUNWIND(mlmp) = unwindphdr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (cap)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf cap_assign(cap, mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Establish the interpretors name as that defined within the initial
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * object (executable). This provides for ORIGIN processing of ld.so.1
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * dependencies.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ldsoexec == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf size_t len = strlen(interp->i_name);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) expand(&interp->i_name, &len, 0, 0,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (PN_TKN_ISALIST | PN_TKN_HWCAP), rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf PATHNAME(rlmp) = interp->i_name;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (FLAGS1(rlmp) & FL1_RT_RELATIVE)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) fullpath(rlmp, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ORIGNAME(rlmp) = PATHNAME(rlmp) = NAME(rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Having established the true runtime linkers name, simplify the name
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * for error diagnostics.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((str = strrchr(PATHNAME(rlmp), '/')) != 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = ++str;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldname = PATHNAME(rlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Expand the fullpath name of the application. This typically occurs
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * as a part of loading an object, but as the kernel probably mapped
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * it in, complete this processing now.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (FLAGS1(mlmp) & FL1_RT_RELATIVE)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) fullpath(mlmp, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Some troublesome programs will change the value of argv[0]. Dupping
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the process string protects us, and insures the string is left in
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * any core files.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((str = (char *)strdup(procname)) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf procname = str;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If the kernel has provided hardware capabilities information, and
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the executable contains hardware capabilities information, make
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * sure it's a valid object.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((rtld_flags2 & RT_FL2_HWCAP) && HWCAP(mlmp)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ulong_t mhwcap;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((mhwcap = (HWCAP(mlmp) & ~hwcap)) != 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf const char *str = conv_cap_val_hw1(mhwcap, M_MACH);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf NAME(mlmp), str);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf eprintf(&lml_main, ERR_FATAL,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MSG_INTL(MSG_GEN_BADHWCAP_1), str);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS(mlmp) |= (FLG_RT_ISMAIN | FLG_RT_MODESET);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS1(mlmp) |= FL1_RT_USED;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * It's the responsibility of MAIN(crt0) to call it's _init and _fini
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * section, therefore null out any INIT/FINI so that this object isn't
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * collected during tsort processing. And, if the application has no
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * initarray or finiarray we can economize on establishing bindings.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf INIT(mlmp) = FINI(mlmp) = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((INITARRAY(mlmp) == 0) && (FINIARRAY(mlmp) == 0))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS1(mlmp) |= FL1_RT_NOINIFIN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Identify lddstub if necessary.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS1(mlmp) |= FL1_RT_LDDSTUB;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Retain our argument information for use in dlinfo.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argsinfo.dla_argv = argv--;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argsinfo.dla_argc = (long)*argv;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argsinfo.dla_envp = envp;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf argsinfo.dla_auxv = auxv;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) enter();
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Add our two main link-maps to the dynlm_list
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (list_append(&dynlm_list, &lml_main) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (list_append(&dynlm_list, &lml_rtld) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Reset the link-map counts for both lists. The init count is used to
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * track how many objects have pending init sections, this gets incre-
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * mented each time an object is relocated. Since ld.so.1 relocates
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * itself, it's init count will remain zero.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * The object count is used to track how many objects have pending fini
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * sections, as ld.so.1 handles its own fini we can zero its count.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_obj = 1;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_rtld.lm_obj = 0;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Initialize debugger information structure. Some parts of this
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * structure were initialized statically.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf r_debug.rtd_rdebug.r_map = (Link_map *)lml_main.lm_head;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf r_debug.rtd_rdebug.r_ldsomap = (Link_map *)lml_rtld.lm_head;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf r_debug.rtd_rdebug.r_ldbase = r_debug.rtd_rdebug.r_ldsomap->l_addr;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf r_debug.rtd_dynlmlst = &dynlm_list;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (platform)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf platform_sz = strlen(platform);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Determine the dev/inode information for the executable to complete
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * load_so() checking for those who might dlopen(a.out).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((FLAGS1(mlmp) & FL1_RT_RELATIVE) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (stat(PATHNAME(mlmp), &status) == 0)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf STDEV(mlmp) = status.st_dev;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf STINO(mlmp) = status.st_ino;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Initialize any configuration information.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (!(rtld_flags & RT_FL_NOCFG)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((features = elf_config(mlmp, (aoutdyn != 0))) == -1)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Establish the modes of the initial object. These modes are
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * propagated to any preloaded objects and explicit shared library
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * dependencies. Note, RTLD_NOW may have been established during
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * analysis of the application had it been built -z now.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(mlmp) |= (RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_flags & RT_FL_CONFGEN)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(mlmp) |= RTLD_CONFGEN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((MODE(mlmp) & RTLD_NOW) == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_flags2 & RT_FL2_BINDNOW)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(mlmp) |= RTLD_NOW;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf else
e07d9cb85217949d497b02d7211de8a197d2f2ebzf MODE(mlmp) |= RTLD_LAZY;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If debugging was requested initialize things now that any cache has
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * been established. A user can specify LD_DEBUG=help to discover the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * list of debugging tokens available without running the application.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * However, don't allow this setting from a configuration file.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Note, to prevent recursion issues caused by loading and binding the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * debugging libraries themselves, a local debugging descriptor is
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * initialized. Once the debugging setup has completed, this local
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * descriptor is copied to the global descriptor which effectively
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * enables diagnostic output.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rpl_debug || prm_debug) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Dbg_desc _dbg_desc = {0, 0, 0};
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rpl_debug) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf uintptr_t ret;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((ret = dbg_setup(rpl_debug, &_dbg_desc)) == S_ERROR)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (ret == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldexit(&lml_main, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (prm_debug)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) dbg_setup(prm_debug, &_dbg_desc);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *dbg_desc = _dbg_desc;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Now that debugging is enabled generate any diagnostics from any
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * previous events.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (hwcap)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_cap_val_hw1(&lml_main, hwcap, M_MACH));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (features)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_file_config_dis(&lml_main, config->c_name,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf features));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (DBG_ENABLED) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf LIST(rlmp)->lm_lmidstr, ALO_DATA));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (FCT(mlmp) == &elf_fct) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_file_elf(&lml_main, PATHNAME(mlmp),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)DYN(mlmp), ADDR(mlmp), MSIZE(mlmp),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ENTRY(mlmp), LIST(mlmp)->lm_lmidstr, ALO_DATA));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf } else {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_file_aout(&lml_main, PATHNAME(mlmp),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)AOUTDYN(mlmp), (ulong_t)ADDR(mlmp),
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (ulong_t)MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf ALO_DATA));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Enable auditing.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rpl_audit || prm_audit || profile_lib) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf int ndx;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf const char *aud[3];
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf aud[0] = rpl_audit;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf aud[1] = prm_audit;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf aud[2] = profile_lib;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Any global auditing (set using LD_AUDIT or LD_PROFILE) that
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * can't be established is non-fatal.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((auditors = calloc(1, sizeof (Audit_desc))) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf for (ndx = 0; ndx < 3; ndx++) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (aud[ndx]) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((auditors->ad_name = strdup(aud[ndx])) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags2 |= RT_FL2_FTL2WARN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) audit_setup(mlmp, auditors,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf PN_SER_EXTLOAD);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags2 &= ~RT_FL2_FTL2WARN;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_tflags |= auditors->ad_flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (AUDITORS(mlmp)) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Any object required auditing (set with a DT_DEPAUDIT dynamic
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * entry) that can't be established is fatal.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (audit_setup(mlmp, AUDITORS(mlmp), 0) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf FLAGS1(mlmp) |= AUDITORS(mlmp)->ad_flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lml_main.lm_flags |= LML_FLG_LOCAUDIT;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Explicitly add the initial object and ld.so.1 to those objects being
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * audited. Note, although the ld.so.1 link-map isn't auditable,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * establish a cookie for ld.so.1 as this may be bound to via the
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * dl*() family.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_MASK) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (((audit_objopen(mlmp, mlmp) == 0) ||
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (audit_objopen(mlmp, rlmp) == 0)) &&
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (FLAGS1(mlmp) & LML_TFLG_AUD_MASK))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Map in any preloadable shared objects. Note, it is valid to preload
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * a 4.x shared object with a 5.0 executable (or visa-versa), as this
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * functionality is required by ldd(1).
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rpl_preload && (preload(rpl_preload, mlmp) == 0))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (prm_preload && (preload(prm_preload, mlmp) == 0))
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Load all dependent (needed) objects.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (analyze_lmc(&lml_main, ALO_DATA, mlmp) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Relocate all the dependencies we've just added.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If this process has been established via crle(1), the environment
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * variable LD_CONFGEN will have been set. crle(1) may create this
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * process twice. The first time crle only needs to gather dependency
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * information. The second time, is to dldump() the images.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf *
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If we're only gathering dependencies, relocation is unnecessary.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * As crle(1) may be building an arbitrary family of objects, they may
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * not fully relocate either. Hence the relocation phase is not carried
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * out now, but will be called by crle(1) once all objects have been
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * loaded.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((rtld_flags & RT_FL_CONFGEN) == 0) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf Word lmflags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (relocate_lmc(&lml_main, ALO_DATA, mlmp) == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Sort the .init sections of all objects we've added. If
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * we're tracing we only need to execute this under ldd(1)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * with the -i or -u options.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf lmflags = lml_main.lm_flags;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf RT_SORT_REV)) == (Rt_map **)S_ERROR)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * If we are tracing we're done. This is the one legitimate use
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * of a direct call to rtldexit() rather than return, as we
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * don't want to return and jump to the application.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (lmflags & LML_FLG_TRC_ENABLE) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf unused(&lml_main);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtldexit(&lml_main, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Inform the debuggers we're here and stable. Newer debuggers
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * can indicate their presence by setting the DT_DEBUG entry in
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * the dynamic executable (see elf_new_lm()). In this case call
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * getpid() so the debugger can catch the system call. This
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * handshake allows the debugger to initialize, and consequently
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * allows the user to set break points in .init code.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rd_event(&lml_rtld, RD_DLACTIVITY, RT_CONSISTENT);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rd_event(&lml_main, RD_DLACTIVITY, RT_CONSISTENT);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (rtld_flags & RT_FL_DEBUGGER) {
e07d9cb85217949d497b02d7211de8a197d2f2ebzf r_debug.rtd_rdebug.r_flags |= RD_FL_ODBG;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf (void) getpid();
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Initialize any initial TLS storage.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (tls_report_modules() == 0)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf }
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf /*
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * Call any necessary auditing routines, clean up any file descriptors
e07d9cb85217949d497b02d7211de8a197d2f2ebzf * and such, and then fire all dependencies .init sections.
e07d9cb85217949d497b02d7211de8a197d2f2ebzf */
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rtld_flags |= RT_FL_APPLIC;
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rd_event(&lml_main, RD_PREINIT, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_ACTIVITY)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf audit_activity(mlmp, LA_ACT_CONSISTENT);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_PREINIT)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf audit_preinit(mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf call_array(PREINITARRAY(mlmp), (uint_t)PREINITARRAYSZ(mlmp), mlmp,
e07d9cb85217949d497b02d7211de8a197d2f2ebzf SHT_PREINIT_ARRAY);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf if (tobj)
e07d9cb85217949d497b02d7211de8a197d2f2ebzf call_init(tobj, DBG_INIT_SORT);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf rd_event(&lml_main, RD_POSTINIT, 0);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf unused(&lml_main);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf DBG_CALL(Dbg_util_call_main(mlmp));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf leave(LIST(mlmp));
e07d9cb85217949d497b02d7211de8a197d2f2ebzf
e07d9cb85217949d497b02d7211de8a197d2f2ebzf return (mlmp);
e07d9cb85217949d497b02d7211de8a197d2f2ebzf}
e07d9cb85217949d497b02d7211de8a197d2f2ebzf