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 * 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 * 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 * 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 * 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 * 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