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 5986fd29aSsetje * Common Development and Distribution License (the "License"). 6986fd29aSsetje * 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 */ 217c478bd9Sstevel@tonic-gate /* 22*db9ce1c9SJerry Gilliam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/exechdr.h> 297c478bd9Sstevel@tonic-gate #include <sys/elf.h> 307c478bd9Sstevel@tonic-gate #include <sys/elf_notes.h> 317c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 327c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 337c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 347c478bd9Sstevel@tonic-gate #include <sys/stat.h> 357c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 367c478bd9Sstevel@tonic-gate #include <sys/link.h> 377c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 387c478bd9Sstevel@tonic-gate #include <sys/salib.h> 397c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h> 407c478bd9Sstevel@tonic-gate #include <sys/platnames.h> 417c478bd9Sstevel@tonic-gate 42bcbe9155Sjg #include "util.h" 43bcbe9155Sjg 447c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 457c478bd9Sstevel@tonic-gate #include <amd64/amd64_page.h> 467c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate union { 497c478bd9Sstevel@tonic-gate struct exec X; 507c478bd9Sstevel@tonic-gate Elf32_Ehdr Elfhdr; 517c478bd9Sstevel@tonic-gate Elf64_Ehdr Elfhdr64; 527c478bd9Sstevel@tonic-gate } ex; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define x ex.X 557c478bd9Sstevel@tonic-gate #define elfhdr ex.Elfhdr 567c478bd9Sstevel@tonic-gate #define elfhdr64 ex.Elfhdr64 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate typedef int (*func_t)(); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #define FAIL ((func_t)-1) 617c478bd9Sstevel@tonic-gate #define ALIGN(x, a) \ 627c478bd9Sstevel@tonic-gate ((a) == 0 ? (uintptr_t)(x) : (((uintptr_t)(x) + (a) - 1) & ~((a) - 1))) 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #define __BOOT_NAUXV_IMPL 22 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate int use_align = 0; 677c478bd9Sstevel@tonic-gate int npagesize = 0; 687c478bd9Sstevel@tonic-gate uint_t icache_flush = 0; 697c478bd9Sstevel@tonic-gate char *cpulist = NULL; 707c478bd9Sstevel@tonic-gate char *mmulist = NULL; 717c478bd9Sstevel@tonic-gate char *module_path; /* path for kernel modules */ 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * This file gets compiled in LP64 (for sun4u) and ILP32 models. 757c478bd9Sstevel@tonic-gate * For LP64 compilation, the "client" file we load and run may be LP64 or ILP32, 767c478bd9Sstevel@tonic-gate * and during bringup, the LP64 clients may have ELF32 headers. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 797c478bd9Sstevel@tonic-gate #ifndef BOOTAMD64 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Bootstrap vector for ELF32 LP64 client - neither supported nor needed for 827c478bd9Sstevel@tonic-gate * AMD64 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate Elf32_Boot *elfbootvecELF32_64; 857c478bd9Sstevel@tonic-gate #endif /* !BOOTAMD64 */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate Elf64_Boot *elfbootvecELF64; /* ELF bootstrap vector for Elf64 LP64 */ 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #define OK ((func_t)0) 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #define FAIL_READELF64 ((uint64_t)0) 927c478bd9Sstevel@tonic-gate #define FAIL_ILOAD64 ((Elf64_Addr)-1) 937c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * And by an ILP32 client. The non-sun4u/LP64 booters use these. 977c478bd9Sstevel@tonic-gate * Also, the sun4u booter must create this for ILP32 clients. 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate Elf32_Boot *elfbootvec; /* ELF bootstrap vector normal ILP32 */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * Read in a Unix executable file and return its entry point. 1037c478bd9Sstevel@tonic-gate * Handle the various a.out formats correctly. 1047c478bd9Sstevel@tonic-gate * "fd" is the standalone file descriptor to read from. 1057c478bd9Sstevel@tonic-gate * Print informative little messages if "print" is on. 1067c478bd9Sstevel@tonic-gate * Returns -1 for errors. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate #ifdef DEBUG 1107c478bd9Sstevel@tonic-gate static int debug = 1; 1117c478bd9Sstevel@tonic-gate #else /* DEBUG */ 1127c478bd9Sstevel@tonic-gate static int debug = 0; 1137c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate #define dprintf if (debug) printf 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 1187c478bd9Sstevel@tonic-gate typedef struct { 1197c478bd9Sstevel@tonic-gate uint_t a_type; 1207c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 1217c478bd9Sstevel@tonic-gate uint_t a_pad; /* needed to 8-byte align uint64_ts below for AMD64 */ 1227c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 1237c478bd9Sstevel@tonic-gate union { 1247c478bd9Sstevel@tonic-gate uint64_t a_val; 1257c478bd9Sstevel@tonic-gate uint64_t a_ptr; 1267c478bd9Sstevel@tonic-gate #ifndef BOOTAMD64 1277c478bd9Sstevel@tonic-gate void (*a_fcn)(); /* XXX - UNUSED? */ 1287c478bd9Sstevel@tonic-gate #endif /* !BOOTAMD64 */ 1297c478bd9Sstevel@tonic-gate } a_un; 1307c478bd9Sstevel@tonic-gate } auxv64_t; 1317c478bd9Sstevel@tonic-gate 132c2e7b48dSkalai #if defined(__sparcv9) 1337c478bd9Sstevel@tonic-gate extern int client_isLP64; 134c2e7b48dSkalai #endif /* __sparcv9 */ 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static uint64_t read_elf64(int, int, Elf64_Ehdr *); 1377c478bd9Sstevel@tonic-gate static Elf64_Addr iload64(char *, Elf64_Phdr *, Elf64_Phdr *, auxv64_t **); 1387c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate #if defined(i386) && !defined(_SYSCALL32) 1417c478bd9Sstevel@tonic-gate typedef auxv_t auxv32_t; 1427c478bd9Sstevel@tonic-gate #endif 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate static func_t read_elf32(int, int, Elf32_Ehdr *); 1457c478bd9Sstevel@tonic-gate static func_t iload32(char *, Elf32_Phdr *, Elf32_Phdr *, auxv32_t **); 1467c478bd9Sstevel@tonic-gate static caddr_t segbrk(caddr_t *, size_t, size_t); 1477c478bd9Sstevel@tonic-gate static int openpath(char *, char *, int); 1487c478bd9Sstevel@tonic-gate static char *getmodpath(char *); 1497c478bd9Sstevel@tonic-gate extern void setup_aux(void); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate extern void *kmem_alloc(size_t, int); 1527c478bd9Sstevel@tonic-gate extern void kmem_free(void *, size_t); 1537c478bd9Sstevel@tonic-gate extern int cons_gets(char *, int); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 1567c478bd9Sstevel@tonic-gate extern const char *amd64_getmmulist(void); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate extern int amd64_elf64; 1597c478bd9Sstevel@tonic-gate extern int is_amd64; 1607c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate #ifdef lint 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * This function is currently inlined 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1677c478bd9Sstevel@tonic-gate void 1687c478bd9Sstevel@tonic-gate sync_instruction_memory(caddr_t v, size_t len) 1697c478bd9Sstevel@tonic-gate {} 1707c478bd9Sstevel@tonic-gate #else /* lint */ 1717c478bd9Sstevel@tonic-gate extern void sync_instruction_memory(caddr_t v, size_t len); 1727c478bd9Sstevel@tonic-gate #endif /* lint */ 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate extern int verbosemode; 1757c478bd9Sstevel@tonic-gate extern int boothowto; 1767c478bd9Sstevel@tonic-gate extern int pagesize; 1777c478bd9Sstevel@tonic-gate extern char filename[]; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * repeat reads (forever) until size of request is satisfied 1817c478bd9Sstevel@tonic-gate * (Thus, you don't want to use this cases where short reads are ok) 1827c478bd9Sstevel@tonic-gate */ 183986fd29aSsetje ssize_t 1847c478bd9Sstevel@tonic-gate xread(int fd, char *p, size_t nbytes) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate size_t bytesread = 0; 1877c478bd9Sstevel@tonic-gate int errorcount = 0; 1887c478bd9Sstevel@tonic-gate ssize_t i; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate while (bytesread < nbytes) { 1917c478bd9Sstevel@tonic-gate i = read(fd, p, nbytes - bytesread); 1927c478bd9Sstevel@tonic-gate if (i < 0) { 1937c478bd9Sstevel@tonic-gate ++errorcount; 1947c478bd9Sstevel@tonic-gate if (verbosemode) 1957c478bd9Sstevel@tonic-gate printf("read error (0x%x times)\n", errorcount); 1967c478bd9Sstevel@tonic-gate continue; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate bytesread += i; 1997c478bd9Sstevel@tonic-gate p += i; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate return (bytesread); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate func_t 2057c478bd9Sstevel@tonic-gate readfile(int fd, int print) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 2087c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 20930f5cf21Sjg extern int bsetprop(struct bootops *, char *, void *, int); 2107c478bd9Sstevel@tonic-gate extern struct bootops *bop; 2117c478bd9Sstevel@tonic-gate extern uint64_t elf64_go2; 2127c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 2137c478bd9Sstevel@tonic-gate uint64_t elf64_go2; 2147c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 2157c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate ssize_t i; 2187c478bd9Sstevel@tonic-gate int shared = 0; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (verbosemode) { 2217c478bd9Sstevel@tonic-gate dprintf("fd = %x\n", fd); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate i = xread(fd, (char *)&elfhdr, sizeof (Elf64_Ehdr)); 2257c478bd9Sstevel@tonic-gate if (x.a_magic == ZMAGIC || x.a_magic == NMAGIC) 2267c478bd9Sstevel@tonic-gate shared = 1; 2277c478bd9Sstevel@tonic-gate if (i != sizeof (Elf64_Ehdr)) { 2287c478bd9Sstevel@tonic-gate printf("Error reading ELF header.\n"); 2297c478bd9Sstevel@tonic-gate return (FAIL); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate if (!shared && x.a_magic != OMAGIC) { 2327c478bd9Sstevel@tonic-gate if (*(int *)&elfhdr.e_ident == *(int *)(ELFMAG)) { 2337c478bd9Sstevel@tonic-gate if (verbosemode) { 2347c478bd9Sstevel@tonic-gate int is64 = (elfhdr.e_ident[EI_CLASS] == 2357c478bd9Sstevel@tonic-gate ELFCLASS64); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate dprintf("calling readelf, elfheader is:\n"); 2387c478bd9Sstevel@tonic-gate dprintf("e_ident\t0x%x, 0x%x, 0x%x, 0x%x\n", 2397c478bd9Sstevel@tonic-gate *(int *)&elfhdr.e_ident[0], 2407c478bd9Sstevel@tonic-gate *(int *)&elfhdr.e_ident[4], 2417c478bd9Sstevel@tonic-gate *(int *)&elfhdr.e_ident[8], 2427c478bd9Sstevel@tonic-gate *(int *)&elfhdr.e_ident[12]); 2437c478bd9Sstevel@tonic-gate dprintf("e_machine\t0x%x\n", elfhdr.e_machine); 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate dprintf("e_entry\t\t0x%llx\n", (is64 ? 2467c478bd9Sstevel@tonic-gate elfhdr64.e_entry : 2477c478bd9Sstevel@tonic-gate (u_longlong_t)elfhdr.e_entry)); 2487c478bd9Sstevel@tonic-gate dprintf("e_shoff\t\t0x%llx\n", (is64 ? 2497c478bd9Sstevel@tonic-gate elfhdr64.e_shoff : 2507c478bd9Sstevel@tonic-gate (u_longlong_t)elfhdr.e_shoff)); 2517c478bd9Sstevel@tonic-gate dprintf("e_shnentsize\t%d\n", (is64 ? 2527c478bd9Sstevel@tonic-gate elfhdr64.e_shentsize : elfhdr.e_shentsize)); 2537c478bd9Sstevel@tonic-gate dprintf("e_shnum\t\t%d\n", (is64 ? 2547c478bd9Sstevel@tonic-gate elfhdr64.e_shnum : elfhdr.e_shnum)); 2557c478bd9Sstevel@tonic-gate dprintf("e_shstrndx\t%d\n", (is64 ? 2567c478bd9Sstevel@tonic-gate elfhdr64.e_shstrndx : elfhdr.e_shstrndx)); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 2617c478bd9Sstevel@tonic-gate dprintf("ELF file CLASS 0x%x 32 is %x 64 is %x\n", 2627c478bd9Sstevel@tonic-gate elfhdr.e_ident[EI_CLASS], ELFCLASS32, ELFCLASS64); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (elfhdr.e_ident[EI_CLASS] == ELFCLASS64) { 2657c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 2667c478bd9Sstevel@tonic-gate if (elfhdr.e_machine != EM_AMD64) { 2677c478bd9Sstevel@tonic-gate printf("FATAL: 64-bit ELF executable " 2687c478bd9Sstevel@tonic-gate "not for AMD64\n (e_machine " 2697c478bd9Sstevel@tonic-gate "= %d).\n", elfhdr.e_machine); 2707c478bd9Sstevel@tonic-gate return (FAIL); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * OK, we know the executable is for an AMD64 2757c478bd9Sstevel@tonic-gate * CPU. Make sure we ARE an AMD64 CPU before 2767c478bd9Sstevel@tonic-gate * proceeding. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate if (is_amd64 == 0) { 2797c478bd9Sstevel@tonic-gate printf("FATAL: AMD64 executables not " 2807c478bd9Sstevel@tonic-gate " supported on this CPU.\n"); 2817c478bd9Sstevel@tonic-gate return (FAIL); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate amd64_elf64 = (elfhdr.e_ident[EI_CLASS] == 2857c478bd9Sstevel@tonic-gate ELFCLASS64); 2867c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate elf64_go2 = read_elf64(fd, print, 2897c478bd9Sstevel@tonic-gate (Elf64_Ehdr *)&elfhdr); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 2927c478bd9Sstevel@tonic-gate if (elf64_go2 != FAIL_READELF64) 2937c478bd9Sstevel@tonic-gate (void) bsetprop(bop, "mmu-modlist", 29430f5cf21Sjg "mmu64", 0); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate return ((elf64_go2 == FAIL_READELF64) ? FAIL : 2977c478bd9Sstevel@tonic-gate OK); 2987c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 2997c478bd9Sstevel@tonic-gate return ((elf64_go2 == FAIL_READELF64) ? FAIL : 3007c478bd9Sstevel@tonic-gate (func_t)elf64_go2); 3017c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate } else 3047c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 3057c478bd9Sstevel@tonic-gate return (read_elf32(fd, print, &elfhdr)); 3067c478bd9Sstevel@tonic-gate } else { 3077c478bd9Sstevel@tonic-gate printf("File not executable.\n"); 3087c478bd9Sstevel@tonic-gate return (FAIL); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate return (FAIL); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 31553391bafSeota * Macros to add attribute/values to the ELF bootstrap vector 31653391bafSeota * and the aux vector. Use the type-cast to convert integers 31753391bafSeota * to pointers first to suppress the gcc warning. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate #define AUX(p, a, v) { (p)->a_type = (a); \ 32053391bafSeota ((p)++)->a_un.a_val = (int32_t)(uintptr_t)(v); } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate #define EBV(p, a, v) { (p)->eb_tag = (a); \ 32353391bafSeota ((p)++)->eb_un.eb_val = (Elf32_Word)(uintptr_t)(v); } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate static func_t 3267c478bd9Sstevel@tonic-gate read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate Elf32_Phdr *phdr; /* program header */ 3297c478bd9Sstevel@tonic-gate Elf32_Nhdr *nhdr; /* note header */ 3307c478bd9Sstevel@tonic-gate int nphdrs, phdrsize; 3317c478bd9Sstevel@tonic-gate caddr_t allphdrs; 3327c478bd9Sstevel@tonic-gate caddr_t namep, descp; 3337c478bd9Sstevel@tonic-gate Elf32_Addr loadaddr, base; 3347c478bd9Sstevel@tonic-gate size_t offset = 0; 3357c478bd9Sstevel@tonic-gate size_t size; 3367c478bd9Sstevel@tonic-gate uintptr_t off; 3377c478bd9Sstevel@tonic-gate int i; 3387c478bd9Sstevel@tonic-gate int bss_seen = 0; 3397c478bd9Sstevel@tonic-gate int interp = 0; /* interpreter required */ 3407c478bd9Sstevel@tonic-gate static char dlname[MAXPATHLEN]; /* name of interpeter */ 3417c478bd9Sstevel@tonic-gate uint_t dynamic; /* dynamic tags array */ 3427c478bd9Sstevel@tonic-gate Elf32_Phdr *thdr; /* "text" program header */ 3437c478bd9Sstevel@tonic-gate Elf32_Phdr *dhdr; /* "data" program header */ 3447c478bd9Sstevel@tonic-gate func_t entrypt; /* entry point of standalone */ 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* Initialize pointers so we won't free bogus ones on elferror */ 3477c478bd9Sstevel@tonic-gate allphdrs = NULL; 3487c478bd9Sstevel@tonic-gate nhdr = NULL; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 3517c478bd9Sstevel@tonic-gate if (verbosemode) 3527c478bd9Sstevel@tonic-gate printf("Elf32 client\n"); 3537c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0) 3567c478bd9Sstevel@tonic-gate goto elferror; 3577c478bd9Sstevel@tonic-gate 35853391bafSeota /* use uintptr_t to suppress the gcc warning */ 35953391bafSeota entrypt = (func_t)(uintptr_t)elfhdrp->e_entry; 3607c478bd9Sstevel@tonic-gate if (verbosemode) 3617c478bd9Sstevel@tonic-gate dprintf("Entry point: %p\n", (void *)entrypt); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Allocate and read in all the program headers. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate nphdrs = elfhdrp->e_phnum; 3677c478bd9Sstevel@tonic-gate phdrsize = nphdrs * elfhdrp->e_phentsize; 3687c478bd9Sstevel@tonic-gate allphdrs = (caddr_t)kmem_alloc(phdrsize, 0); 3697c478bd9Sstevel@tonic-gate if (allphdrs == NULL) 3707c478bd9Sstevel@tonic-gate goto elferror; 3717c478bd9Sstevel@tonic-gate if (verbosemode) 3727c478bd9Sstevel@tonic-gate dprintf("lseek: args = %x %x %x\n", fd, elfhdrp->e_phoff, 0); 3737c478bd9Sstevel@tonic-gate if (lseek(fd, elfhdrp->e_phoff, 0) == -1) 3747c478bd9Sstevel@tonic-gate goto elferror; 3757c478bd9Sstevel@tonic-gate if (xread(fd, allphdrs, phdrsize) != phdrsize) 3767c478bd9Sstevel@tonic-gate goto elferror; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * First look for PT_NOTE headers that tell us what pagesize to 3807c478bd9Sstevel@tonic-gate * use in allocating program memory. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate npagesize = 0; 3837c478bd9Sstevel@tonic-gate for (i = 0; i < nphdrs; i++) { 3847c478bd9Sstevel@tonic-gate void *note_buf; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i); 3877c478bd9Sstevel@tonic-gate if (phdr->p_type != PT_NOTE) 3887c478bd9Sstevel@tonic-gate continue; 3897c478bd9Sstevel@tonic-gate if (verbosemode) { 3907c478bd9Sstevel@tonic-gate dprintf("allocating 0x%x bytes for note hdr\n", 3917c478bd9Sstevel@tonic-gate phdr->p_filesz); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL) 3947c478bd9Sstevel@tonic-gate goto elferror; 3957c478bd9Sstevel@tonic-gate if (verbosemode) 3967c478bd9Sstevel@tonic-gate dprintf("seeking to 0x%x\n", phdr->p_offset); 3977c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) 3987c478bd9Sstevel@tonic-gate goto elferror; 3997c478bd9Sstevel@tonic-gate if (verbosemode) { 4007c478bd9Sstevel@tonic-gate dprintf("reading 0x%x bytes into %p\n", 4017c478bd9Sstevel@tonic-gate phdr->p_filesz, (void *)nhdr); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate nhdr = (Elf32_Nhdr *)note_buf; 4047c478bd9Sstevel@tonic-gate if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz) 4057c478bd9Sstevel@tonic-gate goto elferror; 4067c478bd9Sstevel@tonic-gate if (verbosemode) { 4077c478bd9Sstevel@tonic-gate dprintf("p_note namesz %x descsz %x type %x\n", 4087c478bd9Sstevel@tonic-gate nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* 4127c478bd9Sstevel@tonic-gate * Iterate through all ELF PT_NOTE elements looking for 4137c478bd9Sstevel@tonic-gate * ELF_NOTE_SOLARIS which, if present, will specify the 4147c478bd9Sstevel@tonic-gate * executable's preferred pagesize. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate do { 4177c478bd9Sstevel@tonic-gate namep = (caddr_t)(nhdr + 1); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 && 4207c478bd9Sstevel@tonic-gate strcmp(namep, ELF_NOTE_SOLARIS) == 0 && 4217c478bd9Sstevel@tonic-gate nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) { 4227c478bd9Sstevel@tonic-gate descp = namep + roundup(nhdr->n_namesz, 4); 4237c478bd9Sstevel@tonic-gate npagesize = *(int *)descp; 4247c478bd9Sstevel@tonic-gate if (verbosemode) 4257c478bd9Sstevel@tonic-gate dprintf("pagesize is %x\n", npagesize); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate offset += sizeof (Elf32_Nhdr) + roundup(nhdr->n_namesz, 4297c478bd9Sstevel@tonic-gate 4) + roundup(nhdr->n_descsz, 4); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate nhdr = (Elf32_Nhdr *)((char *)note_buf + offset); 4327c478bd9Sstevel@tonic-gate } while (offset < phdr->p_filesz); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate kmem_free(note_buf, phdr->p_filesz); 4357c478bd9Sstevel@tonic-gate nhdr = NULL; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Next look for PT_LOAD headers to read in. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate if (print) 4427c478bd9Sstevel@tonic-gate printf("Size: "); 4437c478bd9Sstevel@tonic-gate for (i = 0; i < nphdrs; i++) { 4447c478bd9Sstevel@tonic-gate phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i); 4457c478bd9Sstevel@tonic-gate if (verbosemode) { 4467c478bd9Sstevel@tonic-gate dprintf("Doing header 0x%x\n", i); 4477c478bd9Sstevel@tonic-gate dprintf("phdr\n"); 4487c478bd9Sstevel@tonic-gate dprintf("\tp_offset = %x, p_vaddr = %x\n", 4497c478bd9Sstevel@tonic-gate phdr->p_offset, phdr->p_vaddr); 4507c478bd9Sstevel@tonic-gate dprintf("\tp_memsz = %x, p_filesz = %x\n", 4517c478bd9Sstevel@tonic-gate phdr->p_memsz, phdr->p_filesz); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_LOAD) { 4547c478bd9Sstevel@tonic-gate if (verbosemode) 4557c478bd9Sstevel@tonic-gate dprintf("seeking to 0x%x\n", phdr->p_offset); 4567c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) 4577c478bd9Sstevel@tonic-gate goto elferror; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate if (phdr->p_flags == (PF_R | PF_W) && 4607c478bd9Sstevel@tonic-gate phdr->p_vaddr == 0) { 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * It's a PT_LOAD segment that is RW but 4637c478bd9Sstevel@tonic-gate * not executable and has a vaddr 4647c478bd9Sstevel@tonic-gate * of zero. This is relocation info that 4657c478bd9Sstevel@tonic-gate * doesn't need to stick around after 4667c478bd9Sstevel@tonic-gate * krtld is done with it. We allocate boot 4677c478bd9Sstevel@tonic-gate * memory for this segment, since we don't want 4687c478bd9Sstevel@tonic-gate * it mapped in permanently as part of 4697c478bd9Sstevel@tonic-gate * the kernel image. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate if ((loadaddr = (uintptr_t) 4727c478bd9Sstevel@tonic-gate kmem_alloc(phdr->p_memsz, 0)) == NULL) 4737c478bd9Sstevel@tonic-gate goto elferror; 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * Save this to pass on 4767c478bd9Sstevel@tonic-gate * to the interpreter. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate phdr->p_vaddr = (Elf32_Addr)loadaddr; 4797c478bd9Sstevel@tonic-gate } else { 4807c478bd9Sstevel@tonic-gate if (print) 4817c478bd9Sstevel@tonic-gate printf("0x%x+", phdr->p_filesz); 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * If we found a new pagesize above, use it 4847c478bd9Sstevel@tonic-gate * to adjust the memory allocation. 4857c478bd9Sstevel@tonic-gate */ 4867c478bd9Sstevel@tonic-gate loadaddr = phdr->p_vaddr; 4877c478bd9Sstevel@tonic-gate if (use_align && npagesize != 0) { 4887c478bd9Sstevel@tonic-gate off = loadaddr & (npagesize - 1); 4897c478bd9Sstevel@tonic-gate size = roundup(phdr->p_memsz + off, 4907c478bd9Sstevel@tonic-gate npagesize); 4917c478bd9Sstevel@tonic-gate base = loadaddr - off; 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate npagesize = 0; 4947c478bd9Sstevel@tonic-gate size = phdr->p_memsz; 4957c478bd9Sstevel@tonic-gate base = loadaddr; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * Check if it's text or data. 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate if (phdr->p_flags & PF_W) 5017c478bd9Sstevel@tonic-gate dhdr = phdr; 5027c478bd9Sstevel@tonic-gate else 5037c478bd9Sstevel@tonic-gate thdr = phdr; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * If memory size is zero just ignore this 5077c478bd9Sstevel@tonic-gate * header. 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gate if (size == 0) 5107c478bd9Sstevel@tonic-gate continue; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (verbosemode) 5137c478bd9Sstevel@tonic-gate dprintf("allocating memory: %x %lx " 5147c478bd9Sstevel@tonic-gate "%x\n", base, size, npagesize); 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * We're all set up to read. 5177c478bd9Sstevel@tonic-gate * Now let's allocate some memory. 5187c478bd9Sstevel@tonic-gate */ 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate #ifdef i386 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * If vaddr == paddr and npagesize is 0, that 5237c478bd9Sstevel@tonic-gate * means the executable needs to be identity 5247c478bd9Sstevel@tonic-gate * mapped in memory (va == pa, mapped 1:1) 5257c478bd9Sstevel@tonic-gate * 5267c478bd9Sstevel@tonic-gate * Otherwise load as usual. 5277c478bd9Sstevel@tonic-gate */ 5287c478bd9Sstevel@tonic-gate if ((phdr->p_vaddr == phdr->p_paddr) && 5297c478bd9Sstevel@tonic-gate (npagesize == 0)) { 5307c478bd9Sstevel@tonic-gate extern caddr_t idmap_mem(uint32_t, 5317c478bd9Sstevel@tonic-gate size_t, int); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate uint_t n; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate n = (uint_t)base & (pagesize - 1); 5367c478bd9Sstevel@tonic-gate if (n) { 5377c478bd9Sstevel@tonic-gate base -= n; 5387c478bd9Sstevel@tonic-gate size += n; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if (!idmap_mem((uint32_t)base, 5427c478bd9Sstevel@tonic-gate (size_t)size, pagesize)) 5437c478bd9Sstevel@tonic-gate goto elferror; 5447c478bd9Sstevel@tonic-gate } else 5457c478bd9Sstevel@tonic-gate #endif /* i386 */ 54653391bafSeota /* use uintptr_t to suppress the gcc warning */ 54753391bafSeota if (get_progmemory((caddr_t)(uintptr_t)base, 54853391bafSeota size, npagesize)) 5497c478bd9Sstevel@tonic-gate goto elferror; 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate if (verbosemode) { 5537c478bd9Sstevel@tonic-gate dprintf("reading 0x%x bytes into 0x%x\n", 5547c478bd9Sstevel@tonic-gate phdr->p_filesz, loadaddr); 5557c478bd9Sstevel@tonic-gate } 55653391bafSeota /* use uintptr_t to suppress the gcc warning */ 55753391bafSeota if (xread(fd, (caddr_t)(uintptr_t)loadaddr, 55853391bafSeota phdr->p_filesz) != phdr->p_filesz) 5597c478bd9Sstevel@tonic-gate goto elferror; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* zero out BSS */ 5627c478bd9Sstevel@tonic-gate if (phdr->p_memsz > phdr->p_filesz) { 5637c478bd9Sstevel@tonic-gate loadaddr += phdr->p_filesz; 5647c478bd9Sstevel@tonic-gate if (verbosemode) { 5657c478bd9Sstevel@tonic-gate dprintf("bss from 0x%x size 0x%x\n", 5667c478bd9Sstevel@tonic-gate loadaddr, 5677c478bd9Sstevel@tonic-gate phdr->p_memsz - phdr->p_filesz); 5687c478bd9Sstevel@tonic-gate } 56953391bafSeota /* use uintptr_t to suppress the gcc warning */ 57053391bafSeota bzero((void *)(uintptr_t)loadaddr, 5717c478bd9Sstevel@tonic-gate phdr->p_memsz - phdr->p_filesz); 5727c478bd9Sstevel@tonic-gate bss_seen++; 5737c478bd9Sstevel@tonic-gate if (print) 5747c478bd9Sstevel@tonic-gate printf("0x%x Bytes\n", 5757c478bd9Sstevel@tonic-gate phdr->p_memsz - phdr->p_filesz); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* force instructions to be visible to icache */ 57953391bafSeota if (phdr->p_flags & PF_X) { 58053391bafSeota sync_instruction_memory( 58153391bafSeota (caddr_t)(uintptr_t)phdr->p_vaddr, 5827c478bd9Sstevel@tonic-gate phdr->p_memsz); 58353391bafSeota } 5847c478bd9Sstevel@tonic-gate } else if (phdr->p_type == PT_INTERP) { 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Dynamically-linked executable. 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate interp = 1; 5897c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) { 5907c478bd9Sstevel@tonic-gate goto elferror; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * Get the name of the interpreter. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate if (xread(fd, dlname, phdr->p_filesz) != 5967c478bd9Sstevel@tonic-gate phdr->p_filesz || 5977c478bd9Sstevel@tonic-gate dlname[phdr->p_filesz - 1] != '\0') 5987c478bd9Sstevel@tonic-gate goto elferror; 5997c478bd9Sstevel@tonic-gate } else if (phdr->p_type == PT_DYNAMIC) { 6007c478bd9Sstevel@tonic-gate dynamic = phdr->p_vaddr; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (!bss_seen && print) 6057c478bd9Sstevel@tonic-gate printf("0 Bytes\n"); 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate /* 6087c478bd9Sstevel@tonic-gate * Load the interpreter 6097c478bd9Sstevel@tonic-gate * if there is one. 6107c478bd9Sstevel@tonic-gate */ 6117c478bd9Sstevel@tonic-gate if (interp) { 6127c478bd9Sstevel@tonic-gate Elf32_Boot bootv[EB_MAX]; /* Bootstrap vector */ 6137c478bd9Sstevel@tonic-gate auxv32_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */ 6147c478bd9Sstevel@tonic-gate Elf32_Boot *bv = bootv; 6157c478bd9Sstevel@tonic-gate auxv32_t *av = auxv; 6167c478bd9Sstevel@tonic-gate size_t vsize; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * Load it. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate if ((entrypt = iload32(dlname, thdr, dhdr, &av)) == FAIL) 6227c478bd9Sstevel@tonic-gate goto elferror; 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Build bootstrap and aux vectors. 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate setup_aux(); 6277c478bd9Sstevel@tonic-gate EBV(bv, EB_AUXV, 0); /* fill in later */ 6287c478bd9Sstevel@tonic-gate EBV(bv, EB_PAGESIZE, pagesize); 6297c478bd9Sstevel@tonic-gate EBV(bv, EB_DYNAMIC, dynamic); 6307c478bd9Sstevel@tonic-gate EBV(bv, EB_NULL, 0); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate AUX(av, AT_BASE, entrypt); 6337c478bd9Sstevel@tonic-gate AUX(av, AT_ENTRY, elfhdrp->e_entry); 6347c478bd9Sstevel@tonic-gate AUX(av, AT_PAGESZ, pagesize); 6357c478bd9Sstevel@tonic-gate AUX(av, AT_PHDR, allphdrs); 6367c478bd9Sstevel@tonic-gate AUX(av, AT_PHNUM, elfhdrp->e_phnum); 6377c478bd9Sstevel@tonic-gate AUX(av, AT_PHENT, elfhdrp->e_phentsize); 6387c478bd9Sstevel@tonic-gate if (use_align) 6397c478bd9Sstevel@tonic-gate AUX(av, AT_SUN_LPAGESZ, npagesize); 6407c478bd9Sstevel@tonic-gate AUX(av, AT_SUN_IFLUSH, icache_flush); 6417c478bd9Sstevel@tonic-gate if (cpulist != NULL) 6427c478bd9Sstevel@tonic-gate AUX(av, AT_SUN_CPU, cpulist); 6437c478bd9Sstevel@tonic-gate if (mmulist != NULL) 6447c478bd9Sstevel@tonic-gate AUX(av, AT_SUN_MMU, mmulist); 6457c478bd9Sstevel@tonic-gate AUX(av, AT_NULL, 0); 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * Realloc vectors and copy them. 6487c478bd9Sstevel@tonic-gate */ 6497c478bd9Sstevel@tonic-gate vsize = (caddr_t)bv - (caddr_t)bootv; 6507c478bd9Sstevel@tonic-gate if ((elfbootvec = (Elf32_Boot *)kmem_alloc(vsize, 0)) == NULL) 6517c478bd9Sstevel@tonic-gate goto elferror; 6527c478bd9Sstevel@tonic-gate bcopy((char *)bootv, (char *)elfbootvec, vsize); 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate size = (caddr_t)av - (caddr_t)auxv; 6557c478bd9Sstevel@tonic-gate if (size > sizeof (auxv)) { 6567c478bd9Sstevel@tonic-gate printf("readelf: overrun of available aux vectors\n"); 6577c478bd9Sstevel@tonic-gate kmem_free(elfbootvec, vsize); 6587c478bd9Sstevel@tonic-gate goto elferror; 6597c478bd9Sstevel@tonic-gate } 66053391bafSeota /* use uintptr_t to suppress the gcc warning */ 6617c478bd9Sstevel@tonic-gate if ((elfbootvec->eb_un.eb_ptr = 66253391bafSeota (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == NULL) { 6637c478bd9Sstevel@tonic-gate kmem_free(elfbootvec, vsize); 6647c478bd9Sstevel@tonic-gate goto elferror; 6657c478bd9Sstevel@tonic-gate } 66653391bafSeota /* use uintptr_t to suppress the gcc warning */ 66753391bafSeota bcopy(auxv, 66853391bafSeota (void *)(uintptr_t)(elfbootvec->eb_un.eb_ptr), size); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate #if defined(_ELF64_SUPPORT) && !defined(BOOTAMD64) 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * Make an LP64 copy of the vector for use by 64-bit standalones 6737c478bd9Sstevel@tonic-gate * even if they have ELF32. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate if ((elfbootvecELF32_64 = (Elf32_Boot *)kmem_alloc(vsize, 0)) 6767c478bd9Sstevel@tonic-gate == NULL) 6777c478bd9Sstevel@tonic-gate goto elferror; 6787c478bd9Sstevel@tonic-gate bcopy(bootv, elfbootvecELF32_64, vsize); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate size = (av - auxv) * sizeof (auxv64_t); 68153391bafSeota /* use uintptr_t to suppress the gcc warning */ 6827c478bd9Sstevel@tonic-gate if ((elfbootvecELF32_64->eb_un.eb_ptr = 68353391bafSeota (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == NULL) { 6847c478bd9Sstevel@tonic-gate kmem_free(elfbootvecELF32_64, vsize); 6857c478bd9Sstevel@tonic-gate goto elferror; 6867c478bd9Sstevel@tonic-gate } else { 6877c478bd9Sstevel@tonic-gate auxv64_t *a64 = 68853391bafSeota (auxv64_t *)(uintptr_t) 68953391bafSeota elfbootvecELF32_64->eb_un.eb_ptr; 6907c478bd9Sstevel@tonic-gate auxv32_t *a = auxv; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate for (a = auxv; a < av; a++) { 6937c478bd9Sstevel@tonic-gate a64->a_type = a->a_type; 6947c478bd9Sstevel@tonic-gate a64->a_un.a_val = a->a_un.a_val; 6957c478bd9Sstevel@tonic-gate a64++; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT && !BOOTAMD64 */ 6997c478bd9Sstevel@tonic-gate } else { 7007c478bd9Sstevel@tonic-gate kmem_free(allphdrs, phdrsize); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate return (entrypt); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate elferror: 7057c478bd9Sstevel@tonic-gate if (allphdrs != NULL) 7067c478bd9Sstevel@tonic-gate kmem_free(allphdrs, phdrsize); 7077c478bd9Sstevel@tonic-gate if (nhdr != NULL) 7087c478bd9Sstevel@tonic-gate kmem_free(nhdr, phdr->p_filesz); 7097c478bd9Sstevel@tonic-gate printf("Elf32 read error.\n"); 7107c478bd9Sstevel@tonic-gate return (FAIL); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 7147c478bd9Sstevel@tonic-gate /* 7157c478bd9Sstevel@tonic-gate * Macros to add attribute/values to the ELF bootstrap vector 7167c478bd9Sstevel@tonic-gate * and the aux vector. 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate #define AUX64(p, a, v) { (p)->a_type = (a); \ 7197c478bd9Sstevel@tonic-gate ((p)++)->a_un.a_val = (uint64_t)(v); } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate #define EBV64(p, a, v) { (p)->eb_tag = (a); \ 7227c478bd9Sstevel@tonic-gate ((p)++)->eb_un.eb_val = (Elf64_Xword)(v); } 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate static uint64_t 7257c478bd9Sstevel@tonic-gate read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp) 7267c478bd9Sstevel@tonic-gate { 7277c478bd9Sstevel@tonic-gate Elf64_Phdr *phdr; /* program header */ 7287c478bd9Sstevel@tonic-gate Elf64_Nhdr *nhdr; /* note header */ 7297c478bd9Sstevel@tonic-gate int nphdrs, phdrsize; 7307c478bd9Sstevel@tonic-gate caddr_t allphdrs; 7317c478bd9Sstevel@tonic-gate caddr_t namep, descp; 7327c478bd9Sstevel@tonic-gate Elf64_Addr loadaddr, base; 7337c478bd9Sstevel@tonic-gate size_t offset = 0; 7347c478bd9Sstevel@tonic-gate size_t size; 7357c478bd9Sstevel@tonic-gate int i; 7367c478bd9Sstevel@tonic-gate uintptr_t off; 7377c478bd9Sstevel@tonic-gate int bss_seen = 0; 7387c478bd9Sstevel@tonic-gate int interp = 0; /* interpreter required */ 7397c478bd9Sstevel@tonic-gate static char dlname[MAXPATHLEN]; /* name of interpeter */ 7407c478bd9Sstevel@tonic-gate uintptr_t dynamic; /* dynamic tags array */ 7417c478bd9Sstevel@tonic-gate Elf64_Phdr *thdr; /* "text" program header */ 7427c478bd9Sstevel@tonic-gate Elf64_Phdr *dhdr; /* "data" program header */ 7437c478bd9Sstevel@tonic-gate Elf64_Addr entrypt; /* entry point of standalone */ 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* Initialize pointers so we won't free bogus ones on elf64error */ 7467c478bd9Sstevel@tonic-gate allphdrs = NULL; 7477c478bd9Sstevel@tonic-gate nhdr = NULL; 748c2e7b48dSkalai #if defined(__sparcv9) 7497c478bd9Sstevel@tonic-gate client_isLP64 = 1; 750c2e7b48dSkalai #endif /* __sparcv9 */ 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate if (verbosemode) 7537c478bd9Sstevel@tonic-gate printf("Elf64 client\n"); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0) 7567c478bd9Sstevel@tonic-gate goto elf64error; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate entrypt = elfhdrp->e_entry; 7597c478bd9Sstevel@tonic-gate if (verbosemode) 7607c478bd9Sstevel@tonic-gate dprintf("Entry point: 0x%llx\n", (u_longlong_t)entrypt); 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * Allocate and read in all the program headers. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate nphdrs = elfhdrp->e_phnum; 7667c478bd9Sstevel@tonic-gate phdrsize = nphdrs * elfhdrp->e_phentsize; 7677c478bd9Sstevel@tonic-gate allphdrs = (caddr_t)kmem_alloc(phdrsize, 0); 7687c478bd9Sstevel@tonic-gate if (allphdrs == NULL) 7697c478bd9Sstevel@tonic-gate goto elf64error; 7707c478bd9Sstevel@tonic-gate if (verbosemode) 7717c478bd9Sstevel@tonic-gate dprintf("lseek: args = %x %llx %x\n", fd, 7727c478bd9Sstevel@tonic-gate (u_longlong_t)elfhdrp->e_phoff, 0); 7737c478bd9Sstevel@tonic-gate if (lseek(fd, elfhdrp->e_phoff, 0) == -1) 7747c478bd9Sstevel@tonic-gate goto elf64error; 7757c478bd9Sstevel@tonic-gate if (xread(fd, allphdrs, phdrsize) != phdrsize) 7767c478bd9Sstevel@tonic-gate goto elf64error; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate /* 7797c478bd9Sstevel@tonic-gate * First look for PT_NOTE headers that tell us what pagesize to 7807c478bd9Sstevel@tonic-gate * use in allocating program memory. 7817c478bd9Sstevel@tonic-gate */ 7827c478bd9Sstevel@tonic-gate npagesize = 0; 7837c478bd9Sstevel@tonic-gate for (i = 0; i < nphdrs; i++) { 7847c478bd9Sstevel@tonic-gate void *note_buf; 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i); 7877c478bd9Sstevel@tonic-gate if (phdr->p_type != PT_NOTE) 7887c478bd9Sstevel@tonic-gate continue; 7897c478bd9Sstevel@tonic-gate if (verbosemode) { 7907c478bd9Sstevel@tonic-gate dprintf("allocating 0x%llx bytes for note hdr\n", 7917c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_filesz); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL) 7947c478bd9Sstevel@tonic-gate goto elf64error; 7957c478bd9Sstevel@tonic-gate if (verbosemode) 7967c478bd9Sstevel@tonic-gate dprintf("seeking to 0x%llx\n", 7977c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_offset); 7987c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) 7997c478bd9Sstevel@tonic-gate goto elf64error; 8007c478bd9Sstevel@tonic-gate if (verbosemode) { 8017c478bd9Sstevel@tonic-gate dprintf("reading 0x%llx bytes into 0x%p\n", 8027c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_filesz, (void *)nhdr); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate nhdr = (Elf64_Nhdr *)note_buf; 8057c478bd9Sstevel@tonic-gate if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz) 8067c478bd9Sstevel@tonic-gate goto elf64error; 8077c478bd9Sstevel@tonic-gate if (verbosemode) { 8087c478bd9Sstevel@tonic-gate dprintf("p_note namesz %x descsz %x type %x\n", 8097c478bd9Sstevel@tonic-gate nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type); 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Iterate through all ELF PT_NOTE elements looking for 8147c478bd9Sstevel@tonic-gate * ELF_NOTE_SOLARIS which, if present, will specify the 8157c478bd9Sstevel@tonic-gate * executable's preferred pagesize. 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate do { 8187c478bd9Sstevel@tonic-gate namep = (caddr_t)(nhdr + 1); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 && 8217c478bd9Sstevel@tonic-gate strcmp(namep, ELF_NOTE_SOLARIS) == 0 && 8227c478bd9Sstevel@tonic-gate nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) { 8237c478bd9Sstevel@tonic-gate descp = namep + roundup(nhdr->n_namesz, 4); 8247c478bd9Sstevel@tonic-gate npagesize = *(int *)descp; 8257c478bd9Sstevel@tonic-gate if (verbosemode) 8267c478bd9Sstevel@tonic-gate dprintf("pagesize is %x\n", npagesize); 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate offset += sizeof (Elf64_Nhdr) + roundup(nhdr->n_namesz, 8307c478bd9Sstevel@tonic-gate 4) + roundup(nhdr->n_descsz, 4); 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate nhdr = (Elf64_Nhdr *)((char *)note_buf + offset); 8337c478bd9Sstevel@tonic-gate } while (offset < phdr->p_filesz); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate kmem_free(note_buf, phdr->p_filesz); 8367c478bd9Sstevel@tonic-gate nhdr = NULL; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate /* 8407c478bd9Sstevel@tonic-gate * Next look for PT_LOAD headers to read in. 8417c478bd9Sstevel@tonic-gate */ 8427c478bd9Sstevel@tonic-gate if (print) 8437c478bd9Sstevel@tonic-gate printf("Size: "); 8447c478bd9Sstevel@tonic-gate for (i = 0; i < nphdrs; i++) { 8457c478bd9Sstevel@tonic-gate phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i); 8467c478bd9Sstevel@tonic-gate if (verbosemode) { 8477c478bd9Sstevel@tonic-gate dprintf("Doing header 0x%x\n", i); 8487c478bd9Sstevel@tonic-gate dprintf("phdr\n"); 8497c478bd9Sstevel@tonic-gate dprintf("\tp_offset = %llx, p_vaddr = %llx\n", 8507c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_offset, 8517c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_vaddr); 8527c478bd9Sstevel@tonic-gate dprintf("\tp_memsz = %llx, p_filesz = %llx\n", 8537c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_memsz, 8547c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_filesz); 8557c478bd9Sstevel@tonic-gate dprintf("\tp_type = %x, p_flags = %x\n", 8567c478bd9Sstevel@tonic-gate phdr->p_type, phdr->p_flags); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_LOAD) { 8597c478bd9Sstevel@tonic-gate if (verbosemode) 8607c478bd9Sstevel@tonic-gate dprintf("seeking to 0x%llx\n", 8617c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_offset); 8627c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) 8637c478bd9Sstevel@tonic-gate goto elf64error; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate if (phdr->p_flags == (PF_R | PF_W) && 8667c478bd9Sstevel@tonic-gate phdr->p_vaddr == 0) { 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * It's a PT_LOAD segment that is RW but 8697c478bd9Sstevel@tonic-gate * not executable and has a vaddr 8707c478bd9Sstevel@tonic-gate * of zero. This is relocation info that 8717c478bd9Sstevel@tonic-gate * doesn't need to stick around after 8727c478bd9Sstevel@tonic-gate * krtld is done with it. We allocate boot 8737c478bd9Sstevel@tonic-gate * memory for this segment, since we don't want 8747c478bd9Sstevel@tonic-gate * it mapped in permanently as part of 8757c478bd9Sstevel@tonic-gate * the kernel image. 8767c478bd9Sstevel@tonic-gate */ 8777c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 8787c478bd9Sstevel@tonic-gate if ((loadaddr = (Elf64_Addr) 8797c478bd9Sstevel@tonic-gate (ADDR_XTND(kmem_alloc(phdr->p_memsz, 0)))) 8807c478bd9Sstevel@tonic-gate == NULL) 8817c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 8827c478bd9Sstevel@tonic-gate if ((loadaddr = (Elf64_Addr)(uintptr_t) 8837c478bd9Sstevel@tonic-gate kmem_alloc(phdr->p_memsz, 0)) == NULL) 8847c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 8857c478bd9Sstevel@tonic-gate goto elf64error; 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate /* 8887c478bd9Sstevel@tonic-gate * Save this to pass on 8897c478bd9Sstevel@tonic-gate * to the interpreter. 8907c478bd9Sstevel@tonic-gate */ 8917c478bd9Sstevel@tonic-gate phdr->p_vaddr = loadaddr; 8927c478bd9Sstevel@tonic-gate } else { 8937c478bd9Sstevel@tonic-gate if (print) 8947c478bd9Sstevel@tonic-gate printf("0x%llx+", 8957c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_filesz); 8967c478bd9Sstevel@tonic-gate /* 8977c478bd9Sstevel@tonic-gate * If we found a new pagesize above, use it 8987c478bd9Sstevel@tonic-gate * to adjust the memory allocation. 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate loadaddr = phdr->p_vaddr; 9017c478bd9Sstevel@tonic-gate if (use_align && npagesize != 0) { 9027c478bd9Sstevel@tonic-gate off = loadaddr & (npagesize - 1); 9037c478bd9Sstevel@tonic-gate size = roundup(phdr->p_memsz + off, 9047c478bd9Sstevel@tonic-gate npagesize); 9057c478bd9Sstevel@tonic-gate base = loadaddr - off; 9067c478bd9Sstevel@tonic-gate } else { 9077c478bd9Sstevel@tonic-gate npagesize = 0; 9087c478bd9Sstevel@tonic-gate size = phdr->p_memsz; 9097c478bd9Sstevel@tonic-gate base = loadaddr; 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate /* 9127c478bd9Sstevel@tonic-gate * Check if it's text or data. 9137c478bd9Sstevel@tonic-gate */ 9147c478bd9Sstevel@tonic-gate if (phdr->p_flags & PF_W) 9157c478bd9Sstevel@tonic-gate dhdr = phdr; 9167c478bd9Sstevel@tonic-gate else 9177c478bd9Sstevel@tonic-gate thdr = phdr; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (verbosemode) 9207c478bd9Sstevel@tonic-gate dprintf( 9217c478bd9Sstevel@tonic-gate "allocating memory: %llx %lx %x\n", 9227c478bd9Sstevel@tonic-gate (u_longlong_t)base, 9237c478bd9Sstevel@tonic-gate size, npagesize); 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * If memory size is zero just ignore this 9277c478bd9Sstevel@tonic-gate * header. 9287c478bd9Sstevel@tonic-gate */ 9297c478bd9Sstevel@tonic-gate if (size == 0) 9307c478bd9Sstevel@tonic-gate continue; 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * We're all set up to read. 9347c478bd9Sstevel@tonic-gate * Now let's allocate some memory. 9357c478bd9Sstevel@tonic-gate */ 936bcbe9155Sjg if (get_progmemory((caddr_t)(uintptr_t)base, 937bcbe9155Sjg size, npagesize)) 9387c478bd9Sstevel@tonic-gate goto elf64error; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate if (verbosemode) { 9427c478bd9Sstevel@tonic-gate dprintf("reading 0x%llx bytes into 0x%llx\n", 9437c478bd9Sstevel@tonic-gate (u_longlong_t)phdr->p_filesz, 9447c478bd9Sstevel@tonic-gate (u_longlong_t)loadaddr); 9457c478bd9Sstevel@tonic-gate } 946bcbe9155Sjg if (xread(fd, (caddr_t)(uintptr_t) 947bcbe9155Sjg loadaddr, phdr->p_filesz) != phdr->p_filesz) 9487c478bd9Sstevel@tonic-gate goto elf64error; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* zero out BSS */ 9517c478bd9Sstevel@tonic-gate if (phdr->p_memsz > phdr->p_filesz) { 9527c478bd9Sstevel@tonic-gate loadaddr += phdr->p_filesz; 9537c478bd9Sstevel@tonic-gate if (verbosemode) { 9547c478bd9Sstevel@tonic-gate dprintf("bss from 0x%llx size 0x%llx\n", 9557c478bd9Sstevel@tonic-gate (u_longlong_t)loadaddr, 9567c478bd9Sstevel@tonic-gate (u_longlong_t)(phdr->p_memsz - 9577c478bd9Sstevel@tonic-gate phdr->p_filesz)); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 960bcbe9155Sjg bzero((caddr_t)(uintptr_t)loadaddr, 9617c478bd9Sstevel@tonic-gate phdr->p_memsz - phdr->p_filesz); 9627c478bd9Sstevel@tonic-gate bss_seen++; 9637c478bd9Sstevel@tonic-gate if (print) 9647c478bd9Sstevel@tonic-gate printf("0x%llx Bytes\n", 9657c478bd9Sstevel@tonic-gate (u_longlong_t)(phdr->p_memsz - 9667c478bd9Sstevel@tonic-gate phdr->p_filesz)); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* force instructions to be visible to icache */ 9707c478bd9Sstevel@tonic-gate if (phdr->p_flags & PF_X) 971bcbe9155Sjg sync_instruction_memory((caddr_t)(uintptr_t) 972bcbe9155Sjg phdr->p_vaddr, phdr->p_memsz); 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate } else if (phdr->p_type == PT_INTERP) { 9757c478bd9Sstevel@tonic-gate /* 9767c478bd9Sstevel@tonic-gate * Dynamically-linked executable. 9777c478bd9Sstevel@tonic-gate */ 9787c478bd9Sstevel@tonic-gate interp = 1; 9797c478bd9Sstevel@tonic-gate if (lseek(fd, phdr->p_offset, 0) == -1) { 9807c478bd9Sstevel@tonic-gate goto elf64error; 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate /* 9837c478bd9Sstevel@tonic-gate * Get the name of the interpreter. 9847c478bd9Sstevel@tonic-gate */ 9857c478bd9Sstevel@tonic-gate if (xread(fd, dlname, phdr->p_filesz) != 9867c478bd9Sstevel@tonic-gate phdr->p_filesz || 9877c478bd9Sstevel@tonic-gate dlname[phdr->p_filesz - 1] != '\0') 9887c478bd9Sstevel@tonic-gate goto elf64error; 9897c478bd9Sstevel@tonic-gate } else if (phdr->p_type == PT_DYNAMIC) { 9907c478bd9Sstevel@tonic-gate dynamic = phdr->p_vaddr; 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if (!bss_seen && print) 9957c478bd9Sstevel@tonic-gate printf("0 Bytes\n"); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate /* 9987c478bd9Sstevel@tonic-gate * Load the interpreter 9997c478bd9Sstevel@tonic-gate * if there is one. 10007c478bd9Sstevel@tonic-gate */ 10017c478bd9Sstevel@tonic-gate if (interp) { 10027c478bd9Sstevel@tonic-gate Elf64_Boot bootv[EB_MAX]; /* Bootstrap vector */ 10037c478bd9Sstevel@tonic-gate auxv64_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */ 10047c478bd9Sstevel@tonic-gate Elf64_Boot *bv = bootv; 10057c478bd9Sstevel@tonic-gate auxv64_t *av = auxv; 10067c478bd9Sstevel@tonic-gate size_t vsize; 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate /* 10097c478bd9Sstevel@tonic-gate * Load it. 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate if ((entrypt = iload64(dlname, thdr, dhdr, &av)) == 10127c478bd9Sstevel@tonic-gate FAIL_ILOAD64) 10137c478bd9Sstevel@tonic-gate goto elf64error; 10147c478bd9Sstevel@tonic-gate /* 10157c478bd9Sstevel@tonic-gate * Build bootstrap and aux vectors. 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate setup_aux(); 10187c478bd9Sstevel@tonic-gate EBV64(bv, EB_AUXV, 0); /* fill in later */ 10197c478bd9Sstevel@tonic-gate EBV64(bv, EB_PAGESIZE, pagesize); 10207c478bd9Sstevel@tonic-gate EBV64(bv, EB_DYNAMIC, dynamic); 10217c478bd9Sstevel@tonic-gate EBV64(bv, EB_NULL, 0); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate AUX64(av, AT_BASE, entrypt); 10247c478bd9Sstevel@tonic-gate AUX64(av, AT_ENTRY, elfhdrp->e_entry); 10257c478bd9Sstevel@tonic-gate AUX64(av, AT_PAGESZ, pagesize); 1026bcbe9155Sjg AUX64(av, AT_PHDR, (uintptr_t)allphdrs); 10277c478bd9Sstevel@tonic-gate AUX64(av, AT_PHNUM, elfhdrp->e_phnum); 10287c478bd9Sstevel@tonic-gate AUX64(av, AT_PHENT, elfhdrp->e_phentsize); 10297c478bd9Sstevel@tonic-gate if (npagesize) 10307c478bd9Sstevel@tonic-gate AUX64(av, AT_SUN_LPAGESZ, npagesize); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 10337c478bd9Sstevel@tonic-gate vsize = strlen(amd64_getmmulist()) + 1; 10347c478bd9Sstevel@tonic-gate if ((mmulist = kmem_alloc(vsize, 0)) == NULL) 10357c478bd9Sstevel@tonic-gate goto elf64error; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate bcopy(amd64_getmmulist(), mmulist, vsize); 10387c478bd9Sstevel@tonic-gate AUX64(av, AT_SUN_MMU, (uintptr_t)mmulist); 10397c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate AUX64(av, AT_SUN_IFLUSH, icache_flush); 10427c478bd9Sstevel@tonic-gate if (cpulist != NULL) 1043bcbe9155Sjg AUX64(av, AT_SUN_CPU, (uintptr_t)cpulist); 10447c478bd9Sstevel@tonic-gate AUX64(av, AT_NULL, 0); 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * Realloc vectors and copy them. 10477c478bd9Sstevel@tonic-gate */ 10487c478bd9Sstevel@tonic-gate vsize = (caddr_t)bv - (caddr_t)bootv; 10497c478bd9Sstevel@tonic-gate if ((elfbootvecELF64 = 10507c478bd9Sstevel@tonic-gate (Elf64_Boot *)kmem_alloc(vsize, 0)) == NULL) 10517c478bd9Sstevel@tonic-gate goto elf64error; 10527c478bd9Sstevel@tonic-gate bcopy((char *)bootv, (char *)elfbootvecELF64, vsize); 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate size = (caddr_t)av - (caddr_t)auxv; 10557c478bd9Sstevel@tonic-gate if (size > sizeof (auxv)) { 10567c478bd9Sstevel@tonic-gate printf("readelf: overrun of available aux vectors\n"); 10577c478bd9Sstevel@tonic-gate kmem_free(elfbootvecELF64, vsize); 10587c478bd9Sstevel@tonic-gate goto elf64error; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 10627c478bd9Sstevel@tonic-gate if ((elfbootvecELF64->eb_un.eb_ptr = 10637c478bd9Sstevel@tonic-gate ADDR_XTND(kmem_alloc(size, 0))) == NULL) { 10647c478bd9Sstevel@tonic-gate kmem_free(elfbootvecELF64, vsize); 10657c478bd9Sstevel@tonic-gate goto elf64error; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate bcopy((char *)auxv, 10697c478bd9Sstevel@tonic-gate (char *)ADDR_TRUNC((elfbootvecELF64->eb_un.eb_ptr)), size); 10707c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 10717c478bd9Sstevel@tonic-gate if ((elfbootvecELF64->eb_un.eb_ptr = 10727c478bd9Sstevel@tonic-gate (Elf64_Addr)kmem_alloc(size, 0)) == NULL) { 10737c478bd9Sstevel@tonic-gate kmem_free(elfbootvecELF64, vsize); 10747c478bd9Sstevel@tonic-gate goto elf64error; 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate bcopy((char *)auxv, (char *)(elfbootvecELF64->eb_un.eb_ptr), 10787c478bd9Sstevel@tonic-gate size); 10797c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 10807c478bd9Sstevel@tonic-gate } else { 10817c478bd9Sstevel@tonic-gate kmem_free(allphdrs, phdrsize); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate return ((uint64_t)entrypt); 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate elf64error: 10867c478bd9Sstevel@tonic-gate if (allphdrs != NULL) 10877c478bd9Sstevel@tonic-gate kmem_free(allphdrs, phdrsize); 10887c478bd9Sstevel@tonic-gate if (nhdr != NULL) 10897c478bd9Sstevel@tonic-gate kmem_free(nhdr, phdr->p_filesz); 10907c478bd9Sstevel@tonic-gate printf("Elf64 read error.\n"); 10917c478bd9Sstevel@tonic-gate return (FAIL_READELF64); 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * Load the interpreter. It expects a 10977c478bd9Sstevel@tonic-gate * relocatable .o capable of bootstrapping 10987c478bd9Sstevel@tonic-gate * itself. 10997c478bd9Sstevel@tonic-gate */ 11007c478bd9Sstevel@tonic-gate static func_t 11017c478bd9Sstevel@tonic-gate iload32(char *rtld, Elf32_Phdr *thdr, Elf32_Phdr *dhdr, auxv32_t **avp) 11027c478bd9Sstevel@tonic-gate { 11037c478bd9Sstevel@tonic-gate Elf32_Ehdr *ehdr = NULL; 11047c478bd9Sstevel@tonic-gate uintptr_t dl_entry = 0; 11057c478bd9Sstevel@tonic-gate uint_t i; 11067c478bd9Sstevel@tonic-gate int fd; 11077c478bd9Sstevel@tonic-gate int size; 11087c478bd9Sstevel@tonic-gate caddr_t shdrs = NULL; 11097c478bd9Sstevel@tonic-gate caddr_t etext, edata; 11107c478bd9Sstevel@tonic-gate 111153391bafSeota /* use uintptr_t to suppress the gcc warning */ 111253391bafSeota etext = (caddr_t)(uintptr_t)thdr->p_vaddr + thdr->p_memsz; 111353391bafSeota edata = (caddr_t)(uintptr_t)dhdr->p_vaddr + dhdr->p_memsz; 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate /* 11167c478bd9Sstevel@tonic-gate * Get the module path. 11177c478bd9Sstevel@tonic-gate */ 11187c478bd9Sstevel@tonic-gate module_path = getmodpath(filename); 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) { 11217c478bd9Sstevel@tonic-gate printf("boot: cannot find %s\n", rtld); 11227c478bd9Sstevel@tonic-gate goto errorx; 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate dprintf("Opened %s OK\n", rtld); 11257c478bd9Sstevel@tonic-gate AUX(*avp, AT_SUN_LDNAME, rtld); 11267c478bd9Sstevel@tonic-gate /* 11277c478bd9Sstevel@tonic-gate * Allocate and read the ELF header. 11287c478bd9Sstevel@tonic-gate */ 11297c478bd9Sstevel@tonic-gate if ((ehdr = (Elf32_Ehdr *)kmem_alloc(sizeof (Elf32_Ehdr), 0)) == NULL) { 11307c478bd9Sstevel@tonic-gate printf("boot: alloc error reading ELF header (%s).\n", rtld); 11317c478bd9Sstevel@tonic-gate goto error; 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) { 11357c478bd9Sstevel@tonic-gate printf("boot: error reading ELF header (%s).\n", rtld); 11367c478bd9Sstevel@tonic-gate goto error; 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate size = ehdr->e_shentsize * ehdr->e_shnum; 11407c478bd9Sstevel@tonic-gate if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) { 11417c478bd9Sstevel@tonic-gate printf("boot: alloc error reading ELF header (%s).\n", rtld); 11427c478bd9Sstevel@tonic-gate goto error; 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * Read the section headers. 11467c478bd9Sstevel@tonic-gate */ 11477c478bd9Sstevel@tonic-gate if (lseek(fd, ehdr->e_shoff, 0) == -1 || 11487c478bd9Sstevel@tonic-gate xread(fd, shdrs, size) != size) { 11497c478bd9Sstevel@tonic-gate printf("boot: error reading section headers\n"); 11507c478bd9Sstevel@tonic-gate goto error; 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate AUX(*avp, AT_SUN_LDELF, ehdr); 11537c478bd9Sstevel@tonic-gate AUX(*avp, AT_SUN_LDSHDR, shdrs); 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate * Load sections into the appropriate dynamic segment. 11567c478bd9Sstevel@tonic-gate */ 11577c478bd9Sstevel@tonic-gate for (i = 1; i < ehdr->e_shnum; i++) { 11587c478bd9Sstevel@tonic-gate Elf32_Shdr *sp; 11597c478bd9Sstevel@tonic-gate caddr_t *spp; 11607c478bd9Sstevel@tonic-gate caddr_t load; 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate sp = (Elf32_Shdr *)(shdrs + (i*ehdr->e_shentsize)); 11637c478bd9Sstevel@tonic-gate /* 11647c478bd9Sstevel@tonic-gate * If it's not allocated and not required 11657c478bd9Sstevel@tonic-gate * to do relocation, skip it. 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate if (!(sp->sh_flags & SHF_ALLOC) && 11687c478bd9Sstevel@tonic-gate #ifdef i386 1169986fd29aSsetje sp->sh_type != SHT_REL && 11707c478bd9Sstevel@tonic-gate #else 1171986fd29aSsetje sp->sh_type != SHT_RELA && 11727c478bd9Sstevel@tonic-gate #endif 1173986fd29aSsetje sp->sh_type != SHT_SYMTAB && 1174986fd29aSsetje sp->sh_type != SHT_STRTAB) 11757c478bd9Sstevel@tonic-gate continue; 11767c478bd9Sstevel@tonic-gate /* 11777c478bd9Sstevel@tonic-gate * If the section is read-only, 11787c478bd9Sstevel@tonic-gate * it goes in as text. 11797c478bd9Sstevel@tonic-gate */ 11807c478bd9Sstevel@tonic-gate spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext; 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * Make some room for it. 11837c478bd9Sstevel@tonic-gate */ 11847c478bd9Sstevel@tonic-gate load = segbrk(spp, sp->sh_size, sp->sh_addralign); 11857c478bd9Sstevel@tonic-gate if (load == NULL) { 11867c478bd9Sstevel@tonic-gate printf("boot: allocating memory for sections failed\n"); 11877c478bd9Sstevel@tonic-gate goto error; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate /* 11907c478bd9Sstevel@tonic-gate * Compute the entry point of the linker. 11917c478bd9Sstevel@tonic-gate */ 11927c478bd9Sstevel@tonic-gate if (dl_entry == 0 && 11937c478bd9Sstevel@tonic-gate !(sp->sh_flags & SHF_WRITE) && 11947c478bd9Sstevel@tonic-gate (sp->sh_flags & SHF_EXECINSTR)) { 11957c478bd9Sstevel@tonic-gate dl_entry = (uintptr_t)load + ehdr->e_entry; 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate /* 11987c478bd9Sstevel@tonic-gate * If it's bss, just zero it out. 11997c478bd9Sstevel@tonic-gate */ 12007c478bd9Sstevel@tonic-gate if (sp->sh_type == SHT_NOBITS) { 12017c478bd9Sstevel@tonic-gate bzero(load, sp->sh_size); 12027c478bd9Sstevel@tonic-gate } else { 12037c478bd9Sstevel@tonic-gate /* 12047c478bd9Sstevel@tonic-gate * Read the section contents. 12057c478bd9Sstevel@tonic-gate */ 12067c478bd9Sstevel@tonic-gate if (lseek(fd, sp->sh_offset, 0) == -1 || 12077c478bd9Sstevel@tonic-gate xread(fd, load, sp->sh_size) != sp->sh_size) { 12087c478bd9Sstevel@tonic-gate printf("boot: error reading sections\n"); 12097c478bd9Sstevel@tonic-gate goto error; 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate /* 121353391bafSeota * Assign the section's virtual addr. Use uintptr_t to 121453391bafSeota * suppress the gcc warning. 12157c478bd9Sstevel@tonic-gate */ 121653391bafSeota sp->sh_addr = (Elf32_Off)(uintptr_t)load; 121753391bafSeota /* 121853391bafSeota * Force instructions to be visible to icache. Use 121953391bafSeota * uintptr_t to suppress the gcc warning as well. 122053391bafSeota */ 12217c478bd9Sstevel@tonic-gate if (sp->sh_flags & SHF_EXECINSTR) 122253391bafSeota sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr, 12237c478bd9Sstevel@tonic-gate sp->sh_size); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate /* 12267c478bd9Sstevel@tonic-gate * Update sizes of segments. 12277c478bd9Sstevel@tonic-gate */ 12287c478bd9Sstevel@tonic-gate thdr->p_memsz = (Elf32_Word)((uintptr_t)etext - thdr->p_vaddr); 12297c478bd9Sstevel@tonic-gate dhdr->p_memsz = (Elf32_Word)((uintptr_t)edata - dhdr->p_vaddr); 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /* load and relocate symbol tables in SAS */ 12327c478bd9Sstevel@tonic-gate (void) close(fd); 12337c478bd9Sstevel@tonic-gate return ((func_t)dl_entry); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate error: 12367c478bd9Sstevel@tonic-gate (void) close(fd); 12377c478bd9Sstevel@tonic-gate errorx: 12387c478bd9Sstevel@tonic-gate if (ehdr) 12397c478bd9Sstevel@tonic-gate kmem_free(ehdr, sizeof (Elf32_Ehdr)); 12407c478bd9Sstevel@tonic-gate if (shdrs) 12417c478bd9Sstevel@tonic-gate kmem_free(shdrs, size); 12427c478bd9Sstevel@tonic-gate printf("boot: error loading interpreter (%s)\n", rtld); 12437c478bd9Sstevel@tonic-gate return (FAIL); 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate #ifdef _ELF64_SUPPORT 12477c478bd9Sstevel@tonic-gate /* 12487c478bd9Sstevel@tonic-gate * Load the interpreter. It expects a 12497c478bd9Sstevel@tonic-gate * relocatable .o capable of bootstrapping 12507c478bd9Sstevel@tonic-gate * itself. 12517c478bd9Sstevel@tonic-gate */ 12527c478bd9Sstevel@tonic-gate static Elf64_Addr 12537c478bd9Sstevel@tonic-gate iload64(char *rtld, Elf64_Phdr *thdr, Elf64_Phdr *dhdr, auxv64_t **avp) 12547c478bd9Sstevel@tonic-gate { 12557c478bd9Sstevel@tonic-gate Elf64_Ehdr *ehdr = NULL; 12567c478bd9Sstevel@tonic-gate Elf64_Addr dl_entry = (Elf64_Addr)0; 12577c478bd9Sstevel@tonic-gate Elf64_Addr etext, edata; 12587c478bd9Sstevel@tonic-gate uint_t i; 12597c478bd9Sstevel@tonic-gate int fd; 12607c478bd9Sstevel@tonic-gate int size; 12617c478bd9Sstevel@tonic-gate caddr_t shdrs = NULL; 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate etext = thdr->p_vaddr + thdr->p_memsz; 12647c478bd9Sstevel@tonic-gate edata = dhdr->p_vaddr + dhdr->p_memsz; 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate /* 12677c478bd9Sstevel@tonic-gate * Get the module path. 12687c478bd9Sstevel@tonic-gate */ 12697c478bd9Sstevel@tonic-gate module_path = getmodpath(filename); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) { 12727c478bd9Sstevel@tonic-gate printf("boot: cannot find %s\n", rtld); 12737c478bd9Sstevel@tonic-gate goto errorx; 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate dprintf("Opened %s OK\n", rtld); 1276bcbe9155Sjg AUX64(*avp, AT_SUN_LDNAME, (uintptr_t)rtld); 12777c478bd9Sstevel@tonic-gate /* 12787c478bd9Sstevel@tonic-gate * Allocate and read the ELF header. 12797c478bd9Sstevel@tonic-gate */ 12807c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 12817c478bd9Sstevel@tonic-gate if ((ehdr = (Elf64_Ehdr *)(uintptr_t)kmem_alloc(sizeof (Elf64_Ehdr), 12827c478bd9Sstevel@tonic-gate 0)) == NULL) { 12837c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 12847c478bd9Sstevel@tonic-gate if ((ehdr = (Elf64_Ehdr *)kmem_alloc(sizeof (Elf64_Ehdr), 0)) == NULL) { 12857c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 12867c478bd9Sstevel@tonic-gate printf("boot: alloc error reading ELF header (%s).\n", rtld); 12877c478bd9Sstevel@tonic-gate goto error; 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) { 12917c478bd9Sstevel@tonic-gate printf("boot: error reading ELF header (%s).\n", rtld); 12927c478bd9Sstevel@tonic-gate goto error; 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate size = ehdr->e_shentsize * ehdr->e_shnum; 12967c478bd9Sstevel@tonic-gate if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) { 12977c478bd9Sstevel@tonic-gate printf("boot: alloc error reading ELF header (%s).\n", rtld); 12987c478bd9Sstevel@tonic-gate goto error; 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * Read the section headers. 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate if (lseek(fd, ehdr->e_shoff, 0) == -1 || 13047c478bd9Sstevel@tonic-gate xread(fd, shdrs, size) != size) { 13057c478bd9Sstevel@tonic-gate printf("boot: error reading section headers\n"); 13067c478bd9Sstevel@tonic-gate goto error; 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 13107c478bd9Sstevel@tonic-gate AUX64(*avp, AT_SUN_LDELF, (uintptr_t)ehdr); 13117c478bd9Sstevel@tonic-gate AUX64(*avp, AT_SUN_LDSHDR, (uintptr_t)shdrs); 13127c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 13137c478bd9Sstevel@tonic-gate AUX64(*avp, AT_SUN_LDELF, ehdr); 13147c478bd9Sstevel@tonic-gate AUX64(*avp, AT_SUN_LDSHDR, shdrs); 13157c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* 13187c478bd9Sstevel@tonic-gate * Load sections into the appropriate dynamic segment. 13197c478bd9Sstevel@tonic-gate */ 13207c478bd9Sstevel@tonic-gate for (i = 1; i < ehdr->e_shnum; i++) { 13217c478bd9Sstevel@tonic-gate Elf64_Shdr *sp; 13227c478bd9Sstevel@tonic-gate Elf64_Addr *spp, load; 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate sp = (Elf64_Shdr *)(shdrs + (i*ehdr->e_shentsize)); 13257c478bd9Sstevel@tonic-gate /* 13267c478bd9Sstevel@tonic-gate * If it's not allocated and not required 13277c478bd9Sstevel@tonic-gate * to do relocation, skip it. 13287c478bd9Sstevel@tonic-gate */ 13297c478bd9Sstevel@tonic-gate if (!(sp->sh_flags & SHF_ALLOC) && 13307c478bd9Sstevel@tonic-gate sp->sh_type != SHT_SYMTAB && 13317c478bd9Sstevel@tonic-gate sp->sh_type != SHT_STRTAB && 13327c478bd9Sstevel@tonic-gate sp->sh_type != SHT_RELA) 13337c478bd9Sstevel@tonic-gate continue; 13347c478bd9Sstevel@tonic-gate /* 13357c478bd9Sstevel@tonic-gate * If the section is read-only, 13367c478bd9Sstevel@tonic-gate * it goes in as text. 13377c478bd9Sstevel@tonic-gate */ 13387c478bd9Sstevel@tonic-gate spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate /* 13417c478bd9Sstevel@tonic-gate * Make some room for it. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 13447c478bd9Sstevel@tonic-gate load = ADDR_XTND(segbrk((caddr_t *)spp, 13457c478bd9Sstevel@tonic-gate sp->sh_size, sp->sh_addralign)); 13467c478bd9Sstevel@tonic-gate #else /* !BOOTAMD64 */ 13477c478bd9Sstevel@tonic-gate load = (Elf64_Addr)segbrk((caddr_t *)spp, sp->sh_size, 13487c478bd9Sstevel@tonic-gate sp->sh_addralign); 13497c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if (load == NULL) { 13527c478bd9Sstevel@tonic-gate printf("boot: allocating memory for section %d " 13537c478bd9Sstevel@tonic-gate "failed\n", i); 13547c478bd9Sstevel@tonic-gate goto error; 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate * Compute the entry point of the linker. 13597c478bd9Sstevel@tonic-gate */ 13607c478bd9Sstevel@tonic-gate if (dl_entry == 0 && 13617c478bd9Sstevel@tonic-gate !(sp->sh_flags & SHF_WRITE) && 13627c478bd9Sstevel@tonic-gate (sp->sh_flags & SHF_EXECINSTR)) { 13637c478bd9Sstevel@tonic-gate dl_entry = load + ehdr->e_entry; 13647c478bd9Sstevel@tonic-gate if (verbosemode) 13657c478bd9Sstevel@tonic-gate dprintf("boot: loading linker @ 0x%llx\n", 13667c478bd9Sstevel@tonic-gate (u_longlong_t)dl_entry); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate /* 13707c478bd9Sstevel@tonic-gate * If it's bss, just zero it out. 13717c478bd9Sstevel@tonic-gate */ 13727c478bd9Sstevel@tonic-gate if (sp->sh_type == SHT_NOBITS) { 1373bcbe9155Sjg bzero((caddr_t)(uintptr_t)load, sp->sh_size); 13747c478bd9Sstevel@tonic-gate } else { 13757c478bd9Sstevel@tonic-gate /* 13767c478bd9Sstevel@tonic-gate * Read the section contents. 13777c478bd9Sstevel@tonic-gate */ 13787c478bd9Sstevel@tonic-gate if (lseek(fd, sp->sh_offset, 0) == -1 || 1379bcbe9155Sjg xread(fd, (caddr_t)(uintptr_t)load, sp->sh_size) != 13807c478bd9Sstevel@tonic-gate sp->sh_size) { 1381986fd29aSsetje printf("boot: error reading section %d\n", i); 13827c478bd9Sstevel@tonic-gate goto error; 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * Assign the section's virtual addr. 13877c478bd9Sstevel@tonic-gate */ 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate sp->sh_addr = load; 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate if (verbosemode) 13927c478bd9Sstevel@tonic-gate dprintf("boot: section %d, type %d, loaded @ 0x%llx, " 13937c478bd9Sstevel@tonic-gate "size 0x%llx\n", i, sp->sh_type, (u_longlong_t)load, 13947c478bd9Sstevel@tonic-gate (u_longlong_t)sp->sh_size); 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate /* force instructions to be visible to icache */ 13977c478bd9Sstevel@tonic-gate if (sp->sh_flags & SHF_EXECINSTR) 1398bcbe9155Sjg sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr, 13997c478bd9Sstevel@tonic-gate sp->sh_size); 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate /* 14027c478bd9Sstevel@tonic-gate * Update sizes of segments. 14037c478bd9Sstevel@tonic-gate */ 14047c478bd9Sstevel@tonic-gate thdr->p_memsz = etext - thdr->p_vaddr; 14057c478bd9Sstevel@tonic-gate dhdr->p_memsz = edata - dhdr->p_vaddr; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate /* load and relocate symbol tables in SAS */ 14087c478bd9Sstevel@tonic-gate (void) close(fd); 14097c478bd9Sstevel@tonic-gate return (dl_entry); 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate error: 14127c478bd9Sstevel@tonic-gate (void) close(fd); 14137c478bd9Sstevel@tonic-gate errorx: 14147c478bd9Sstevel@tonic-gate if (ehdr) 14157c478bd9Sstevel@tonic-gate kmem_free((caddr_t)ehdr, sizeof (Elf64_Ehdr)); 14167c478bd9Sstevel@tonic-gate if (shdrs) 14177c478bd9Sstevel@tonic-gate kmem_free(shdrs, size); 14187c478bd9Sstevel@tonic-gate printf("boot: error loading interpreter (%s)\n", rtld); 14197c478bd9Sstevel@tonic-gate return (FAIL_ILOAD64); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate #endif /* _ELF64_SUPPORT */ 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate /* 14247c478bd9Sstevel@tonic-gate * Extend the segment's "break" value by bytes. 14257c478bd9Sstevel@tonic-gate */ 14267c478bd9Sstevel@tonic-gate static caddr_t 14277c478bd9Sstevel@tonic-gate segbrk(caddr_t *spp, size_t bytes, size_t align) 14287c478bd9Sstevel@tonic-gate { 14297c478bd9Sstevel@tonic-gate caddr_t va, pva; 14307c478bd9Sstevel@tonic-gate size_t size = 0; 14317c478bd9Sstevel@tonic-gate unsigned int alloc_pagesize = pagesize; 14327c478bd9Sstevel@tonic-gate unsigned int alloc_align = 0; 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate if (npagesize) { 14357c478bd9Sstevel@tonic-gate alloc_align = npagesize; 14367c478bd9Sstevel@tonic-gate alloc_pagesize = npagesize; 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate va = (caddr_t)ALIGN(*spp, align); 14407c478bd9Sstevel@tonic-gate pva = (caddr_t)roundup((uintptr_t)*spp, alloc_pagesize); 14417c478bd9Sstevel@tonic-gate /* 14427c478bd9Sstevel@tonic-gate * Need more pages? 14437c478bd9Sstevel@tonic-gate */ 14447c478bd9Sstevel@tonic-gate if (va + bytes > pva) { 14457c478bd9Sstevel@tonic-gate size = roundup((bytes - (pva - va)), alloc_pagesize); 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if (get_progmemory(pva, size, alloc_align)) { 14487c478bd9Sstevel@tonic-gate printf("boot: segbrk allocation failed, " 14497c478bd9Sstevel@tonic-gate "0x%lx bytes @ %p\n", bytes, (void *)pva); 14507c478bd9Sstevel@tonic-gate return (NULL); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate } 14537c478bd9Sstevel@tonic-gate *spp = va + bytes; 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate return (va); 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate /* 14597c478bd9Sstevel@tonic-gate * Open the file using a search path and 14607c478bd9Sstevel@tonic-gate * return the file descriptor (or -1 on failure). 14617c478bd9Sstevel@tonic-gate */ 14627c478bd9Sstevel@tonic-gate static int 14637c478bd9Sstevel@tonic-gate openpath(path, fname, flags) 14647c478bd9Sstevel@tonic-gate char *path; 14657c478bd9Sstevel@tonic-gate char *fname; 14667c478bd9Sstevel@tonic-gate int flags; 14677c478bd9Sstevel@tonic-gate { 14687c478bd9Sstevel@tonic-gate register char *p, *q; 14697c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 14707c478bd9Sstevel@tonic-gate int fd; 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* 14737c478bd9Sstevel@tonic-gate * If the file name is absolute, 14747c478bd9Sstevel@tonic-gate * don't use the module search path. 14757c478bd9Sstevel@tonic-gate */ 14767c478bd9Sstevel@tonic-gate if (fname[0] == '/') 14777c478bd9Sstevel@tonic-gate return (open(fname, flags)); 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate q = NULL; 14807c478bd9Sstevel@tonic-gate for (p = path; /* forever */; p = q) { 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate while (*p == ' ' || *p == '\t' || *p == ':') 14837c478bd9Sstevel@tonic-gate p++; 14847c478bd9Sstevel@tonic-gate if (*p == '\0') 14857c478bd9Sstevel@tonic-gate break; 14867c478bd9Sstevel@tonic-gate q = p; 14877c478bd9Sstevel@tonic-gate while (*q && *q != ' ' && *q != '\t' && *q != ':') 14887c478bd9Sstevel@tonic-gate q++; 14897c478bd9Sstevel@tonic-gate (void) strncpy(buf, p, q - p); 14907c478bd9Sstevel@tonic-gate if (q[-1] != '/') { 14917c478bd9Sstevel@tonic-gate buf[q - p] = '/'; 14927c478bd9Sstevel@tonic-gate (void) strcpy(&buf[q - p + 1], fname); 14937c478bd9Sstevel@tonic-gate } else { 14947c478bd9Sstevel@tonic-gate /* 14957c478bd9Sstevel@tonic-gate * This checks for paths that end in '/' 14967c478bd9Sstevel@tonic-gate */ 14977c478bd9Sstevel@tonic-gate (void) strcpy(&buf[q - p], fname); 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate if ((fd = open(buf, flags)) > 0) 15017c478bd9Sstevel@tonic-gate return (fd); 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate return (-1); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate /* 15077c478bd9Sstevel@tonic-gate * Get the module search path. 15087c478bd9Sstevel@tonic-gate */ 15097c478bd9Sstevel@tonic-gate static char * 15107c478bd9Sstevel@tonic-gate getmodpath(fname) 15117c478bd9Sstevel@tonic-gate char *fname; 15127c478bd9Sstevel@tonic-gate { 15137c478bd9Sstevel@tonic-gate register char *p = strrchr(fname, '/'); 15147c478bd9Sstevel@tonic-gate static char mod_path[MOD_MAXPATH]; 15157c478bd9Sstevel@tonic-gate size_t len; 15167c478bd9Sstevel@tonic-gate extern char *impl_arch_name; 1517c2e7b48dSkalai #if defined(__sparcv9) || defined(BOOTAMD64) 15187c478bd9Sstevel@tonic-gate #ifdef __sparcv9 15197c478bd9Sstevel@tonic-gate char *isastr = "/sparcv9"; 15207c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 15217c478bd9Sstevel@tonic-gate #ifdef BOOTAMD64 15227c478bd9Sstevel@tonic-gate char *isastr = "/amd64"; 15237c478bd9Sstevel@tonic-gate #endif /* BOOTAMD64 */ 15247c478bd9Sstevel@tonic-gate size_t isalen = strlen(isastr); 1525c2e7b48dSkalai #endif /* __sparcv9 || BOOTAMD64 */ 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate if (p == NULL) { 15287c478bd9Sstevel@tonic-gate /* strchr could not find a "/" */ 15297c478bd9Sstevel@tonic-gate printf("%s is not a legal kernel pathname", fname); 15307c478bd9Sstevel@tonic-gate return (NULL); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate while (p > fname && *(p - 1) == '/') 15337c478bd9Sstevel@tonic-gate p--; /* remove trailing "/"s */ 15347c478bd9Sstevel@tonic-gate if (p == fname) 15357c478bd9Sstevel@tonic-gate p++; /* "/" is the modpath in this case */ 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate len = p - fname; 15387c478bd9Sstevel@tonic-gate (void) strncpy(mod_path, fname, len); 15397c478bd9Sstevel@tonic-gate mod_path[len] = 0; 15407c478bd9Sstevel@tonic-gate 1541c2e7b48dSkalai #if defined(__sparcv9) || defined(BOOTAMD64) 15427c478bd9Sstevel@tonic-gate len = strlen(mod_path); 15437c478bd9Sstevel@tonic-gate if ((len > isalen) && (strcmp(&mod_path[len - isalen], isastr) == 0)) { 15447c478bd9Sstevel@tonic-gate mod_path[len - isalen] = '\0'; 1545c2e7b48dSkalai #if defined(__sparcv9) 15467c478bd9Sstevel@tonic-gate if ((client_isLP64 == 0) && verbosemode) 15477c478bd9Sstevel@tonic-gate printf("Assuming LP64 %s client.\n", isastr); 15487c478bd9Sstevel@tonic-gate client_isLP64 = 1; 1549c2e7b48dSkalai #endif /* __sparcv9 */ 15507c478bd9Sstevel@tonic-gate } 1551c2e7b48dSkalai #endif /* __sparcv9 || BOOTAMD64 */ 15527c478bd9Sstevel@tonic-gate mod_path_uname_m(mod_path, impl_arch_name); 15537c478bd9Sstevel@tonic-gate (void) strcat(mod_path, " "); 15547c478bd9Sstevel@tonic-gate (void) strcat(mod_path, MOD_DEFPATH); 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 15577c478bd9Sstevel@tonic-gate char buf[MOD_MAXPATH]; 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate printf("Enter default directory for modules [%s]: ", mod_path); 15607c478bd9Sstevel@tonic-gate (void) cons_gets(buf, sizeof (buf)); 15617c478bd9Sstevel@tonic-gate if (buf[0] != '\0') 15627c478bd9Sstevel@tonic-gate (void) strcpy(mod_path, buf); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate if (verbosemode) 15657c478bd9Sstevel@tonic-gate printf("modpath: %s\n", mod_path); 15667c478bd9Sstevel@tonic-gate return (mod_path); 15677c478bd9Sstevel@tonic-gate } 1568