Branch data Line data Source code
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 <unistd.h> 36 : : #include <sys/stat.h> 37 : : 38 : : #include <system.h> 39 : : #include "libelfP.h" 40 : : #include "common.h" 41 : : 42 : : 43 : : static void 44 : 1 : set_address (Elf *elf, size_t offset) 45 : : { 46 [ - + ]: 1 : if (elf->kind == ELF_K_AR) 47 : : { 48 : 0 : Elf *child = elf->state.ar.children; 49 : : 50 [ # # ]: 0 : while (child != NULL) 51 : : { 52 [ # # ]: 0 : if (child->map_address == NULL) 53 : : { 54 : 0 : child->map_address = elf->map_address; 55 : 0 : child->start_offset -= offset; 56 [ # # ]: 0 : if (child->kind == ELF_K_AR) 57 : 0 : child->state.ar.offset -= offset; 58 : : 59 : 0 : set_address (child, offset); 60 : : } 61 : : 62 : 0 : child = child->next; 63 : : } 64 : : } 65 : 1 : } 66 : : 67 : : 68 : : char * 69 : : internal_function 70 : 1 : __libelf_readall (Elf *elf) 71 : : { 72 : : /* Get the file. */ 73 : 1 : rwlock_wrlock (elf->lock); 74 : : 75 [ + - - + ]: 1 : if (elf->map_address == NULL && unlikely (elf->fildes == -1)) 76 : : { 77 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 78 : 0 : rwlock_unlock (elf->lock); 79 : 0 : return NULL; 80 : : } 81 : : 82 : : /* If the file is not mmap'ed and not previously loaded, do it now. */ 83 [ + - ]: 1 : if (elf->map_address == NULL) 84 : : { 85 : 1 : char *mem = NULL; 86 : : 87 : : /* If this is an archive and we have derived descriptors get the 88 : : locks for all of them. */ 89 : 1 : libelf_acquire_all (elf); 90 : : 91 [ - + ]: 1 : if (elf->maximum_size == ~((size_t) 0)) 92 : : { 93 : : /* We don't yet know how large the file is. Determine that now. */ 94 : 0 : struct stat st; 95 : : 96 [ # # ]: 0 : if (fstat (elf->fildes, &st) < 0) 97 : 0 : goto read_error; 98 : : 99 : 0 : if (sizeof (size_t) >= sizeof (st.st_size) 100 : : || st.st_size <= ~((size_t) 0)) 101 : 0 : elf->maximum_size = (size_t) st.st_size; 102 : : else 103 : : { 104 : : errno = EOVERFLOW; 105 : : goto read_error; 106 : : } 107 : : } 108 : : 109 : : /* Allocate all the memory we need. */ 110 : 1 : mem = (char *) malloc (elf->maximum_size); 111 [ + - ]: 1 : if (mem != NULL) 112 : : { 113 : : /* Read the file content. */ 114 [ - + ]: 1 : if (unlikely ((size_t) pread_retry (elf->fildes, mem, 115 : : elf->maximum_size, 116 : : elf->start_offset) 117 : : != elf->maximum_size)) 118 : : { 119 : : /* Something went wrong. */ 120 : 0 : read_error: 121 : 0 : __libelf_seterrno (ELF_E_READ_ERROR); 122 : 0 : free (mem); 123 : : } 124 : : else 125 : : { 126 : : /* Remember the address. */ 127 : 1 : elf->map_address = mem; 128 : : 129 : : /* Also remember that we allocated the memory. */ 130 : 1 : elf->flags |= ELF_F_MALLOCED; 131 : : 132 : : /* Propagate the information down to all children and 133 : : their children. */ 134 : 1 : set_address (elf, elf->start_offset); 135 : : 136 : : /* Correct the own offsets. */ 137 [ - + ]: 1 : if (elf->kind == ELF_K_AR) 138 : 0 : elf->state.ar.offset -= elf->start_offset; 139 : 1 : elf->start_offset = 0; 140 : : } 141 : : } 142 : : else 143 : 0 : __libelf_seterrno (ELF_E_NOMEM); 144 : : 145 : : /* Free the locks on the children. */ 146 : 1 : libelf_release_all (elf); 147 : : } 148 : : 149 : 1 : rwlock_unlock (elf->lock); 150 : : 151 : 1 : return (char *) elf->map_address; 152 : : }