1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <string.h> 33 #include <ar.h> 34 #include <stdlib.h> 35 #include <sys/mman.h> 36 #include <errno.h> 37 #include <libelf.h> 38 #include "decl.h" 39 #include "member.h" 40 #include "msg.h" 41 42 #include <sys/mman.h> 43 44 /* 45 * Cook the input file. 46 * These functions take the input file buffer and extract 47 * the Ehdr, Phdr table, and the Shdr table. They keep track 48 * of the buffer status as "fresh," "cooked," or "frozen." 49 * 50 * fresh The file buffer is in its original state and 51 * nothing has yet referenced it. 52 * 53 * cooked The application asked for translated data first 54 * and caused the library to return a pointer into 55 * the file buffer. After this happens, all "raw" 56 * operations must go back to the disk. 57 * 58 * frozen The application first did a "raw" operation that 59 * prohibits reusing the file buffer. This effectively 60 * freezes the buffer, and all "normal" operations must 61 * duplicate their data. 62 * 63 * For archive handling, these functions conspire to align the 64 * file buffer to the host memory format. Archive members 65 * are guaranteed only even byte alignment, but the file uses 66 * objects at least 4 bytes long. If an archive member is about 67 * to be cooked and is not aligned in memory, these functions 68 * "slide" the buffer up into the archive member header. 69 * This sliding never occurs for frozen files. 70 * 71 * Some processors might not need sliding at all, if they have 72 * no alignment constraints on memory references. This code 73 * ignores that possibility for two reasons. First, even machines 74 * that have no constraints usually handle aligned objects faster 75 * than unaligned. Forcing alignment here probably leads to better 76 * performance. Second, there's no way to test at run time whether 77 * alignment is required or not. The safe thing is to align in 78 * all cases. 79 * 80 * This sliding relies on the archive header being disposable. 81 * Only archive members that are object files ever slide. 82 * They're also the only ones that ever need to. Archives never 83 * freeze to make headers disposable. Any program peculiar enough 84 * to want a frozen archive pays the penalty. 85 * 86 * The library itself inspects the Ehdr and the Shdr table 87 * from the file. Consequently, it converts the file's data 88 * to EV_CURRENT version, not the working version. This is 89 * transparent to the user. The library never looks at the 90 * Phdr table; so that's kept in the working version. 91 */ 92 93 Dnode * 94 _elf_dnode() 95 { 96 register Dnode *d; 97 98 if ((d = (Dnode *)malloc(sizeof (Dnode))) == 0) { 99 _elf_seterr(EMEM_DNODE, errno); 100 return (0); 101 } 102 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d)) 103 *d = _elf_dnode_init; 104 d->db_myflags = DBF_ALLOC; 105 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d)) 106 return (d); 107 } 108 109 110 111 int 112 _elf_slide(Elf * elf) 113 { 114 NOTE(ASSUMING_PROTECTED(*elf)) 115 Elf *par = elf->ed_parent; 116 size_t sz, szof; 117 register char *dst; 118 register char *src = elf->ed_ident; 119 120 if (par == 0 || par->ed_kind != ELF_K_AR) 121 return (0); 122 123 /* 124 * This code relies on other code to ensure 125 * the ar_hdr is big enough to move into. 126 */ 127 if (elf->ed_ident[EI_CLASS] == ELFCLASS64) 128 szof = sizeof (Elf64); 129 else 130 szof = sizeof (Elf32); 131 if ((sz = (size_t)(src - (char *)elf->ed_image) % szof) == 0) 132 return (0); 133 dst = src - sz; 134 elf->ed_ident -= sz; 135 elf->ed_memoff -= sz; 136 elf->ed_armem->m_slide = sz; 137 if (_elf_vm(par, elf->ed_memoff, sz + elf->ed_fsz) != OK_YES) 138 return (-1); 139 140 /* 141 * If the archive has been mmaped in, and we're going to slide it, 142 * and it wasn't open for write in the first place, and we've never 143 * done the mprotect() operation before, then do it now. 144 */ 145 if ((elf->ed_vm == 0) && ((elf->ed_myflags & EDF_WRITE) == 0) && 146 ((elf->ed_myflags & EDF_MPROTECT) == 0)) { 147 if (mprotect((char *)elf->ed_image, elf->ed_imagesz, 148 PROT_READ|PROT_WRITE) == -1) { 149 _elf_seterr(EIO_VM, errno); 150 return (-1); 151 } 152 elf->ed_myflags |= EDF_MPROTECT; 153 } 154 155 if (memmove((void *)dst, (const void *)src, elf->ed_fsz) != (void *)dst) 156 return (-1); 157 else 158 return (0); 159 } 160 161 162 Okay 163 _elf_cook(Elf * elf) 164 { 165 NOTE(ASSUMING_PROTECTED(*elf)) 166 register int inplace = 1; 167 168 if (elf->ed_kind != ELF_K_ELF) 169 return (OK_YES); 170 171 if ((elf->ed_status == ES_COOKED) || 172 ((elf->ed_myflags & EDF_READ) == 0)) 173 return (OK_YES); 174 175 /* 176 * Here's where the unaligned archive member gets fixed. 177 */ 178 if (elf->ed_status == ES_FRESH && _elf_slide(elf) != 0) 179 return (OK_NO); 180 181 if (elf->ed_status == ES_FROZEN) 182 inplace = 0; 183 184 /* 185 * This is the first time we've actually looked at the file 186 * contents. We need to know whether or not this is an 187 * Elf32 or Elf64 file before we can decode the header. 188 * But it's the header that tells us which is which. 189 * 190 * Resolve the chicken-and-egg problem by peeking at the 191 * 'class' byte in the ident string. 192 */ 193 if (elf->ed_ident[EI_CLASS] == ELFCLASS32) { 194 if (_elf32_ehdr(elf, inplace) != 0) 195 return (OK_NO); 196 if (_elf32_phdr(elf, inplace) != 0) 197 goto xehdr; 198 if (_elf32_shdr(elf, inplace) != 0) 199 goto xphdr; 200 elf->ed_class = ELFCLASS32; 201 } else if (elf->ed_ident[EI_CLASS] == ELFCLASS64) { 202 if (_elf64_ehdr(elf, inplace) != 0) 203 return (OK_NO); 204 if (_elf64_phdr(elf, inplace) != 0) 205 goto xehdr; 206 if (_elf64_shdr(elf, inplace) != 0) 207 goto xphdr; 208 elf->ed_class = ELFCLASS64; 209 } else 210 return (OK_NO); 211 212 return (OK_YES); 213 214 xphdr: 215 if (elf->ed_myflags & EDF_PHALLOC) { 216 elf->ed_myflags &= ~EDF_PHALLOC; 217 free(elf->ed_phdr); 218 } 219 elf->ed_phdr = 0; 220 xehdr: 221 if (elf->ed_myflags & EDF_EHALLOC) { 222 elf->ed_myflags &= ~EDF_EHALLOC; 223 free(elf->ed_ehdr); 224 } 225 elf->ed_ehdr = 0; 226 227 return (OK_NO); 228 } 229 230 231 Okay 232 _elf_cookscn(Elf_Scn * s) 233 { 234 Elf * elf = s->s_elf; 235 236 if (elf->ed_class == ELFCLASS32) { 237 return (_elf32_cookscn(s)); 238 } else if (elf->ed_class == ELFCLASS64) { 239 return (_elf64_cookscn(s)); 240 } 241 242 _elf_seterr(EREQ_CLASS, 0); 243 return (OK_NO); 244 } 245