17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*5aefb655Srie * Common Development and Distribution License (the "License").
6*5aefb655Srie * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21*5aefb655Srie
227c478bd9Sstevel@tonic-gate /*
23*5aefb655Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #include <sys/mman.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/stat.h>
337c478bd9Sstevel@tonic-gate #include <procfs.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <limits.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <alloca.h>
417c478bd9Sstevel@tonic-gate #include "rtld.h"
427c478bd9Sstevel@tonic-gate #include "rtc.h"
437c478bd9Sstevel@tonic-gate #include "_crle.h"
447c478bd9Sstevel@tonic-gate #include "msg.h"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate * Routines for dumping alternate objects under CRLE_AUD_DLDUMP mode.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate static Addr membgn = 0;
507c478bd9Sstevel@tonic-gate static Addr memend = 0;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * For each file in the configuration file that requires an alternate (dldump())
547c478bd9Sstevel@tonic-gate * version, add the object to the processes main link-map. The process head
557c478bd9Sstevel@tonic-gate * may be an application, shared object, or lddstub. In any case this object
567c478bd9Sstevel@tonic-gate * may be augmented with other objects defined within the configuration file.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate * Each file is initially loaded with RTLD_CONFGEN so that no dependency
597c478bd9Sstevel@tonic-gate * analysis, relocation, or user code (.init's) is executed. By skipping
607c478bd9Sstevel@tonic-gate * analysis we save time and allow for a family of objects to be dumped that
617c478bd9Sstevel@tonic-gate * may not have all relocations satisfied. If necessary, a later call to
627c478bd9Sstevel@tonic-gate * dlopen() using RTLD_NOW will force relocations to occur.
637c478bd9Sstevel@tonic-gate *
647c478bd9Sstevel@tonic-gate * A mapping range is maintained to span the mapping of each objects, and this
657c478bd9Sstevel@tonic-gate * range is finally written back to the caller.
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate static int
687c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
load(const char * opath,const char * npath)697c478bd9Sstevel@tonic-gate load(const char *opath, const char *npath)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate Grp_hdl * ghp;
727c478bd9Sstevel@tonic-gate Rt_map * lmp;
737c478bd9Sstevel@tonic-gate Addr _membgn, _memend;
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate if ((ghp = (Grp_hdl *)dlmopen(LM_ID_BASE, opath,
767c478bd9Sstevel@tonic-gate (RTLD_LAZY | RTLD_GLOBAL | RTLD_CONFGEN))) == NULL) {
777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_OPEN),
787c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror());
797c478bd9Sstevel@tonic-gate return (1);
807c478bd9Sstevel@tonic-gate }
81*5aefb655Srie lmp = ghp->gh_ownlmp;
827c478bd9Sstevel@tonic-gate FLAGS1(lmp) |= FL1_RT_CONFSET;
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate * Establish the mapping range of the objects dumped so far.
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate _membgn = ADDR(lmp);
887c478bd9Sstevel@tonic-gate _memend = (ADDR(lmp) + MSIZE(lmp));
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate if (membgn == 0) {
917c478bd9Sstevel@tonic-gate membgn = _membgn;
927c478bd9Sstevel@tonic-gate memend = _memend;
937c478bd9Sstevel@tonic-gate } else {
947c478bd9Sstevel@tonic-gate if (membgn > _membgn)
957c478bd9Sstevel@tonic-gate membgn = _membgn;
967c478bd9Sstevel@tonic-gate if (memend < _memend)
977c478bd9Sstevel@tonic-gate memend = _memend;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate return (0);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * dldump(3x) an object that is already part of the main link-map list.
1047c478bd9Sstevel@tonic-gate */
1057c478bd9Sstevel@tonic-gate static int
dump(const char * opath,const char * npath)1067c478bd9Sstevel@tonic-gate dump(const char *opath, const char *npath)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate (void) unlink(npath);
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate if (dldump(opath, npath, dlflag) != 0) {
1117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_DUMP),
1127c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror());
1137c478bd9Sstevel@tonic-gate return (1);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate return (0);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate * Traverse a configuration file directory/file list. Each file within the
1207c478bd9Sstevel@tonic-gate * list is maintained as both a full pathname and a simple filename - we're
1217c478bd9Sstevel@tonic-gate * only interested in one.
1227c478bd9Sstevel@tonic-gate *
1237c478bd9Sstevel@tonic-gate * This rutine is called twice, once to insure the appropriate objects are
1247c478bd9Sstevel@tonic-gate * mapped in (fptr == load()) and then once again to dldump(3x) the mapped
1257c478bd9Sstevel@tonic-gate * objects (fptr == dump()).
1267c478bd9Sstevel@tonic-gate */
1277c478bd9Sstevel@tonic-gate static int
scanconfig(Addr addr,int (* fptr)())1287c478bd9Sstevel@tonic-gate scanconfig(Addr addr, int (*fptr)())
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate Rtc_head * head = (Rtc_head *)addr;
1317c478bd9Sstevel@tonic-gate Rtc_obj * obj;
1327c478bd9Sstevel@tonic-gate Rtc_dir * dirtbl;
1337c478bd9Sstevel@tonic-gate Rtc_file * filetbl;
1347c478bd9Sstevel@tonic-gate const char *str, *strtbl;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /* LINTED */
1377c478bd9Sstevel@tonic-gate strtbl = (const char *)((char *)addr + head->ch_str);
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate * Scan the directory and filename arrays looking for alternatives.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate for (dirtbl = (Rtc_dir *)(head->ch_dir + addr);
1437c478bd9Sstevel@tonic-gate dirtbl->cd_obj; dirtbl++) {
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate obj = (Rtc_obj *)(dirtbl->cd_obj + addr);
1467c478bd9Sstevel@tonic-gate str = strtbl + obj->co_name;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate if (obj->co_flags & RTC_OBJ_NOEXIST)
1497c478bd9Sstevel@tonic-gate continue;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate for (filetbl = (Rtc_file *)(dirtbl->cd_file + addr);
1527c478bd9Sstevel@tonic-gate filetbl->cf_obj; filetbl++) {
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate obj = (Rtc_obj *)(filetbl->cf_obj + addr);
1557c478bd9Sstevel@tonic-gate str = strtbl + obj->co_name;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate if ((obj->co_flags &
1587c478bd9Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH | RTC_OBJ_EXEC)) ==
1597c478bd9Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) {
1607c478bd9Sstevel@tonic-gate if ((*fptr)(str, strtbl + obj->co_alter) != 0)
1617c478bd9Sstevel@tonic-gate return (1);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate * Are we dumping a specific application.
1687c478bd9Sstevel@tonic-gate */
1697c478bd9Sstevel@tonic-gate if (head->ch_app) {
1707c478bd9Sstevel@tonic-gate if (fptr == load) {
1717c478bd9Sstevel@tonic-gate Grp_hdl * ghp;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * Obtain a handle to the application and set the
1757c478bd9Sstevel@tonic-gate * FL1_RT_CONFSET flag.
1767c478bd9Sstevel@tonic-gate */
1777c478bd9Sstevel@tonic-gate if ((ghp = dlmopen(LM_ID_BASE, 0,
1787c478bd9Sstevel@tonic-gate (RTLD_NOLOAD | RTLD_CONFGEN))) == 0)
1797c478bd9Sstevel@tonic-gate return (1);
180*5aefb655Srie FLAGS1(ghp->gh_ownlmp) |= FL1_RT_CONFSET;
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate } else {
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * If we're dumping and this configuration is for a
1857c478bd9Sstevel@tonic-gate * specific application dump it also.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate /* LINTED */
1887c478bd9Sstevel@tonic-gate obj = (Rtc_obj *)((char *)addr + head->ch_app);
1897c478bd9Sstevel@tonic-gate str = strtbl + obj->co_alter;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate if (dump((const char *)0, str) != 0)
1927c478bd9Sstevel@tonic-gate return (1);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate return (0);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * Before loading any dependencies determine the present memory mappings being
2017c478bd9Sstevel@tonic-gate * used and fill any holes between these mappings. This insures that all
2027c478bd9Sstevel@tonic-gate * dldump()'ed dependencies will live in a single consecutive address range.
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate int
filladdr(void)2057c478bd9Sstevel@tonic-gate filladdr(void)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate prmap_t *maps, *_maps;
2087c478bd9Sstevel@tonic-gate struct stat status;
2097c478bd9Sstevel@tonic-gate int fd = 0, err, num, _num;
2107c478bd9Sstevel@tonic-gate size_t size, syspagsz;
2117c478bd9Sstevel@tonic-gate uintptr_t laddr = 0, saddr;
2127c478bd9Sstevel@tonic-gate pstatus_t prstatus;
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * Open /proc/self/status to determine the virtual address of the
2167c478bd9Sstevel@tonic-gate * process heap.
2177c478bd9Sstevel@tonic-gate */
2187c478bd9Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCSTATUS), O_RDONLY)) == -1) {
2197c478bd9Sstevel@tonic-gate err = errno;
2207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
2217c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS),
2227c478bd9Sstevel@tonic-gate strerror(err));
2237c478bd9Sstevel@tonic-gate return (1);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate if (read(fd, &prstatus, sizeof (pstatus_t)) != sizeof (pstatus_t)) {
2267c478bd9Sstevel@tonic-gate err = errno;
2277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ),
2287c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS),
2297c478bd9Sstevel@tonic-gate strerror(err));
2307c478bd9Sstevel@tonic-gate (void) close(fd);
2317c478bd9Sstevel@tonic-gate return (1);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate (void) close(fd);
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * Round the process heap to the next page boundary so that it can be
2377c478bd9Sstevel@tonic-gate * used to isolated the a.out mappings (pr_brkbase typically occurs
2387c478bd9Sstevel@tonic-gate * at the end, but within, the a.out's data segment). As libcrle is
2397c478bd9Sstevel@tonic-gate * used as an audit library, no process user code has run so there
2407c478bd9Sstevel@tonic-gate * can't be any heap. pr_brksize is added here for completeness.
2417c478bd9Sstevel@tonic-gate */
2427c478bd9Sstevel@tonic-gate syspagsz = sysconf(_SC_PAGESIZE);
2437c478bd9Sstevel@tonic-gate saddr = M_PROUND(prstatus.pr_brkbase + prstatus.pr_brksize);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * Open /proc/self/rmap to obtain the processes reserved mappings.
2477c478bd9Sstevel@tonic-gate */
2487c478bd9Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCRMAP), O_RDONLY)) == -1) {
2497c478bd9Sstevel@tonic-gate err = errno;
2507c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
2517c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP),
2527c478bd9Sstevel@tonic-gate strerror(err));
2537c478bd9Sstevel@tonic-gate return (1);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate (void) fstat(fd, &status);
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * Determine number of mappings - use alloca so as not to perturb any
2597c478bd9Sstevel@tonic-gate * mapping information by a malloc, which itself might add a mapping.
2607c478bd9Sstevel@tonic-gate */
2617c478bd9Sstevel@tonic-gate /* LINTED */
2627c478bd9Sstevel@tonic-gate num = (int)(status.st_size / sizeof (prmap_t));
2637c478bd9Sstevel@tonic-gate size = num * sizeof (prmap_t);
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate if ((maps = alloca(size)) == 0) {
2667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ALLOC),
2677c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), strerror(ENOMEM));
2687c478bd9Sstevel@tonic-gate (void) close(pfd);
2697c478bd9Sstevel@tonic-gate return (1);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate if (read(fd, (void *)maps, size) < 0) {
2737c478bd9Sstevel@tonic-gate err = errno;
2747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ),
2757c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP),
2767c478bd9Sstevel@tonic-gate strerror(err));
2777c478bd9Sstevel@tonic-gate (void) close(fd);
2787c478bd9Sstevel@tonic-gate return (1);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate (void) close(fd);
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate /*
2837c478bd9Sstevel@tonic-gate * Use /dev/null for filling holes.
2847c478bd9Sstevel@tonic-gate */
2857c478bd9Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_DEVNULL), O_RDONLY)) == -1) {
2867c478bd9Sstevel@tonic-gate err = errno;
2877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
2887c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_DEVNULL),
2897c478bd9Sstevel@tonic-gate strerror(err));
2907c478bd9Sstevel@tonic-gate return (1);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate * Scan each mapping - note it is assummed that the mappings are
2957c478bd9Sstevel@tonic-gate * presented in order. We fill holes between mappings. On intel
2967c478bd9Sstevel@tonic-gate * the last mapping is usually the data segment of ld.so.1, after
2977c478bd9Sstevel@tonic-gate * this comes a red zone into which non-fixed mapping won't get
2987c478bd9Sstevel@tonic-gate * place. Thus we can simply bail from the loop after seeing the
2997c478bd9Sstevel@tonic-gate * last mapping.
3007c478bd9Sstevel@tonic-gate */
3017c478bd9Sstevel@tonic-gate for (_num = 0, _maps = maps; _num < num; _num++, _maps++) {
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate * Skip all mappings below brkbase, these represent the a.out
3047c478bd9Sstevel@tonic-gate * (and the stack on intel).
3057c478bd9Sstevel@tonic-gate */
3067c478bd9Sstevel@tonic-gate if ((laddr == 0) &&
3077c478bd9Sstevel@tonic-gate ((_maps->pr_vaddr + _maps->pr_size) <= saddr))
3087c478bd9Sstevel@tonic-gate continue;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /*
3117c478bd9Sstevel@tonic-gate * For each consecutive mapping determine the hole between each
3127c478bd9Sstevel@tonic-gate * and fill it from /dev/null.
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate if (laddr == 0) {
3157c478bd9Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size;
3167c478bd9Sstevel@tonic-gate continue;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate if ((size = _maps->pr_vaddr - laddr) != 0) {
3207c478bd9Sstevel@tonic-gate if (mmap((void *)laddr, size, PROT_NONE,
3217c478bd9Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) {
3227c478bd9Sstevel@tonic-gate err = errno;
3237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP),
3247c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE),
3257c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3267c478bd9Sstevel@tonic-gate return (1);
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size;
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate * It's been observed that there may be space between the end of the
3347c478bd9Sstevel@tonic-gate * last mapping (typically ld.so.1), and the kernel base address. As
3357c478bd9Sstevel@tonic-gate * there's no interface to determine the kernel base address, keep
3367c478bd9Sstevel@tonic-gate * filling in pages until we get an error. We'll get ENOMEM once we
3377c478bd9Sstevel@tonic-gate * hit the kernel base address.
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate while (laddr) {
3407c478bd9Sstevel@tonic-gate if (mmap((void *)laddr, syspagsz, PROT_NONE,
3417c478bd9Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) {
3427c478bd9Sstevel@tonic-gate err = errno;
3437c478bd9Sstevel@tonic-gate if (err == ENOMEM)
3447c478bd9Sstevel@tonic-gate break;
3457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP),
3467c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE),
3477c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3487c478bd9Sstevel@tonic-gate return (1);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate laddr += syspagsz;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate * Close /dev/null.
3557c478bd9Sstevel@tonic-gate */
3567c478bd9Sstevel@tonic-gate (void) close(fd);
3577c478bd9Sstevel@tonic-gate return (0);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate * Dump alternative objects as part of building a configuration file. A temp
3627c478bd9Sstevel@tonic-gate * configuration is already built and made available to the process, and is
3637c478bd9Sstevel@tonic-gate * located via dlinfo(). Having load()'ed each object, and dump()'ed its image,
3647c478bd9Sstevel@tonic-gate * the final memory reservation infoamtion is returned to the caller.
3657c478bd9Sstevel@tonic-gate */
3667c478bd9Sstevel@tonic-gate int
dumpconfig(void)3677c478bd9Sstevel@tonic-gate dumpconfig(void)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate char buffer[PATH_MAX];
3707c478bd9Sstevel@tonic-gate Addr config;
3717c478bd9Sstevel@tonic-gate Dl_info info;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate * Determine the configuration file and where it is mapped.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate if (dlinfo((void *)NULL, RTLD_DI_CONFIGADDR, &info) == -1) {
3777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_INFO),
3787c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror());
3797c478bd9Sstevel@tonic-gate return (1);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate config = (Addr)info.dli_fbase;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * Scan the configuration file for alternative entries.
3857c478bd9Sstevel@tonic-gate */
3867c478bd9Sstevel@tonic-gate if (scanconfig(config, load) != 0)
3877c478bd9Sstevel@tonic-gate return (1);
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Having mapped all objects, relocate them. It would be nice if we
3917c478bd9Sstevel@tonic-gate * could drop this step altogether, and have dldump() carry out just
3927c478bd9Sstevel@tonic-gate * those relocations required, but when binding to an application we
3937c478bd9Sstevel@tonic-gate * need to handle copy relocations - these can affect bindings (in the
3947c478bd9Sstevel@tonic-gate * case of things like libld.so which have direct bindings) and require
3957c478bd9Sstevel@tonic-gate * that the data being copied is itself relocated.
3967c478bd9Sstevel@tonic-gate */
3977c478bd9Sstevel@tonic-gate if (dlmopen(LM_ID_BASE, 0, (RTLD_NOW | RTLD_CONFGEN)) == 0)
3987c478bd9Sstevel@tonic-gate return (1);
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate * Rescan the configuration dumping out each alternative file.
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate if (scanconfig(config, dump) != 0)
4047c478bd9Sstevel@tonic-gate return (1);
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * Having established the memory range of the dumped images and
4087c478bd9Sstevel@tonic-gate * sucessfully dumped them out, report back to the caller.
4097c478bd9Sstevel@tonic-gate */
4107c478bd9Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESBGN), EC_ADDR(membgn));
4117c478bd9Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer));
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESEND), EC_ADDR(memend));
4147c478bd9Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer));
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate return (0);
4177c478bd9Sstevel@tonic-gate }
418