1/* Read all of the file associated with the descriptor. 2 Copyright (C) 1998-2009, 2015 Red Hat, Inc. 3 This file is part of elfutils. 4 Contributed by Ulrich Drepper <drepper@redhat.com>, 1998. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of either 8 9 * the GNU Lesser General Public License as published by the Free 10 Software Foundation; either version 3 of the License, or (at 11 your option) any later version 12 13 or 14 15 * the GNU General Public License as published by the Free 16 Software Foundation; either version 2 of the License, or (at 17 your option) any later version 18 19 or both in parallel, as here. 20 21 elfutils is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received copies of the GNU General Public License and 27 the GNU Lesser General Public License along with this program. If 28 not, see <http://www.gnu.org/licenses/>. */ 29 30#ifdef HAVE_CONFIG_H 31# include <config.h> 32#endif 33 34#include <errno.h> 35#include <sys/stat.h> 36 37#include "libelfP.h" 38#include "common.h" 39 40 41static void 42set_address (Elf *elf, size_t offset) 43{ 44 if (elf->kind == ELF_K_AR) 45 { 46 Elf *child = elf->state.ar.children; 47 48 while (child != NULL) 49 { 50 if (child->map_address == NULL) 51 { 52 child->map_address = elf->map_address; 53 child->start_offset -= offset; 54 if (child->kind == ELF_K_AR) 55 child->state.ar.offset -= offset; 56 57 set_address (child, offset); 58 } 59 60 child = child->next; 61 } 62 } 63} 64 65 66char * 67internal_function 68__libelf_readall (Elf *elf) 69{ 70 /* Get the file. */ 71 rwlock_wrlock (elf->lock); 72 73 if (elf->map_address == NULL && unlikely (elf->fildes == -1)) 74 { 75 __libelf_seterrno (ELF_E_INVALID_HANDLE); 76 rwlock_unlock (elf->lock); 77 return NULL; 78 } 79 80 /* If the file is not mmap'ed and not previously loaded, do it now. */ 81 if (elf->map_address == NULL) 82 { 83 char *mem = NULL; 84 85 /* If this is an archive and we have derived descriptors get the 86 locks for all of them. */ 87 libelf_acquire_all (elf); 88 89 if (elf->maximum_size == ~((size_t) 0)) 90 { 91 /* We don't yet know how large the file is. Determine that now. */ 92 struct stat st; 93 94 if (fstat (elf->fildes, &st) < 0) 95 goto read_error; 96 97 if (sizeof (size_t) >= sizeof (st.st_size) 98 || st.st_size <= ~((size_t) 0)) 99 elf->maximum_size = (size_t) st.st_size; 100 else 101 { 102 errno = EOVERFLOW; 103 goto read_error; 104 } 105 } 106 107 /* Allocate all the memory we need. */ 108 mem = malloc (elf->maximum_size); 109 if (mem != NULL) 110 { 111 /* Read the file content. */ 112 if (unlikely ((size_t) pread_retry (elf->fildes, mem, 113 elf->maximum_size, 114 elf->start_offset) 115 != elf->maximum_size)) 116 { 117 /* Something went wrong. */ 118 read_error: 119 __libelf_seterrno (ELF_E_READ_ERROR); 120 free (mem); 121 } 122 else 123 { 124 /* Remember the address. */ 125 elf->map_address = mem; 126 127 /* Also remember that we allocated the memory. */ 128 elf->flags |= ELF_F_MALLOCED; 129 130 /* Propagate the information down to all children and 131 their children. */ 132 set_address (elf, elf->start_offset); 133 134 /* Correct the own offsets. */ 135 if (elf->kind == ELF_K_AR) 136 elf->state.ar.offset -= elf->start_offset; 137 elf->start_offset = 0; 138 } 139 } 140 else 141 __libelf_seterrno (ELF_E_NOMEM); 142 143 /* Free the locks on the children. */ 144 libelf_release_all (elf); 145 } 146 147 rwlock_unlock (elf->lock); 148 149 return (char *) elf->map_address; 150} 151