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 /*
28 * Copyright (c) 1988 AT&T
29 * All Rights Reserved
30 */
31
32 #include <ar.h>
33 #include <stdlib.h>
34 #include <memory.h>
35 #include <errno.h>
36 #include <libelf.h>
37 #include <sys/mman.h>
38 #include "decl.h"
39 #include "member.h"
40 #include "msg.h"
41
42 static const char armag[] = ARMAG;
43
44
45 /*
46 * Initialize archive member
47 */
48 Elf *
_elf_member(int fd,Elf * ref,unsigned flags)49 _elf_member(int fd, Elf * ref, unsigned flags)
50 {
51 register Elf *elf;
52 Member *mh;
53 size_t base;
54
55 if (ref->ed_nextoff >= ref->ed_fsz)
56 return (0);
57 if (ref->ed_fd == -1) /* disabled */
58 fd = -1;
59 if (flags & EDF_WRITE) {
60 _elf_seterr(EREQ_ARRDWR, 0);
61 return (0);
62 }
63 if (ref->ed_fd != fd) {
64 _elf_seterr(EREQ_ARMEMFD, 0);
65 return (0);
66 }
67 if ((_elf_vm(ref, ref->ed_nextoff, sizeof (struct ar_hdr)) !=
68 OK_YES) || ((mh = _elf_armem(ref,
69 ref->ed_ident + ref->ed_nextoff, ref->ed_fsz)) == 0))
70 return (0);
71
72 base = ref->ed_nextoff + sizeof (struct ar_hdr);
73 if (ref->ed_fsz - base < mh->m_hdr.ar_size) {
74 _elf_seterr(EFMT_ARMEMSZ, 0);
75 return (0);
76 }
77 if ((elf = (Elf *)calloc(1, sizeof (Elf))) == 0) {
78 _elf_seterr(EMEM_ELF, errno);
79 return (0);
80 }
81 ++ref->ed_activ;
82 elf->ed_parent = ref;
83 elf->ed_fd = fd;
84 elf->ed_myflags |= flags;
85 elf->ed_armem = mh;
86 elf->ed_fsz = mh->m_hdr.ar_size;
87 elf->ed_baseoff = ref->ed_baseoff + base;
88 elf->ed_memoff = base - mh->m_slide;
89 elf->ed_siboff = base + elf->ed_fsz + (elf->ed_fsz & 1);
90 ref->ed_nextoff = elf->ed_siboff;
91 elf->ed_image = ref->ed_image;
92 elf->ed_imagesz = ref->ed_imagesz;
93 elf->ed_vm = ref->ed_vm;
94 elf->ed_vmsz = ref->ed_vmsz;
95 elf->ed_ident = ref->ed_ident + base - mh->m_slide;
96
97 /*
98 * If this member is the archive string table,
99 * we've already altered the bytes.
100 */
101
102 if (ref->ed_arstroff == ref->ed_nextoff)
103 elf->ed_status = ES_COOKED;
104 return (elf);
105 }
106
107
108 Elf *
_elf_regular(int fd,unsigned flags)109 _elf_regular(int fd, unsigned flags) /* initialize regular file */
110 {
111 Elf *elf;
112
113 if ((elf = (Elf *)calloc(1, sizeof (Elf))) == 0) {
114 _elf_seterr(EMEM_ELF, errno);
115 return (0);
116 }
117
118 elf->ed_fd = fd;
119 elf->ed_myflags |= flags;
120 if (_elf_inmap(elf) != OK_YES) {
121 free(elf);
122 return (0);
123 }
124 return (elf);
125 }
126
127
128 Elf *
_elf_config(Elf * elf)129 _elf_config(Elf * elf)
130 {
131 char *base;
132 unsigned encode;
133
134 ELFRWLOCKINIT(&elf->ed_rwlock);
135
136 /*
137 * Determine if this is a ELF file.
138 */
139 base = elf->ed_ident;
140 if ((elf->ed_fsz >= EI_NIDENT) &&
141 (_elf_vm(elf, (size_t)0, (size_t)EI_NIDENT) == OK_YES) &&
142 (base[EI_MAG0] == ELFMAG0) &&
143 (base[EI_MAG1] == ELFMAG1) &&
144 (base[EI_MAG2] == ELFMAG2) &&
145 (base[EI_MAG3] == ELFMAG3)) {
146 elf->ed_kind = ELF_K_ELF;
147 elf->ed_class = base[EI_CLASS];
148 elf->ed_encode = base[EI_DATA];
149 if ((elf->ed_version = base[EI_VERSION]) == 0)
150 elf->ed_version = 1;
151 elf->ed_identsz = EI_NIDENT;
152
153 /*
154 * Allow writing only if originally specified read only.
155 * This is only necessary if the file must be translating
156 * from one encoding to another.
157 */
158 ELFACCESSDATA(encode, _elf_encode)
159 if ((elf->ed_vm == 0) && ((elf->ed_myflags & EDF_WRITE) == 0) &&
160 (elf->ed_encode != encode)) {
161 if (mprotect((char *)elf->ed_image, elf->ed_imagesz,
162 PROT_READ|PROT_WRITE) == -1) {
163 _elf_seterr(EIO_VM, errno);
164 return (0);
165 }
166 }
167 return (elf);
168 }
169
170 /*
171 * Determine if this is an Archive
172 */
173 if ((elf->ed_fsz >= SARMAG) &&
174 (_elf_vm(elf, (size_t)0, (size_t)SARMAG) == OK_YES) &&
175 (memcmp(base, armag, SARMAG) == 0)) {
176 _elf_arinit(elf);
177 elf->ed_kind = ELF_K_AR;
178 elf->ed_identsz = SARMAG;
179 return (elf);
180 }
181
182 /*
183 * Return a few ident bytes, but not so many that
184 * getident() must read a large file. 512 is arbitrary.
185 */
186
187 elf->ed_kind = ELF_K_NONE;
188 if ((elf->ed_identsz = elf->ed_fsz) > 512)
189 elf->ed_identsz = 512;
190
191 return (elf);
192 }
193
194 Elf *
elf_memory(char * image,size_t sz)195 elf_memory(char *image, size_t sz)
196 {
197 Elf *elf;
198 unsigned work;
199
200 /*
201 * version() no called yet?
202 */
203 ELFACCESSDATA(work, _elf_work)
204 if (work == EV_NONE) {
205 _elf_seterr(ESEQ_VER, 0);
206 return (0);
207 }
208
209 if ((elf = (Elf *)calloc(1, sizeof (Elf))) == 0) {
210 _elf_seterr(EMEM_ELF, errno);
211 return (0);
212 }
213 elf->ed_fd = -1;
214 elf->ed_myflags |= EDF_READ | EDF_MEMORY;
215 elf->ed_image = elf->ed_ident = image;
216 elf->ed_imagesz = elf->ed_fsz = elf->ed_identsz = sz;
217 elf->ed_kind = ELF_K_ELF;
218 elf->ed_class = image[EI_CLASS];
219 elf->ed_encode = image[EI_DATA];
220 if ((elf->ed_version = image[EI_VERSION]) == 0)
221 elf->ed_version = 1;
222 elf->ed_identsz = EI_NIDENT;
223 elf->ed_activ = 1;
224 elf = _elf_config(elf);
225 return (elf);
226 }
227
228 /*
229 * The following is a private interface between the linkers (ld & ld.so.1)
230 * and libelf.
231 *
232 * elf_begin(0, ELF_C_IMAGE, ref)
233 * Return a new elf_descriptor which uses the memory image from
234 * ref as the base image of the elf file. Before this elf_begin()
235 * is called an elf_update(ref, ELF_C_WRIMAGE) must have been
236 * done to the ref elf descriptor.
237 * The ELF_C_IMAGE is unique in that modificatino of the Elf structure
238 * is illegal (no elf_new*()) but you can modify the actual
239 * data image of the file in question.
240 *
241 * When you are done processing this file you can then perform a
242 * elf_end() on it.
243 *
244 * NOTE: if an elf_update(ref, ELF_C_WRITE) is done on the ref Elf
245 * descriptor then the memory image that the ELF_C_IMAGE
246 * is using has been discarded. The proper calling convention
247 * for this is as follows:
248 *
249 * elf1 = elf_begin(fd, ELF_C_WRITE, 0);
250 * ...
251 * elf_update(elf1, ELF_C_WRIMAGE); build memory image
252 * elf2 = elf_begin(0, ELF_C_IMAGE, elf1);
253 * ...
254 * elf_end(elf2);
255 * elf_updage(elf1, ELF_C_WRITE); flush memory image to disk
256 * elf_end(elf1);
257 *
258 *
259 * elf_begin(0, ELF_C_IMAGE, 0);
260 * returns a pointer to an elf descriptor as if it were opened
261 * with ELF_C_WRITE except that it has no file descriptor and it
262 * will not create a file. It's to be used with the command:
263 *
264 * elf_update(elf, ELF_C_WRIMAGE)
265 *
266 * which will build a memory image instead of a file image.
267 * The memory image is allocated via dynamic memory (malloc) and
268 * can be free with a subsequent call to
269 *
270 * elf_update(elf, ELF_C_WRITE)
271 *
272 * NOTE: that if elf_end(elf) is called it will not free the
273 * memory image if it is still allocated. It is then
274 * the callers responsiblity to free it via a call
275 * to free().
276 *
277 * Here is a potential calling sequence for this interface:
278 *
279 * elf1 = elf_begin(0, ELF_C_IMAGE, 0);
280 * ...
281 * elf_update(elf1, ELF_C_WRIMAGE); build memory image
282 * elf2 = elf_begin(0, ELF_C_IMAGE, elf1);
283 * ...
284 * image_ptr = elf32_getehdr(elf2); get pointer to image
285 * elf_end(elf2);
286 * elf_end(elf1);
287 * ...
288 * use image
289 * ...
290 * free(image_ptr);
291 */
292
293 Elf *
elf_begin(int fd,Elf_Cmd cmd,Elf * ref)294 elf_begin(int fd, Elf_Cmd cmd, Elf *ref)
295 {
296 register Elf *elf;
297 unsigned work;
298 unsigned flags = 0;
299
300 ELFACCESSDATA(work, _elf_work)
301 if (work == EV_NONE) /* version() not called yet */
302 {
303 _elf_seterr(ESEQ_VER, 0);
304 return (0);
305 }
306 switch (cmd) {
307 default:
308 _elf_seterr(EREQ_BEGIN, 0);
309 return (0);
310
311 case ELF_C_NULL:
312 return (0);
313
314 case ELF_C_IMAGE:
315 if (ref) {
316 char *image;
317 size_t imagesz;
318 ELFRLOCK(ref);
319 if ((image = ref->ed_wrimage) == 0) {
320 _elf_seterr(EREQ_NOWRIMAGE, 0);
321 ELFUNLOCK(ref);
322 return (0);
323 }
324 imagesz = ref->ed_wrimagesz;
325 ELFUNLOCK(ref);
326 return (elf_memory(image, imagesz));
327 }
328 /* FALLTHROUGH */
329 case ELF_C_WRITE:
330 if ((elf = (Elf *)calloc(1, sizeof (Elf))) == 0) {
331 _elf_seterr(EMEM_ELF, errno);
332 return (0);
333 }
334 ELFRWLOCKINIT(&elf->ed_rwlock);
335 elf->ed_fd = fd;
336 elf->ed_activ = 1;
337 elf->ed_myflags |= EDF_WRITE;
338 if (cmd == ELF_C_IMAGE)
339 elf->ed_myflags |= EDF_WRALLOC;
340 return (elf);
341 case ELF_C_RDWR:
342 flags = EDF_WRITE | EDF_READ;
343 break;
344
345 case ELF_C_READ:
346 flags = EDF_READ;
347 break;
348 }
349
350 /*
351 * A null ref asks for a new file
352 * Non-null ref bumps the activation count
353 * or gets next archive member
354 */
355
356 if (ref == 0) {
357 if ((elf = _elf_regular(fd, flags)) == 0)
358 return (0);
359 } else {
360 ELFWLOCK(ref);
361 if ((ref->ed_myflags & flags) != flags) {
362 _elf_seterr(EREQ_RDWR, 0);
363 ELFUNLOCK(ref);
364 return (0);
365 }
366 /*
367 * new activation ?
368 */
369 if (ref->ed_kind != ELF_K_AR) {
370 ++ref->ed_activ;
371 ELFUNLOCK(ref);
372 return (ref);
373 }
374 if ((elf = _elf_member(fd, ref, flags)) == 0) {
375 ELFUNLOCK(ref);
376 return (0);
377 }
378 ELFUNLOCK(ref);
379 }
380
381 elf->ed_activ = 1;
382 elf = _elf_config(elf);
383
384 return (elf);
385 }
386