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*8fd04b83SRoger A. Faulkner * Common Development and Distribution License (the "License"). 6*8fd04b83SRoger A. Faulkner * 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*8fd04b83SRoger A. Faulkner 22*8fd04b83SRoger A. Faulkner /* 23*8fd04b83SRoger A. Faulkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24*8fd04b83SRoger A. Faulkner * Use is subject to license terms. 25*8fd04b83SRoger A. Faulkner */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Redirection ld.so. Based on the 4.x binary compatibility ld.so, used 297c478bd9Sstevel@tonic-gate * to redirect aliases for ld.so to the real one. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * Import data structures 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/mman.h> 377c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 397c478bd9Sstevel@tonic-gate #include <sys/sysconfig.h> 407c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 417c478bd9Sstevel@tonic-gate #include <elf.h> 427c478bd9Sstevel@tonic-gate #include <link.h> 437c478bd9Sstevel@tonic-gate #include <string.h> 447c478bd9Sstevel@tonic-gate #include "alias_boot.h" 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* 477c478bd9Sstevel@tonic-gate * Local manifest constants and macros. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate #define ALIGN(x, a) ((int)(x) & ~((int)(a) - 1)) 507c478bd9Sstevel@tonic-gate #define ROUND(x, a) (((int)(x) + ((int)(a) - 1)) & \ 517c478bd9Sstevel@tonic-gate ~((int)(a) - 1)) 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #define EMPTY strings[EMPTY_S] 547c478bd9Sstevel@tonic-gate #define LDSO strings[LDSO_S] 557c478bd9Sstevel@tonic-gate #define ZERO strings[ZERO_S] 567c478bd9Sstevel@tonic-gate #define CLOSE (*(funcs[CLOSE_F])) 57*8fd04b83SRoger A. Faulkner #define FSTATAT (*(funcs[FSTATAT_F])) 587c478bd9Sstevel@tonic-gate #define MMAP (*(funcs[MMAP_F])) 597c478bd9Sstevel@tonic-gate #define MUNMAP (*(funcs[MUNMAP_F])) 60*8fd04b83SRoger A. Faulkner #define OPENAT (*(funcs[OPENAT_F])) 617c478bd9Sstevel@tonic-gate #define PANIC (*(funcs[PANIC_F])) 627c478bd9Sstevel@tonic-gate #define SYSCONFIG (*(funcs[SYSCONFIG_F])) 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #include <link.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * Alias ld.so entry point -- receives a bootstrap structure and a vector 687c478bd9Sstevel@tonic-gate * of strings. The vector is "well-known" to us, and consists of pointers 697c478bd9Sstevel@tonic-gate * to string constants. This aliasing bootstrap requires no relocation in 707c478bd9Sstevel@tonic-gate * order to run, save for the pointers of constant strings. This second 717c478bd9Sstevel@tonic-gate * parameter provides this. Note that this program is carefully coded in 727c478bd9Sstevel@tonic-gate * order to maintain the "no bootstrapping" requirement -- it calls only 737c478bd9Sstevel@tonic-gate * local functions, uses no intrinsics, etc. 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate void * 767c478bd9Sstevel@tonic-gate __rtld(Elf32_Boot *ebp, const char *strings[], int (*funcs[])()) 777c478bd9Sstevel@tonic-gate { 787c478bd9Sstevel@tonic-gate int i, j, p; /* working */ 797c478bd9Sstevel@tonic-gate int page_size = 0; /* size of a page */ 807c478bd9Sstevel@tonic-gate const char *program_name = EMPTY; /* our name */ 817c478bd9Sstevel@tonic-gate int ldfd; /* fd assigned to ld.so */ 827c478bd9Sstevel@tonic-gate int dzfd = 0; /* fd assigned to /dev/zero */ 837c478bd9Sstevel@tonic-gate Elf32_Ehdr *ehdr; /* ELF header of ld.so */ 847c478bd9Sstevel@tonic-gate Elf32_Phdr *phdr; /* first Phdr in file */ 857c478bd9Sstevel@tonic-gate Elf32_Phdr *pptr; /* working Phdr */ 867c478bd9Sstevel@tonic-gate Elf32_Phdr *lph; /* last loadable Phdr */ 877c478bd9Sstevel@tonic-gate Elf32_Phdr *fph = 0; /* first loadable Phdr */ 887c478bd9Sstevel@tonic-gate caddr_t maddr; /* pointer to mapping claim */ 897c478bd9Sstevel@tonic-gate Elf32_Off mlen; /* total mapping claim */ 907c478bd9Sstevel@tonic-gate caddr_t faddr; /* first program mapping of ld.so */ 917c478bd9Sstevel@tonic-gate Elf32_Off foff; /* file offset for segment mapping */ 927c478bd9Sstevel@tonic-gate Elf32_Off flen; /* file length for segment mapping */ 937c478bd9Sstevel@tonic-gate caddr_t addr; /* working mapping address */ 947c478bd9Sstevel@tonic-gate caddr_t zaddr; /* /dev/zero working mapping addr */ 957c478bd9Sstevel@tonic-gate struct stat sb; /* stat buffer for sizing */ 967c478bd9Sstevel@tonic-gate auxv_t *ap; /* working aux pointer */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Discover things about our environment: auxiliary vector (if 1007c478bd9Sstevel@tonic-gate * any), arguments, program name, and the like. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate while (ebp->eb_tag != NULL) { 1037c478bd9Sstevel@tonic-gate switch (ebp->eb_tag) { 1047c478bd9Sstevel@tonic-gate case EB_ARGV: 1057c478bd9Sstevel@tonic-gate program_name = *((char **)ebp->eb_un.eb_ptr); 1067c478bd9Sstevel@tonic-gate break; 1077c478bd9Sstevel@tonic-gate case EB_AUXV: 1087c478bd9Sstevel@tonic-gate for (ap = (auxv_t *)ebp->eb_un.eb_ptr; 1097c478bd9Sstevel@tonic-gate ap->a_type != AT_NULL; ap++) 1107c478bd9Sstevel@tonic-gate if (ap->a_type == AT_PAGESZ) { 1117c478bd9Sstevel@tonic-gate page_size = ap->a_un.a_val; 1127c478bd9Sstevel@tonic-gate break; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate break; 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate ebp++; 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * If we didn't get a page size from looking in the auxiliary 1217c478bd9Sstevel@tonic-gate * vector, we need to get one now. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate if (page_size == 0) { 1247c478bd9Sstevel@tonic-gate page_size = SYSCONFIG(_CONFIG_PAGESIZE); 1257c478bd9Sstevel@tonic-gate ebp->eb_tag = EB_PAGESIZE, (ebp++)->eb_un.eb_val = 1267c478bd9Sstevel@tonic-gate (Elf32_Word)page_size; 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Map in the real ld.so. Note that we're mapping it as 1317c478bd9Sstevel@tonic-gate * an ELF database, not as a program -- we just want to walk it's 1327c478bd9Sstevel@tonic-gate * data structures. Further mappings will actually establish the 1337c478bd9Sstevel@tonic-gate * program in the address space. 1347c478bd9Sstevel@tonic-gate */ 135*8fd04b83SRoger A. Faulkner if ((ldfd = OPENAT(AT_FDCWD, LDSO, O_RDONLY)) == -1) 1367c478bd9Sstevel@tonic-gate PANIC(program_name); 137*8fd04b83SRoger A. Faulkner if (FSTATAT(ldfd, NULL, &sb, 0) == -1) 1387c478bd9Sstevel@tonic-gate PANIC(program_name); 1397c478bd9Sstevel@tonic-gate ehdr = (Elf32_Ehdr *)MMAP(0, sb.st_size, PROT_READ | PROT_EXEC, 1407c478bd9Sstevel@tonic-gate MAP_SHARED, ldfd, 0); 1417c478bd9Sstevel@tonic-gate if (ehdr == (Elf32_Ehdr *)-1) 1427c478bd9Sstevel@tonic-gate PANIC(program_name); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Validate the file we're looking at, ensure it has the correct 1467c478bd9Sstevel@tonic-gate * ELF structures, such as: ELF magic numbers, coded for 386, 1477c478bd9Sstevel@tonic-gate * is a ".so", etc. 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || 1507c478bd9Sstevel@tonic-gate ehdr->e_ident[EI_MAG1] != ELFMAG1 || 1517c478bd9Sstevel@tonic-gate ehdr->e_ident[EI_MAG2] != ELFMAG2 || 1527c478bd9Sstevel@tonic-gate ehdr->e_ident[EI_MAG3] != ELFMAG3) 1537c478bd9Sstevel@tonic-gate PANIC(program_name); 1547c478bd9Sstevel@tonic-gate if (ehdr->e_ident[EI_CLASS] != ELFCLASS32 || 1557c478bd9Sstevel@tonic-gate ehdr->e_ident[EI_DATA] != ELFDATA2LSB) 1567c478bd9Sstevel@tonic-gate PANIC(program_name); 1577c478bd9Sstevel@tonic-gate if (ehdr->e_type != ET_DYN) 1587c478bd9Sstevel@tonic-gate PANIC(program_name); 1597c478bd9Sstevel@tonic-gate if (ehdr->e_machine != EM_386) 1607c478bd9Sstevel@tonic-gate PANIC(program_name); 1617c478bd9Sstevel@tonic-gate if (ehdr->e_version > EV_CURRENT) 1627c478bd9Sstevel@tonic-gate PANIC(program_name); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Point at program headers and start figuring out what to load. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate phdr = (Elf32_Phdr *)((caddr_t)ehdr + ehdr->e_phoff); 1687c478bd9Sstevel@tonic-gate for (p = 0, pptr = phdr; p < (int)ehdr->e_phnum; p++, 1697c478bd9Sstevel@tonic-gate pptr = (Elf32_Phdr *)((caddr_t)pptr + ehdr->e_phentsize)) 1707c478bd9Sstevel@tonic-gate if (pptr->p_type == PT_LOAD) { 1717c478bd9Sstevel@tonic-gate if (fph == 0) { 1727c478bd9Sstevel@tonic-gate fph = pptr; 1737c478bd9Sstevel@tonic-gate } else if (pptr->p_vaddr <= lph->p_vaddr) 1747c478bd9Sstevel@tonic-gate PANIC(program_name); 1757c478bd9Sstevel@tonic-gate lph = pptr; 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * We'd better have at least one loadable segment. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate if (fph == 0) 1827c478bd9Sstevel@tonic-gate PANIC(program_name); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Map enough address space to hold the program (as opposed to the 1867c478bd9Sstevel@tonic-gate * file) represented by ld.so. The amount to be assigned is the 1877c478bd9Sstevel@tonic-gate * range between the end of the last loadable segment and the 1887c478bd9Sstevel@tonic-gate * beginning of the first PLUS the alignment of the first segment. 1897c478bd9Sstevel@tonic-gate * mmap() can assign us any page-aligned address, but the relocations 1907c478bd9Sstevel@tonic-gate * assume the alignments included in the program header. As an 1917c478bd9Sstevel@tonic-gate * optimization, however, let's assume that mmap() will actually 1927c478bd9Sstevel@tonic-gate * give us an aligned address -- since if it does, we can save 1937c478bd9Sstevel@tonic-gate * an munmap() later on. If it doesn't -- then go try it again. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate mlen = ROUND((lph->p_vaddr + lph->p_memsz) - 1967c478bd9Sstevel@tonic-gate ALIGN(fph->p_vaddr, page_size), page_size); 1977c478bd9Sstevel@tonic-gate maddr = (caddr_t)MMAP(0, mlen, PROT_READ | PROT_EXEC, 1987c478bd9Sstevel@tonic-gate MAP_SHARED, ldfd, 0); 1997c478bd9Sstevel@tonic-gate if (maddr == (caddr_t)-1) 2007c478bd9Sstevel@tonic-gate PANIC(program_name); 2017c478bd9Sstevel@tonic-gate faddr = (caddr_t)ROUND(maddr, fph->p_align); 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Check to see whether alignment skew was really needed. 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate if (faddr != maddr) { 2077c478bd9Sstevel@tonic-gate (void) MUNMAP(maddr, mlen); 2087c478bd9Sstevel@tonic-gate mlen = ROUND((lph->p_vaddr + lph->p_memsz) - 2097c478bd9Sstevel@tonic-gate ALIGN(fph->p_vaddr, fph->p_align) + fph->p_align, 2107c478bd9Sstevel@tonic-gate page_size); 2117c478bd9Sstevel@tonic-gate maddr = (caddr_t)MMAP(0, mlen, PROT_READ | PROT_EXEC, 2127c478bd9Sstevel@tonic-gate MAP_SHARED, ldfd, 0); 2137c478bd9Sstevel@tonic-gate if (maddr == (caddr_t)-1) 2147c478bd9Sstevel@tonic-gate PANIC(program_name); 2157c478bd9Sstevel@tonic-gate faddr = (caddr_t)ROUND(maddr, fph->p_align); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * We have the address space reserved, so map each loadable segment. 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate for (p = 0, pptr = phdr; p < (int)ehdr->e_phnum; p++, 2227c478bd9Sstevel@tonic-gate pptr = (Elf32_Phdr *)((caddr_t)pptr + ehdr->e_phentsize)) { 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Skip non-loadable segments or segments that don't occupy 2267c478bd9Sstevel@tonic-gate * any memory. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if ((pptr->p_type != PT_LOAD) || (pptr->p_memsz == 0)) 2297c478bd9Sstevel@tonic-gate continue; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * Determine the file offset to which the mapping will 2337c478bd9Sstevel@tonic-gate * directed (must be aligned) and how much to map (might 2347c478bd9Sstevel@tonic-gate * be more than the file in the case of .bss.) 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate foff = ALIGN(pptr->p_offset, page_size); 2377c478bd9Sstevel@tonic-gate flen = pptr->p_memsz + (pptr->p_offset - foff); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Set address of this segment relative to our base. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate addr = (caddr_t)ALIGN(faddr + pptr->p_vaddr, page_size); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * If this is the first program header, record our base 2467c478bd9Sstevel@tonic-gate * address for later use. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate if (pptr == phdr) { 2497c478bd9Sstevel@tonic-gate ebp->eb_tag = EB_LDSO_BASE; 2507c478bd9Sstevel@tonic-gate (ebp++)->eb_un.eb_ptr = (Elf32_Addr)addr; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Unmap anything from the last mapping address to this 2557c478bd9Sstevel@tonic-gate * one. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate if (addr - maddr) { 2587c478bd9Sstevel@tonic-gate (void) MUNMAP(maddr, addr - maddr); 2597c478bd9Sstevel@tonic-gate mlen -= addr - maddr; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Determine the mapping protection from the section 2647c478bd9Sstevel@tonic-gate * attributes. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate i = 0; 2677c478bd9Sstevel@tonic-gate if (pptr->p_flags & PF_R) 2687c478bd9Sstevel@tonic-gate i |= PROT_READ; 2697c478bd9Sstevel@tonic-gate if (pptr->p_flags & PF_W) 2707c478bd9Sstevel@tonic-gate i |= PROT_WRITE; 2717c478bd9Sstevel@tonic-gate if (pptr->p_flags & PF_X) 2727c478bd9Sstevel@tonic-gate i |= PROT_EXEC; 2737c478bd9Sstevel@tonic-gate if ((caddr_t)MMAP((caddr_t)addr, flen, i, 2747c478bd9Sstevel@tonic-gate MAP_FIXED | MAP_PRIVATE, ldfd, foff) == (caddr_t)-1) 2757c478bd9Sstevel@tonic-gate PANIC(program_name); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * If the memory occupancy of the segment overflows the 2797c478bd9Sstevel@tonic-gate * definition in the file, we need to "zero out" the 2807c478bd9Sstevel@tonic-gate * end of the mapping we've established, and if necessary, 2817c478bd9Sstevel@tonic-gate * map some more space from /dev/zero. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if (pptr->p_memsz > pptr->p_filesz) { 2847c478bd9Sstevel@tonic-gate foff = (int)faddr + pptr->p_vaddr + pptr->p_filesz; 2857c478bd9Sstevel@tonic-gate zaddr = (caddr_t)ROUND(foff, page_size); 2867c478bd9Sstevel@tonic-gate for (j = 0; j < (int)(zaddr - foff); j++) 2877c478bd9Sstevel@tonic-gate *((char *)foff + j) = 0; 2887c478bd9Sstevel@tonic-gate j = (faddr + pptr->p_vaddr + pptr->p_memsz) - zaddr; 2897c478bd9Sstevel@tonic-gate if (j > 0) { 2907c478bd9Sstevel@tonic-gate if (dzfd == 0) { 291*8fd04b83SRoger A. Faulkner dzfd = OPENAT(AT_FDCWD, ZERO, O_RDWR); 2927c478bd9Sstevel@tonic-gate if (dzfd == -1) 2937c478bd9Sstevel@tonic-gate PANIC(program_name); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate if ((caddr_t)MMAP((caddr_t)zaddr, j, i, 2967c478bd9Sstevel@tonic-gate MAP_FIXED | MAP_PRIVATE, dzfd, 2977c478bd9Sstevel@tonic-gate 0) == (caddr_t)-1) 2987c478bd9Sstevel@tonic-gate PANIC(program_name); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Update the mapping claim pointer. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate maddr = addr + ROUND(flen, page_size); 3067c478bd9Sstevel@tonic-gate mlen -= maddr - addr; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * Unmap any final reservation. 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate if (mlen > 0) 3137c478bd9Sstevel@tonic-gate (void) MUNMAP(maddr, mlen); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * Clean up file descriptor space we've consumed. Pass along 3177c478bd9Sstevel@tonic-gate * the /dev/zero file descriptor we got -- every cycle counts. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate (void) CLOSE(ldfd); 3207c478bd9Sstevel@tonic-gate if (dzfd != 0) 3217c478bd9Sstevel@tonic-gate ebp->eb_tag = EB_DEVZERO, (ebp++)->eb_un.eb_val = dzfd; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate ebp->eb_tag = EB_NULL, ebp->eb_un.eb_val = 0; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* The two bytes before _rt_boot is for the alias entry point */ 3267c478bd9Sstevel@tonic-gate return (void *) (ehdr->e_entry + faddr - 2); 3277c478bd9Sstevel@tonic-gate } 328