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 */ 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 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 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 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 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