1164190Sjkoshy/*- 2164190Sjkoshy * Copyright (c) 2006 Joseph Koshy 3164190Sjkoshy * All rights reserved. 4164190Sjkoshy * 5164190Sjkoshy * Redistribution and use in source and binary forms, with or without 6164190Sjkoshy * modification, are permitted provided that the following conditions 7164190Sjkoshy * are met: 8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright 9164190Sjkoshy * notice, this list of conditions and the following disclaimer. 10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11164190Sjkoshy * notice, this list of conditions and the following disclaimer in the 12164190Sjkoshy * documentation and/or other materials provided with the distribution. 13164190Sjkoshy * 14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17164190Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24164190Sjkoshy * SUCH DAMAGE. 25164190Sjkoshy */ 26164190Sjkoshy 27164190Sjkoshy#include <sys/cdefs.h> 28164190Sjkoshy__FBSDID("$FreeBSD$"); 29164190Sjkoshy 30164190Sjkoshy#include <sys/types.h> 31164190Sjkoshy#include <sys/errno.h> 32164190Sjkoshy#include <sys/mman.h> 33164190Sjkoshy#include <sys/stat.h> 34164190Sjkoshy 35164190Sjkoshy#include <ar.h> 36164190Sjkoshy#include <ctype.h> 37164190Sjkoshy#include <libelf.h> 38210329Skaiw#include <unistd.h> 39164190Sjkoshy 40164190Sjkoshy#include "_libelf.h" 41164190Sjkoshy 42164190Sjkoshystatic Elf * 43164190Sjkoshy_libelf_open_object(int fd, Elf_Cmd c) 44164190Sjkoshy{ 45164190Sjkoshy Elf *e; 46164190Sjkoshy void *m; 47164190Sjkoshy struct stat sb; 48164190Sjkoshy 49164190Sjkoshy /* 50164190Sjkoshy * 'Raw' files are always mapped with 'PROT_READ'. At 51164190Sjkoshy * elf_update(3) time for files opened with ELF_C_RDWR the 52164190Sjkoshy * mapping is unmapped, file data is written to using write(2) 53164190Sjkoshy * and then the raw data is immediately mapped back in. 54164190Sjkoshy */ 55164190Sjkoshy if (fstat(fd, &sb) < 0) { 56164190Sjkoshy LIBELF_SET_ERROR(IO, errno); 57164190Sjkoshy return (NULL); 58164190Sjkoshy } 59164190Sjkoshy 60164190Sjkoshy m = NULL; 61164190Sjkoshy if ((m = mmap(NULL, (size_t) sb.st_size, PROT_READ, MAP_PRIVATE, fd, 62164190Sjkoshy (off_t) 0)) == MAP_FAILED) { 63164190Sjkoshy LIBELF_SET_ERROR(IO, errno); 64164190Sjkoshy return (NULL); 65164190Sjkoshy } 66164190Sjkoshy 67164190Sjkoshy if ((e = elf_memory(m, (size_t) sb.st_size)) == NULL) { 68164190Sjkoshy (void) munmap(m, (size_t) sb.st_size); 69164190Sjkoshy return (NULL); 70164190Sjkoshy } 71164190Sjkoshy 72164190Sjkoshy e->e_flags |= LIBELF_F_MMAP; 73164190Sjkoshy e->e_fd = fd; 74164190Sjkoshy e->e_cmd = c; 75164190Sjkoshy 76164190Sjkoshy if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) { 77164190Sjkoshy (void) elf_end(e); 78164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 79164190Sjkoshy return (NULL); 80164190Sjkoshy } 81164190Sjkoshy 82164190Sjkoshy return (e); 83164190Sjkoshy} 84164190Sjkoshy 85164190SjkoshyElf * 86164190Sjkoshyelf_begin(int fd, Elf_Cmd c, Elf *a) 87164190Sjkoshy{ 88164190Sjkoshy Elf *e; 89164190Sjkoshy 90164190Sjkoshy e = NULL; 91164190Sjkoshy 92164190Sjkoshy if (LIBELF_PRIVATE(version) == EV_NONE) { 93164190Sjkoshy LIBELF_SET_ERROR(SEQUENCE, 0); 94164190Sjkoshy return (NULL); 95164190Sjkoshy } 96164190Sjkoshy 97164190Sjkoshy switch (c) { 98164190Sjkoshy case ELF_C_NULL: 99164190Sjkoshy return (NULL); 100164190Sjkoshy 101164190Sjkoshy case ELF_C_WRITE: 102164190Sjkoshy 103164190Sjkoshy if (a != NULL) { /* not allowed for ar(1) archives. */ 104164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 105164190Sjkoshy return (NULL); 106164190Sjkoshy } 107164190Sjkoshy 108164190Sjkoshy /* 109164190Sjkoshy * Check writeability of `fd' immediately and fail if 110164190Sjkoshy * not writeable. 111164190Sjkoshy */ 112164190Sjkoshy if (ftruncate(fd, (off_t) 0) < 0) { 113164190Sjkoshy LIBELF_SET_ERROR(IO, errno); 114164190Sjkoshy return (NULL); 115164190Sjkoshy } 116164190Sjkoshy 117164190Sjkoshy if ((e = _libelf_allocate_elf()) != NULL) { 118164190Sjkoshy _libelf_init_elf(e, ELF_K_ELF); 119164190Sjkoshy e->e_byteorder = LIBELF_PRIVATE(byteorder); 120164190Sjkoshy e->e_fd = fd; 121164190Sjkoshy e->e_cmd = c; 122164190Sjkoshy } 123164190Sjkoshy return (e); 124164190Sjkoshy 125164190Sjkoshy case ELF_C_RDWR: 126164190Sjkoshy if (a != NULL) { /* not allowed for ar(1) archives. */ 127164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 128164190Sjkoshy return (NULL); 129164190Sjkoshy } 130164190Sjkoshy /*FALLTHROUGH*/ 131164190Sjkoshy case ELF_C_READ: 132164190Sjkoshy /* 133164190Sjkoshy * Descriptor `a' could be for a regular ELF file, or 134210351Skaiw * for an ar(1) archive. If descriptor `a' was opened 135210351Skaiw * using a valid file descriptor, we need to check if 136210351Skaiw * the passed in `fd' value matches the original one. 137164190Sjkoshy */ 138210351Skaiw if (a && 139210351Skaiw ((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) { 140164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 141164190Sjkoshy return (NULL); 142164190Sjkoshy } 143164190Sjkoshy break; 144164190Sjkoshy 145164190Sjkoshy default: 146164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 147164190Sjkoshy return (NULL); 148164190Sjkoshy 149164190Sjkoshy } 150164190Sjkoshy 151164190Sjkoshy if (a == NULL) 152164190Sjkoshy e = _libelf_open_object(fd, c); 153164190Sjkoshy else if (a->e_kind == ELF_K_AR) 154210351Skaiw e = _libelf_ar_open_member(a->e_fd, c, a); 155164190Sjkoshy else 156164190Sjkoshy (e = a)->e_activations++; 157164190Sjkoshy 158164190Sjkoshy return (e); 159164190Sjkoshy} 160