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 "@(#)cook.c 1.20 08/05/31 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 93Dnode * 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 111int 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 162Okay 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 && elf->ed_kind != ELF_K_MACHO) 169 return (OK_YES); 170 171 if (elf->ed_kind == ELF_K_MACHO) 172 inplace = 0; /* Ensures ident structure gets fresh storage */ 173 174 if ((elf->ed_status == ES_COOKED) || 175 ((elf->ed_myflags & EDF_READ) == 0)) 176 return (OK_YES); 177 178 /* 179 * Here's where the unaligned archive member gets fixed. 180 */ 181 if (elf->ed_status == ES_FRESH && _elf_slide(elf) != 0) 182 return (OK_NO); 183 184 if (elf->ed_status == ES_FROZEN) 185 inplace = 0; 186 187 /* 188 * This is the first time we've actually looked at the file 189 * contents. We need to know whether or not this is an 190 * Elf32 or Elf64 file before we can decode the header. 191 * But it's the header that tells us which is which. 192 * 193 * Resolve the chicken-and-egg problem by peeking at the 194 * 'class' byte in the ident string. 195 */ 196 if (elf->ed_ident[EI_CLASS] == ELFCLASS32) { 197 if (_elf32_ehdr(elf, inplace) != 0) 198 return (OK_NO); 199 if (_elf32_phdr(elf, inplace) != 0) 200 goto xehdr; 201 if (_elf32_shdr(elf, inplace) != 0) 202 goto xphdr; 203 elf->ed_class = ELFCLASS32; 204 } else if (elf->ed_ident[EI_CLASS] == ELFCLASS64) { 205 if (_elf64_ehdr(elf, inplace) != 0) 206 return (OK_NO); 207 if (_elf64_phdr(elf, inplace) != 0) 208 goto xehdr; 209 if (_elf64_shdr(elf, inplace) != 0) 210 goto xphdr; 211 elf->ed_class = ELFCLASS64; 212 } else 213 return (OK_NO); 214 215 return (OK_YES); 216 217xphdr: 218 if (elf->ed_myflags & EDF_PHALLOC) { 219 elf->ed_myflags &= ~EDF_PHALLOC; 220 free(elf->ed_phdr); 221 } 222 elf->ed_phdr = 0; 223xehdr: 224 if (elf->ed_myflags & EDF_EHALLOC) { 225 elf->ed_myflags &= ~EDF_EHALLOC; 226 free(elf->ed_ehdr); 227 } 228 elf->ed_ehdr = 0; 229 230 return (OK_NO); 231} 232 233 234Okay 235_elf_cookscn(Elf_Scn * s) 236{ 237 Elf * elf = s->s_elf; 238 239 if (elf->ed_class == ELFCLASS32) { 240 return (_elf32_cookscn(s)); 241 } else if (elf->ed_class == ELFCLASS64) { 242 return (_elf64_cookscn(s)); 243 } 244 245 _elf_seterr(EREQ_CLASS, 0); 246 return (OK_NO); 247} 248