1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate /* LINTLIBRARY */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <sys/mman.h> 31*0Sstevel@tonic-gate #include <sys/types.h> 32*0Sstevel@tonic-gate #include <sys/stat.h> 33*0Sstevel@tonic-gate #include <procfs.h> 34*0Sstevel@tonic-gate #include <unistd.h> 35*0Sstevel@tonic-gate #include <fcntl.h> 36*0Sstevel@tonic-gate #include <stdio.h> 37*0Sstevel@tonic-gate #include <string.h> 38*0Sstevel@tonic-gate #include <limits.h> 39*0Sstevel@tonic-gate #include <errno.h> 40*0Sstevel@tonic-gate #include <alloca.h> 41*0Sstevel@tonic-gate #include "rtld.h" 42*0Sstevel@tonic-gate #include "rtc.h" 43*0Sstevel@tonic-gate #include "_crle.h" 44*0Sstevel@tonic-gate #include "msg.h" 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* 47*0Sstevel@tonic-gate * Routines for dumping alternate objects under CRLE_AUD_DLDUMP mode. 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate static Addr membgn = 0; 50*0Sstevel@tonic-gate static Addr memend = 0; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate /* 53*0Sstevel@tonic-gate * For each file in the configuration file that requires an alternate (dldump()) 54*0Sstevel@tonic-gate * version, add the object to the processes main link-map. The process head 55*0Sstevel@tonic-gate * may be an application, shared object, or lddstub. In any case this object 56*0Sstevel@tonic-gate * may be augmented with other objects defined within the configuration file. 57*0Sstevel@tonic-gate * 58*0Sstevel@tonic-gate * Each file is initially loaded with RTLD_CONFGEN so that no dependency 59*0Sstevel@tonic-gate * analysis, relocation, or user code (.init's) is executed. By skipping 60*0Sstevel@tonic-gate * analysis we save time and allow for a family of objects to be dumped that 61*0Sstevel@tonic-gate * may not have all relocations satisfied. If necessary, a later call to 62*0Sstevel@tonic-gate * dlopen() using RTLD_NOW will force relocations to occur. 63*0Sstevel@tonic-gate * 64*0Sstevel@tonic-gate * A mapping range is maintained to span the mapping of each objects, and this 65*0Sstevel@tonic-gate * range is finally written back to the caller. 66*0Sstevel@tonic-gate */ 67*0Sstevel@tonic-gate static int 68*0Sstevel@tonic-gate /* ARGSUSED1 */ 69*0Sstevel@tonic-gate load(const char *opath, const char *npath) 70*0Sstevel@tonic-gate { 71*0Sstevel@tonic-gate Grp_hdl * ghp; 72*0Sstevel@tonic-gate Rt_map * lmp; 73*0Sstevel@tonic-gate Addr _membgn, _memend; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate if ((ghp = (Grp_hdl *)dlmopen(LM_ID_BASE, opath, 76*0Sstevel@tonic-gate (RTLD_LAZY | RTLD_GLOBAL | RTLD_CONFGEN))) == NULL) { 77*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_OPEN), 78*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 79*0Sstevel@tonic-gate return (1); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate lmp = ghp->gh_owner; 82*0Sstevel@tonic-gate FLAGS1(lmp) |= FL1_RT_CONFSET; 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate /* 85*0Sstevel@tonic-gate * Establish the mapping range of the objects dumped so far. 86*0Sstevel@tonic-gate */ 87*0Sstevel@tonic-gate _membgn = ADDR(lmp); 88*0Sstevel@tonic-gate _memend = (ADDR(lmp) + MSIZE(lmp)); 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate if (membgn == 0) { 91*0Sstevel@tonic-gate membgn = _membgn; 92*0Sstevel@tonic-gate memend = _memend; 93*0Sstevel@tonic-gate } else { 94*0Sstevel@tonic-gate if (membgn > _membgn) 95*0Sstevel@tonic-gate membgn = _membgn; 96*0Sstevel@tonic-gate if (memend < _memend) 97*0Sstevel@tonic-gate memend = _memend; 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate return (0); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /* 103*0Sstevel@tonic-gate * dldump(3x) an object that is already part of the main link-map list. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate static int 106*0Sstevel@tonic-gate dump(const char *opath, const char *npath) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate (void) unlink(npath); 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate if (dldump(opath, npath, dlflag) != 0) { 111*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_DUMP), 112*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 113*0Sstevel@tonic-gate return (1); 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate return (0); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * Traverse a configuration file directory/file list. Each file within the 120*0Sstevel@tonic-gate * list is maintained as both a full pathname and a simple filename - we're 121*0Sstevel@tonic-gate * only interested in one. 122*0Sstevel@tonic-gate * 123*0Sstevel@tonic-gate * This rutine is called twice, once to insure the appropriate objects are 124*0Sstevel@tonic-gate * mapped in (fptr == load()) and then once again to dldump(3x) the mapped 125*0Sstevel@tonic-gate * objects (fptr == dump()). 126*0Sstevel@tonic-gate */ 127*0Sstevel@tonic-gate static int 128*0Sstevel@tonic-gate scanconfig(Addr addr, int (*fptr)()) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate Rtc_head * head = (Rtc_head *)addr; 131*0Sstevel@tonic-gate Rtc_obj * obj; 132*0Sstevel@tonic-gate Rtc_dir * dirtbl; 133*0Sstevel@tonic-gate Rtc_file * filetbl; 134*0Sstevel@tonic-gate const char *str, *strtbl; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* LINTED */ 137*0Sstevel@tonic-gate strtbl = (const char *)((char *)addr + head->ch_str); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate /* 140*0Sstevel@tonic-gate * Scan the directory and filename arrays looking for alternatives. 141*0Sstevel@tonic-gate */ 142*0Sstevel@tonic-gate for (dirtbl = (Rtc_dir *)(head->ch_dir + addr); 143*0Sstevel@tonic-gate dirtbl->cd_obj; dirtbl++) { 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate obj = (Rtc_obj *)(dirtbl->cd_obj + addr); 146*0Sstevel@tonic-gate str = strtbl + obj->co_name; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (obj->co_flags & RTC_OBJ_NOEXIST) 149*0Sstevel@tonic-gate continue; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate for (filetbl = (Rtc_file *)(dirtbl->cd_file + addr); 152*0Sstevel@tonic-gate filetbl->cf_obj; filetbl++) { 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate obj = (Rtc_obj *)(filetbl->cf_obj + addr); 155*0Sstevel@tonic-gate str = strtbl + obj->co_name; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate if ((obj->co_flags & 158*0Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH | RTC_OBJ_EXEC)) == 159*0Sstevel@tonic-gate (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) { 160*0Sstevel@tonic-gate if ((*fptr)(str, strtbl + obj->co_alter) != 0) 161*0Sstevel@tonic-gate return (1); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * Are we dumping a specific application. 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate if (head->ch_app) { 170*0Sstevel@tonic-gate if (fptr == load) { 171*0Sstevel@tonic-gate Grp_hdl * ghp; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * Obtain a handle to the application and set the 175*0Sstevel@tonic-gate * FL1_RT_CONFSET flag. 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate if ((ghp = dlmopen(LM_ID_BASE, 0, 178*0Sstevel@tonic-gate (RTLD_NOLOAD | RTLD_CONFGEN))) == 0) 179*0Sstevel@tonic-gate return (1); 180*0Sstevel@tonic-gate FLAGS1(ghp->gh_owner) |= FL1_RT_CONFSET; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate } else { 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * If we're dumping and this configuration is for a 185*0Sstevel@tonic-gate * specific application dump it also. 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate /* LINTED */ 188*0Sstevel@tonic-gate obj = (Rtc_obj *)((char *)addr + head->ch_app); 189*0Sstevel@tonic-gate str = strtbl + obj->co_alter; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate if (dump((const char *)0, str) != 0) 192*0Sstevel@tonic-gate return (1); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate return (0); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate /* 200*0Sstevel@tonic-gate * Before loading any dependencies determine the present memory mappings being 201*0Sstevel@tonic-gate * used and fill any holes between these mappings. This insures that all 202*0Sstevel@tonic-gate * dldump()'ed dependencies will live in a single consecutive address range. 203*0Sstevel@tonic-gate */ 204*0Sstevel@tonic-gate int 205*0Sstevel@tonic-gate filladdr(void) 206*0Sstevel@tonic-gate { 207*0Sstevel@tonic-gate prmap_t *maps, *_maps; 208*0Sstevel@tonic-gate struct stat status; 209*0Sstevel@tonic-gate int fd = 0, err, num, _num; 210*0Sstevel@tonic-gate size_t size, syspagsz; 211*0Sstevel@tonic-gate uintptr_t laddr = 0, saddr; 212*0Sstevel@tonic-gate pstatus_t prstatus; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * Open /proc/self/status to determine the virtual address of the 216*0Sstevel@tonic-gate * process heap. 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCSTATUS), O_RDONLY)) == -1) { 219*0Sstevel@tonic-gate err = errno; 220*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 221*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS), 222*0Sstevel@tonic-gate strerror(err)); 223*0Sstevel@tonic-gate return (1); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate if (read(fd, &prstatus, sizeof (pstatus_t)) != sizeof (pstatus_t)) { 226*0Sstevel@tonic-gate err = errno; 227*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), 228*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCSTATUS), 229*0Sstevel@tonic-gate strerror(err)); 230*0Sstevel@tonic-gate (void) close(fd); 231*0Sstevel@tonic-gate return (1); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate (void) close(fd); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * Round the process heap to the next page boundary so that it can be 237*0Sstevel@tonic-gate * used to isolated the a.out mappings (pr_brkbase typically occurs 238*0Sstevel@tonic-gate * at the end, but within, the a.out's data segment). As libcrle is 239*0Sstevel@tonic-gate * used as an audit library, no process user code has run so there 240*0Sstevel@tonic-gate * can't be any heap. pr_brksize is added here for completeness. 241*0Sstevel@tonic-gate */ 242*0Sstevel@tonic-gate syspagsz = sysconf(_SC_PAGESIZE); 243*0Sstevel@tonic-gate saddr = M_PROUND(prstatus.pr_brkbase + prstatus.pr_brksize); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * Open /proc/self/rmap to obtain the processes reserved mappings. 247*0Sstevel@tonic-gate */ 248*0Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_PROCRMAP), O_RDONLY)) == -1) { 249*0Sstevel@tonic-gate err = errno; 250*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 251*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP), 252*0Sstevel@tonic-gate strerror(err)); 253*0Sstevel@tonic-gate return (1); 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate (void) fstat(fd, &status); 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate /* 258*0Sstevel@tonic-gate * Determine number of mappings - use alloca so as not to perturb any 259*0Sstevel@tonic-gate * mapping information by a malloc, which itself might add a mapping. 260*0Sstevel@tonic-gate */ 261*0Sstevel@tonic-gate /* LINTED */ 262*0Sstevel@tonic-gate num = (int)(status.st_size / sizeof (prmap_t)); 263*0Sstevel@tonic-gate size = num * sizeof (prmap_t); 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate if ((maps = alloca(size)) == 0) { 266*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ALLOC), 267*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), strerror(ENOMEM)); 268*0Sstevel@tonic-gate (void) close(pfd); 269*0Sstevel@tonic-gate return (1); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (read(fd, (void *)maps, size) < 0) { 273*0Sstevel@tonic-gate err = errno; 274*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), 275*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_PROCRMAP), 276*0Sstevel@tonic-gate strerror(err)); 277*0Sstevel@tonic-gate (void) close(fd); 278*0Sstevel@tonic-gate return (1); 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate (void) close(fd); 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate /* 283*0Sstevel@tonic-gate * Use /dev/null for filling holes. 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate if ((fd = open(MSG_ORIG(MSG_PTH_DEVNULL), O_RDONLY)) == -1) { 286*0Sstevel@tonic-gate err = errno; 287*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 288*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), MSG_ORIG(MSG_PTH_DEVNULL), 289*0Sstevel@tonic-gate strerror(err)); 290*0Sstevel@tonic-gate return (1); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate /* 294*0Sstevel@tonic-gate * Scan each mapping - note it is assummed that the mappings are 295*0Sstevel@tonic-gate * presented in order. We fill holes between mappings. On intel 296*0Sstevel@tonic-gate * the last mapping is usually the data segment of ld.so.1, after 297*0Sstevel@tonic-gate * this comes a red zone into which non-fixed mapping won't get 298*0Sstevel@tonic-gate * place. Thus we can simply bail from the loop after seeing the 299*0Sstevel@tonic-gate * last mapping. 300*0Sstevel@tonic-gate */ 301*0Sstevel@tonic-gate for (_num = 0, _maps = maps; _num < num; _num++, _maps++) { 302*0Sstevel@tonic-gate /* 303*0Sstevel@tonic-gate * Skip all mappings below brkbase, these represent the a.out 304*0Sstevel@tonic-gate * (and the stack on intel). 305*0Sstevel@tonic-gate */ 306*0Sstevel@tonic-gate if ((laddr == 0) && 307*0Sstevel@tonic-gate ((_maps->pr_vaddr + _maps->pr_size) <= saddr)) 308*0Sstevel@tonic-gate continue; 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate /* 311*0Sstevel@tonic-gate * For each consecutive mapping determine the hole between each 312*0Sstevel@tonic-gate * and fill it from /dev/null. 313*0Sstevel@tonic-gate */ 314*0Sstevel@tonic-gate if (laddr == 0) { 315*0Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size; 316*0Sstevel@tonic-gate continue; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if ((size = _maps->pr_vaddr - laddr) != 0) { 320*0Sstevel@tonic-gate if (mmap((void *)laddr, size, PROT_NONE, 321*0Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) { 322*0Sstevel@tonic-gate err = errno; 323*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), 324*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), 325*0Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err)); 326*0Sstevel@tonic-gate return (1); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate laddr = _maps->pr_vaddr + _maps->pr_size; 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* 333*0Sstevel@tonic-gate * It's been observed that there may be space between the end of the 334*0Sstevel@tonic-gate * last mapping (typically ld.so.1), and the kernel base address. As 335*0Sstevel@tonic-gate * there's no interface to determine the kernel base address, keep 336*0Sstevel@tonic-gate * filling in pages until we get an error. We'll get ENOMEM once we 337*0Sstevel@tonic-gate * hit the kernel base address. 338*0Sstevel@tonic-gate */ 339*0Sstevel@tonic-gate while (laddr) { 340*0Sstevel@tonic-gate if (mmap((void *)laddr, syspagsz, PROT_NONE, 341*0Sstevel@tonic-gate (MAP_FIXED | MAP_PRIVATE), fd, 0) == MAP_FAILED) { 342*0Sstevel@tonic-gate err = errno; 343*0Sstevel@tonic-gate if (err == ENOMEM) 344*0Sstevel@tonic-gate break; 345*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), 346*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), 347*0Sstevel@tonic-gate MSG_ORIG(MSG_PTH_DEVNULL), strerror(err)); 348*0Sstevel@tonic-gate return (1); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate laddr += syspagsz; 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate /* 354*0Sstevel@tonic-gate * Close /dev/null. 355*0Sstevel@tonic-gate */ 356*0Sstevel@tonic-gate (void) close(fd); 357*0Sstevel@tonic-gate return (0); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* 361*0Sstevel@tonic-gate * Dump alternative objects as part of building a configuration file. A temp 362*0Sstevel@tonic-gate * configuration is already built and made available to the process, and is 363*0Sstevel@tonic-gate * located via dlinfo(). Having load()'ed each object, and dump()'ed its image, 364*0Sstevel@tonic-gate * the final memory reservation infoamtion is returned to the caller. 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate int 367*0Sstevel@tonic-gate dumpconfig(void) 368*0Sstevel@tonic-gate { 369*0Sstevel@tonic-gate char buffer[PATH_MAX]; 370*0Sstevel@tonic-gate Addr config; 371*0Sstevel@tonic-gate Dl_info info; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * Determine the configuration file and where it is mapped. 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate if (dlinfo((void *)NULL, RTLD_DI_CONFIGADDR, &info) == -1) { 377*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_DL_INFO), 378*0Sstevel@tonic-gate MSG_ORIG(MSG_FIL_LIBCRLE), dlerror()); 379*0Sstevel@tonic-gate return (1); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate config = (Addr)info.dli_fbase; 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate /* 384*0Sstevel@tonic-gate * Scan the configuration file for alternative entries. 385*0Sstevel@tonic-gate */ 386*0Sstevel@tonic-gate if (scanconfig(config, load) != 0) 387*0Sstevel@tonic-gate return (1); 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate /* 390*0Sstevel@tonic-gate * Having mapped all objects, relocate them. It would be nice if we 391*0Sstevel@tonic-gate * could drop this step altogether, and have dldump() carry out just 392*0Sstevel@tonic-gate * those relocations required, but when binding to an application we 393*0Sstevel@tonic-gate * need to handle copy relocations - these can affect bindings (in the 394*0Sstevel@tonic-gate * case of things like libld.so which have direct bindings) and require 395*0Sstevel@tonic-gate * that the data being copied is itself relocated. 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate if (dlmopen(LM_ID_BASE, 0, (RTLD_NOW | RTLD_CONFGEN)) == 0) 398*0Sstevel@tonic-gate return (1); 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* 401*0Sstevel@tonic-gate * Rescan the configuration dumping out each alternative file. 402*0Sstevel@tonic-gate */ 403*0Sstevel@tonic-gate if (scanconfig(config, dump) != 0) 404*0Sstevel@tonic-gate return (1); 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* 407*0Sstevel@tonic-gate * Having established the memory range of the dumped images and 408*0Sstevel@tonic-gate * sucessfully dumped them out, report back to the caller. 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESBGN), EC_ADDR(membgn)); 411*0Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer)); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate (void) sprintf(buffer, MSG_ORIG(MSG_AUD_RESEND), EC_ADDR(memend)); 414*0Sstevel@tonic-gate (void) write(pfd, buffer, strlen(buffer)); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate return (0); 417*0Sstevel@tonic-gate } 418