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