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