10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1618Srie * Common Development and Distribution License (the "License"). 6*1618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*1618Srie 220Sstevel@tonic-gate /* 23*1618Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* LINTLIBRARY */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <sys/mman.h> 310Sstevel@tonic-gate #include <sys/types.h> 320Sstevel@tonic-gate #include <sys/stat.h> 330Sstevel@tonic-gate #include <procfs.h> 340Sstevel@tonic-gate #include <unistd.h> 350Sstevel@tonic-gate #include <fcntl.h> 360Sstevel@tonic-gate #include <stdio.h> 370Sstevel@tonic-gate #include <string.h> 380Sstevel@tonic-gate #include <limits.h> 390Sstevel@tonic-gate #include <errno.h> 400Sstevel@tonic-gate #include <alloca.h> 410Sstevel@tonic-gate #include "rtld.h" 420Sstevel@tonic-gate #include "rtc.h" 430Sstevel@tonic-gate #include "_crle.h" 440Sstevel@tonic-gate #include "msg.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * Routines for dumping alternate objects under CRLE_AUD_DLDUMP mode. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate static Addr membgn = 0; 500Sstevel@tonic-gate static Addr memend = 0; 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * For each file in the configuration file that requires an alternate (dldump()) 540Sstevel@tonic-gate * version, add the object to the processes main link-map. The process head 550Sstevel@tonic-gate * may be an application, shared object, or lddstub. In any case this object 560Sstevel@tonic-gate * may be augmented with other objects defined within the configuration file. 570Sstevel@tonic-gate * 580Sstevel@tonic-gate * Each file is initially loaded with RTLD_CONFGEN so that no dependency 590Sstevel@tonic-gate * analysis, relocation, or user code (.init's) is executed. By skipping 600Sstevel@tonic-gate * analysis we save time and allow for a family of objects to be dumped that 610Sstevel@tonic-gate * may not have all relocations satisfied. If necessary, a later call to 620Sstevel@tonic-gate * dlopen() using RTLD_NOW will force relocations to occur. 630Sstevel@tonic-gate * 640Sstevel@tonic-gate * A mapping range is maintained to span the mapping of each objects, and this 650Sstevel@tonic-gate * range is finally written back to the caller. 660Sstevel@tonic-gate */ 670Sstevel@tonic-gate static int 680Sstevel@tonic-gate /* ARGSUSED1 */ 690Sstevel@tonic-gate load(const char *opath, const char *npath) 700Sstevel@tonic-gate { 710Sstevel@tonic-gate Grp_hdl * ghp; 720Sstevel@tonic-gate Rt_map * lmp; 730Sstevel@tonic-gate Addr _membgn, _memend; 740Sstevel@tonic-gate 750Sstevel@tonic-gate if ((ghp = (Grp_hdl *)dlmopen(LM_ID_BASE, opath, 760Sstevel@tonic-gate (RTLD_LAZY | RTLD_GLOBAL | RTLD_CONFGEN))) == NULL) { 770Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_OPEN), 780Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 790Sstevel@tonic-gate return (1); 800Sstevel@tonic-gate } 81*1618Srie lmp = ghp->gh_ownlmp; 820Sstevel@tonic-gate FLAGS1(lmp) |= FL1_RT_CONFSET; 830Sstevel@tonic-gate 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * Establish the mapping range of the objects dumped so far. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate _membgn = ADDR(lmp); 880Sstevel@tonic-gate _memend = (ADDR(lmp) + MSIZE(lmp)); 890Sstevel@tonic-gate 900Sstevel@tonic-gate if (membgn == 0) { 910Sstevel@tonic-gate membgn = _membgn; 920Sstevel@tonic-gate memend = _memend; 930Sstevel@tonic-gate } else { 940Sstevel@tonic-gate if (membgn > _membgn) 950Sstevel@tonic-gate membgn = _membgn; 960Sstevel@tonic-gate if (memend < _memend) 970Sstevel@tonic-gate memend = _memend; 980Sstevel@tonic-gate } 990Sstevel@tonic-gate return (0); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * dldump(3x) an object that is already part of the main link-map list. 1040Sstevel@tonic-gate */ 1050Sstevel@tonic-gate static int 1060Sstevel@tonic-gate dump(const char *opath, const char *npath) 1070Sstevel@tonic-gate { 1080Sstevel@tonic-gate (void) unlink(npath); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate if (dldump(opath, npath, dlflag) != 0) { 1110Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_DUMP), 1120Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 1130Sstevel@tonic-gate return (1); 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate return (0); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 1190Sstevel@tonic-gate * Traverse a configuration file directory/file list. Each file within the 1200Sstevel@tonic-gate * list is maintained as both a full pathname and a simple filename - we're 1210Sstevel@tonic-gate * only interested in one. 1220Sstevel@tonic-gate * 1230Sstevel@tonic-gate * This rutine is called twice, once to insure the appropriate objects are 1240Sstevel@tonic-gate * mapped in (fptr == load()) and then once again to dldump(3x) the mapped 1250Sstevel@tonic-gate * objects (fptr == dump()). 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate static int 1280Sstevel@tonic-gate scanconfig(Addr addr, int (*fptr)()) 1290Sstevel@tonic-gate { 1300Sstevel@tonic-gate Rtc_head * head = (Rtc_head *)addr; 1310Sstevel@tonic-gate Rtc_obj * obj; 1320Sstevel@tonic-gate Rtc_dir * dirtbl; 1330Sstevel@tonic-gate Rtc_file * filetbl; 1340Sstevel@tonic-gate const char *str, *strtbl; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /* LINTED */ 1370Sstevel@tonic-gate strtbl = (const char *)((char *)addr + head->ch_str); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * Scan the directory and filename arrays looking for alternatives. 1410Sstevel@tonic-gate */ 1420Sstevel@tonic-gate for (dirtbl = (Rtc_dir *)(head->ch_dir + addr); 1430Sstevel@tonic-gate dirtbl->cd_obj; dirtbl++) { 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate obj = (Rtc_obj *)(dirtbl->cd_obj + addr); 1460Sstevel@tonic-gate str = strtbl + obj->co_name; 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate if (obj->co_flags & RTC_OBJ_NOEXIST) 1490Sstevel@tonic-gate continue; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate for (filetbl = (Rtc_file *)(dirtbl->cd_file + addr); 1520Sstevel@tonic-gate filetbl->cf_obj; filetbl++) { 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate obj = (Rtc_obj *)(filetbl->cf_obj + addr); 1550Sstevel@tonic-gate str = strtbl + obj->co_name; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if ((obj->co_flags & 1580Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH | RTC_OBJ_EXEC)) == 1590Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) { 1600Sstevel@tonic-gate if ((*fptr)(str, strtbl + obj->co_alter) != 0) 1610Sstevel@tonic-gate return (1); 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * Are we dumping a specific application. 1680Sstevel@tonic-gate */ 1690Sstevel@tonic-gate if (head->ch_app) { 1700Sstevel@tonic-gate if (fptr == load) { 1710Sstevel@tonic-gate Grp_hdl * ghp; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Obtain a handle to the application and set the 1750Sstevel@tonic-gate * FL1_RT_CONFSET flag. 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate if ((ghp = dlmopen(LM_ID_BASE, 0, 1780Sstevel@tonic-gate (RTLD_NOLOAD | RTLD_CONFGEN))) == 0) 1790Sstevel@tonic-gate return (1); 180*1618Srie FLAGS1(ghp->gh_ownlmp) |= FL1_RT_CONFSET; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate } else { 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * If we're dumping and this configuration is for a 1850Sstevel@tonic-gate * specific application dump it also. 1860Sstevel@tonic-gate */ 1870Sstevel@tonic-gate /* LINTED */ 1880Sstevel@tonic-gate obj = (Rtc_obj *)((char *)addr + head->ch_app); 1890Sstevel@tonic-gate str = strtbl + obj->co_alter; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate if (dump((const char *)0, str) != 0) 1920Sstevel@tonic-gate return (1); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate return (0); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate /* 2000Sstevel@tonic-gate * Before loading any dependencies determine the present memory mappings being 2010Sstevel@tonic-gate * used and fill any holes between these mappings. This insures that all 2020Sstevel@tonic-gate * dldump()'ed dependencies will live in a single consecutive address range. 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate int 2050Sstevel@tonic-gate filladdr(void) 2060Sstevel@tonic-gate { 2070Sstevel@tonic-gate prmap_t *maps, *_maps; 2080Sstevel@tonic-gate struct stat status; 2090Sstevel@tonic-gate int fd = 0, err, num, _num; 2100Sstevel@tonic-gate size_t size, syspagsz; 2110Sstevel@tonic-gate uintptr_t laddr = 0, saddr; 2120Sstevel@tonic-gate pstatus_t prstatus; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * Open /proc/self/status to determine the virtual address of the 2160Sstevel@tonic-gate * process heap. 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCSTATUS), O_RDONLY)) == -1) { 2190Sstevel@tonic-gate err = errno; 2200Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 2210Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS), 2220Sstevel@tonic-gate strerror(err)); 2230Sstevel@tonic-gate return (1); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate if (read(fd, &prstatus, sizeof (pstatus_t)) != sizeof (pstatus_t)) { 2260Sstevel@tonic-gate err = errno; 2270Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), 2280Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS), 2290Sstevel@tonic-gate strerror(err)); 2300Sstevel@tonic-gate (void) close(fd); 2310Sstevel@tonic-gate return (1); 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate (void) close(fd); 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * Round the process heap to the next page boundary so that it can be 2370Sstevel@tonic-gate * used to isolated the a.out mappings (pr_brkbase typically occurs 2380Sstevel@tonic-gate * at the end, but within, the a.out's data segment). As libcrle is 2390Sstevel@tonic-gate * used as an audit library, no process user code has run so there 2400Sstevel@tonic-gate * can't be any heap. pr_brksize is added here for completeness. 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate syspagsz = sysconf(_SC_PAGESIZE); 2430Sstevel@tonic-gate saddr = M_PROUND(prstatus.pr_brkbase + prstatus.pr_brksize); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate /* 2460Sstevel@tonic-gate * Open /proc/self/rmap to obtain the processes reserved mappings. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCRMAP), O_RDONLY)) == -1) { 2490Sstevel@tonic-gate err = errno; 2500Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 2510Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP), 2520Sstevel@tonic-gate strerror(err)); 2530Sstevel@tonic-gate return (1); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate (void) fstat(fd, &status); 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate /* 2580Sstevel@tonic-gate * Determine number of mappings - use alloca so as not to perturb any 2590Sstevel@tonic-gate * mapping information by a malloc, which itself might add a mapping. 2600Sstevel@tonic-gate */ 2610Sstevel@tonic-gate /* LINTED */ 2620Sstevel@tonic-gate num = (int)(status.st_size / sizeof (prmap_t)); 2630Sstevel@tonic-gate size = num * sizeof (prmap_t); 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate if ((maps = alloca(size)) == 0) { 2660Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ALLOC), 2670Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), strerror(ENOMEM)); 2680Sstevel@tonic-gate (void) close(pfd); 2690Sstevel@tonic-gate return (1); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate if (read(fd, (void *)maps, size) < 0) { 2730Sstevel@tonic-gate err = errno; 2740Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), 2750Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP), 2760Sstevel@tonic-gate strerror(err)); 2770Sstevel@tonic-gate (void) close(fd); 2780Sstevel@tonic-gate return (1); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate (void) close(fd); 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate /* 2830Sstevel@tonic-gate * Use /dev/null for filling holes. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_DEVNULL), O_RDONLY)) == -1) { 2860Sstevel@tonic-gate err = errno; 2870Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 2880Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_DEVNULL), 2890Sstevel@tonic-gate strerror(err)); 2900Sstevel@tonic-gate return (1); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Scan each mapping - note it is assummed that the mappings are 2950Sstevel@tonic-gate * presented in order. We fill holes between mappings. On intel 2960Sstevel@tonic-gate * the last mapping is usually the data segment of ld.so.1, after 2970Sstevel@tonic-gate * this comes a red zone into which non-fixed mapping won't get 2980Sstevel@tonic-gate * place. Thus we can simply bail from the loop after seeing the 2990Sstevel@tonic-gate * last mapping. 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate for (_num = 0, _maps = maps; _num < num; _num++, _maps++) { 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Skip all mappings below brkbase, these represent the a.out 3040Sstevel@tonic-gate * (and the stack on intel). 3050Sstevel@tonic-gate */ 3060Sstevel@tonic-gate if ((laddr == 0) && 3070Sstevel@tonic-gate ((_maps->pr_vaddr + _maps->pr_size) <= saddr)) 3080Sstevel@tonic-gate continue; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* 3110Sstevel@tonic-gate * For each consecutive mapping determine the hole between each 3120Sstevel@tonic-gate * and fill it from /dev/null. 3130Sstevel@tonic-gate */ 3140Sstevel@tonic-gate if (laddr == 0) { 3150Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size; 3160Sstevel@tonic-gate continue; 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate if ((size = _maps->pr_vaddr - laddr) != 0) { 3200Sstevel@tonic-gate if (mmap((void *)laddr, size, PROT_NONE, 3210Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) { 3220Sstevel@tonic-gate err = errno; 3230Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), 3240Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), 3250Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err)); 3260Sstevel@tonic-gate return (1); 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size; 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /* 3330Sstevel@tonic-gate * It's been observed that there may be space between the end of the 3340Sstevel@tonic-gate * last mapping (typically ld.so.1), and the kernel base address. As 3350Sstevel@tonic-gate * there's no interface to determine the kernel base address, keep 3360Sstevel@tonic-gate * filling in pages until we get an error. We'll get ENOMEM once we 3370Sstevel@tonic-gate * hit the kernel base address. 3380Sstevel@tonic-gate */ 3390Sstevel@tonic-gate while (laddr) { 3400Sstevel@tonic-gate if (mmap((void *)laddr, syspagsz, PROT_NONE, 3410Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) { 3420Sstevel@tonic-gate err = errno; 3430Sstevel@tonic-gate if (err == ENOMEM) 3440Sstevel@tonic-gate break; 3450Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), 3460Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), 3470Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err)); 3480Sstevel@tonic-gate return (1); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate laddr += syspagsz; 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Close /dev/null. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate (void) close(fd); 3570Sstevel@tonic-gate return (0); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate /* 3610Sstevel@tonic-gate * Dump alternative objects as part of building a configuration file. A temp 3620Sstevel@tonic-gate * configuration is already built and made available to the process, and is 3630Sstevel@tonic-gate * located via dlinfo(). Having load()'ed each object, and dump()'ed its image, 3640Sstevel@tonic-gate * the final memory reservation infoamtion is returned to the caller. 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate int 3670Sstevel@tonic-gate dumpconfig(void) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate char buffer[PATH_MAX]; 3700Sstevel@tonic-gate Addr config; 3710Sstevel@tonic-gate Dl_info info; 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate /* 3740Sstevel@tonic-gate * Determine the configuration file and where it is mapped. 3750Sstevel@tonic-gate */ 3760Sstevel@tonic-gate if (dlinfo((void *)NULL, RTLD_DI_CONFIGADDR, &info) == -1) { 3770Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_INFO), 3780Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 3790Sstevel@tonic-gate return (1); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate config = (Addr)info.dli_fbase; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * Scan the configuration file for alternative entries. 3850Sstevel@tonic-gate */ 3860Sstevel@tonic-gate if (scanconfig(config, load) != 0) 3870Sstevel@tonic-gate return (1); 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * Having mapped all objects, relocate them. It would be nice if we 3910Sstevel@tonic-gate * could drop this step altogether, and have dldump() carry out just 3920Sstevel@tonic-gate * those relocations required, but when binding to an application we 3930Sstevel@tonic-gate * need to handle copy relocations - these can affect bindings (in the 3940Sstevel@tonic-gate * case of things like libld.so which have direct bindings) and require 3950Sstevel@tonic-gate * that the data being copied is itself relocated. 3960Sstevel@tonic-gate */ 3970Sstevel@tonic-gate if (dlmopen(LM_ID_BASE, 0, (RTLD_NOW | RTLD_CONFGEN)) == 0) 3980Sstevel@tonic-gate return (1); 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * Rescan the configuration dumping out each alternative file. 4020Sstevel@tonic-gate */ 4030Sstevel@tonic-gate if (scanconfig(config, dump) != 0) 4040Sstevel@tonic-gate return (1); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /* 4070Sstevel@tonic-gate * Having established the memory range of the dumped images and 4080Sstevel@tonic-gate * sucessfully dumped them out, report back to the caller. 4090Sstevel@tonic-gate */ 4100Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESBGN), EC_ADDR(membgn)); 4110Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer)); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESEND), EC_ADDR(memend)); 4140Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer)); 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate return (0); 4170Sstevel@tonic-gate } 418