Branch data Line data Source code
1 : : /* Return converted data from raw chunk of ELF file. 2 : : Copyright (C) 2007, 2014, 2015 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <assert.h> 34 : : #include <errno.h> 35 : : #include <stdlib.h> 36 : : #include <string.h> 37 : : #include <unistd.h> 38 : : 39 : : #include <system.h> 40 : : #include "libelfP.h" 41 : : #include "common.h" 42 : : 43 : : Elf_Data * 44 : 1085 : elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) 45 : : { 46 [ + - ]: 1085 : if (unlikely (elf == NULL)) 47 : : return NULL; 48 : : 49 [ - + ]: 1085 : if (unlikely (elf->kind != ELF_K_ELF)) 50 : : { 51 : : /* No valid descriptor. */ 52 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 53 : 0 : return NULL; 54 : : } 55 : : 56 [ + - + + : 1085 : if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size - + ] 57 : : || elf->maximum_size - (uint64_t) offset < size)) 58 : : 59 : : { 60 : : /* Invalid request. */ 61 : 12 : __libelf_seterrno (ELF_E_INVALID_OP); 62 : 12 : return NULL; 63 : : } 64 : : 65 [ - + ]: 1073 : if (type >= ELF_T_NUM) 66 : : { 67 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_TYPE); 68 : 0 : return NULL; 69 : : } 70 : : 71 : : /* Get the raw bytes from the file. */ 72 : 1073 : void *rawchunk; 73 : 1073 : int flags = 0; 74 : 1073 : Elf_Data *result = NULL; 75 : : 76 : 1073 : rwlock_rdlock (elf->lock); 77 : : 78 : 1073 : size_t align = __libelf_type_align (elf->class, type); 79 [ + + ]: 1073 : if (elf->map_address != NULL) 80 : : { 81 : : /* If the file is mmap'ed we can use it directly, if aligned for type. */ 82 : 832 : char *rawdata = elf->map_address + elf->start_offset + offset; 83 [ + + ]: 832 : if (((uintptr_t) rawdata & (align - 1)) == 0) 84 : : rawchunk = rawdata; 85 : : else 86 : : { 87 : : /* We allocate the memory and memcpy it to get aligned data. */ 88 : 3 : rawchunk = malloc (size); 89 [ - + ]: 3 : if (rawchunk == NULL) 90 : 0 : goto nomem; 91 : 3 : memcpy (rawchunk, rawdata, size); 92 : 3 : flags = ELF_F_MALLOCED; 93 : : } 94 : : } 95 : : else 96 : : { 97 : : /* We allocate the memory and read the data from the file. */ 98 : 241 : rawchunk = malloc (size); 99 [ - + ]: 241 : if (rawchunk == NULL) 100 : : { 101 : 0 : nomem: 102 : 0 : __libelf_seterrno (ELF_E_NOMEM); 103 : 0 : goto out; 104 : : } 105 : : 106 : : /* Read the file content. */ 107 [ - + ]: 241 : if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size, 108 : : elf->start_offset + offset) 109 : : != size)) 110 : : { 111 : : /* Something went wrong. */ 112 : 0 : free (rawchunk); 113 : 0 : __libelf_seterrno (ELF_E_READ_ERROR); 114 : 0 : goto out; 115 : : } 116 : : 117 : : flags = ELF_F_MALLOCED; 118 : : } 119 : : 120 : : /* Copy and/or convert the data as needed for aligned native-order access. */ 121 : 1073 : void *buffer; 122 [ + + ]: 1073 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA) 123 : : { 124 [ - + ]: 710 : if (((uintptr_t) rawchunk & (align - 1)) == 0) 125 : : /* No need to copy, we can use the raw data. */ 126 : : buffer = rawchunk; 127 : : else 128 : : { 129 : : /* A malloc'd block is always sufficiently aligned. */ 130 [ # # ]: 0 : assert (flags == 0); 131 : : 132 : 0 : buffer = malloc (size); 133 [ # # ]: 0 : if (unlikely (buffer == NULL)) 134 : 0 : goto nomem; 135 : 0 : flags = ELF_F_MALLOCED; 136 : : 137 : : /* The copy will be appropriately aligned for direct access. */ 138 : 0 : memcpy (buffer, rawchunk, size); 139 : : } 140 : : } 141 : : else 142 : : { 143 [ + + ]: 363 : if (flags) 144 : : buffer = rawchunk; 145 : : else 146 : : { 147 : 337 : buffer = malloc (size); 148 [ - + ]: 337 : if (unlikely (buffer == NULL)) 149 : 0 : goto nomem; 150 : : flags = ELF_F_MALLOCED; 151 : : } 152 : : 153 : : /* Call the conversion function. */ 154 : 363 : (*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0); 155 : : } 156 : : 157 : : /* Allocate the dummy container to point at this buffer. */ 158 : 1073 : Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk); 159 [ - + ]: 1073 : if (chunk == NULL) 160 : : { 161 [ # # ]: 0 : if (flags) 162 : 0 : free (buffer); 163 : 0 : goto nomem; 164 : : } 165 : : 166 : 1073 : chunk->dummy_scn.elf = elf; 167 : 1073 : chunk->dummy_scn.flags = flags; 168 : 1073 : chunk->data.s = &chunk->dummy_scn; 169 : 1073 : chunk->data.d.d_buf = buffer; 170 : 1073 : chunk->data.d.d_size = size; 171 : 1073 : chunk->data.d.d_type = type; 172 : 1073 : chunk->data.d.d_align = align; 173 : 1073 : chunk->data.d.d_version = EV_CURRENT; 174 : : 175 : 1073 : rwlock_unlock (elf->lock); 176 : 1073 : rwlock_wrlock (elf->lock); 177 : : 178 : 1073 : chunk->next = elf->state.elf.rawchunks; 179 : 1073 : elf->state.elf.rawchunks = chunk; 180 : 1073 : result = &chunk->data.d; 181 : : 182 : : out: 183 : : rwlock_unlock (elf->lock); 184 : : return result; 185 : : }