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 : : Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org> 4 : : This file is part of elfutils. 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 <assert.h> 35 : : #include <errno.h> 36 : : #include <stdlib.h> 37 : : #include <string.h> 38 : : 39 : : #include "libelfP.h" 40 : : #include "common.h" 41 : : 42 : : Elf_Data * 43 : 1048 : elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) 44 : : { 45 [ + - ]: 1048 : if (unlikely (elf == NULL)) 46 : : return NULL; 47 : : 48 [ - + ]: 1048 : if (unlikely (elf->kind != ELF_K_ELF)) 49 : : { 50 : : /* No valid descriptor. */ 51 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 52 : 0 : return NULL; 53 : : } 54 : : 55 [ + - + + : 1048 : if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size - + ] 56 : : || elf->maximum_size - (uint64_t) offset < size)) 57 : : 58 : : { 59 : : /* Invalid request. */ 60 : 12 : __libelf_seterrno (ELF_E_INVALID_OP); 61 : 12 : return NULL; 62 : : } 63 : : 64 [ - + ]: 1036 : if (type >= ELF_T_NUM) 65 : : { 66 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_TYPE); 67 : 0 : return NULL; 68 : : } 69 : : 70 : : /* Get the raw bytes from the file. */ 71 : 1036 : void *rawchunk; 72 : 1036 : int flags = 0; 73 : 1036 : Elf_Data *result = NULL; 74 : : 75 : 1036 : rwlock_rdlock (elf->lock); 76 : : 77 : : /* Maybe we already got this chunk? */ 78 : 1036 : Elf_Data_Chunk *rawchunks = elf->state.elf.rawchunks; 79 [ + + ]: 18797 : while (rawchunks != NULL) 80 : : { 81 [ + + - + ]: 17799 : if ((rawchunks->offset == offset || size == 0) 82 [ + - ]: 38 : && rawchunks->data.d.d_size == size 83 [ + - ]: 38 : && rawchunks->data.d.d_type == type) 84 : : { 85 : 38 : result = &rawchunks->data.d; 86 : 38 : goto out; 87 : : } 88 : 17761 : rawchunks = rawchunks->next; 89 : : } 90 : : 91 : 998 : size_t align = __libelf_type_align (elf->class, type); 92 [ + + ]: 998 : if (elf->map_address != NULL) 93 : : { 94 : : /* If the file is mmap'ed we can use it directly, if aligned for type. */ 95 : 757 : char *rawdata = elf->map_address + elf->start_offset + offset; 96 [ + + ]: 757 : if (((uintptr_t) rawdata & (align - 1)) == 0) 97 : : rawchunk = rawdata; 98 : : else 99 : : { 100 : : /* We allocate the memory and memcpy it to get aligned data. */ 101 : 2 : rawchunk = malloc (size); 102 [ - + ]: 2 : if (rawchunk == NULL) 103 : 0 : goto nomem; 104 : 2 : memcpy (rawchunk, rawdata, size); 105 : 2 : flags = ELF_F_MALLOCED; 106 : : } 107 : : } 108 : : else 109 : : { 110 : : /* We allocate the memory and read the data from the file. */ 111 : 241 : rawchunk = malloc (size); 112 [ - + ]: 241 : if (rawchunk == NULL) 113 : : { 114 : 0 : nomem: 115 : 0 : __libelf_seterrno (ELF_E_NOMEM); 116 : 0 : goto out; 117 : : } 118 : : 119 : : /* Read the file content. */ 120 [ - + ]: 241 : if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size, 121 : : elf->start_offset + offset) 122 : : != size)) 123 : : { 124 : : /* Something went wrong. */ 125 : 0 : free (rawchunk); 126 : 0 : __libelf_seterrno (ELF_E_READ_ERROR); 127 : 0 : goto out; 128 : : } 129 : : 130 : : flags = ELF_F_MALLOCED; 131 : : } 132 : : 133 : : /* Copy and/or convert the data as needed for aligned native-order access. */ 134 : 998 : void *buffer; 135 [ + + ]: 998 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA) 136 : : { 137 [ - + ]: 645 : if (((uintptr_t) rawchunk & (align - 1)) == 0) 138 : : /* No need to copy, we can use the raw data. */ 139 : : buffer = rawchunk; 140 : : else 141 : : { 142 : : /* A malloc'd block is always sufficiently aligned. */ 143 [ # # ]: 0 : assert (flags == 0); 144 : : 145 : 0 : buffer = malloc (size); 146 [ # # ]: 0 : if (unlikely (buffer == NULL)) 147 : 0 : goto nomem; 148 : 0 : flags = ELF_F_MALLOCED; 149 : : 150 : : /* The copy will be appropriately aligned for direct access. */ 151 : 0 : memcpy (buffer, rawchunk, size); 152 : : } 153 : : } 154 : : else 155 : : { 156 [ + + ]: 353 : if (flags) 157 : : buffer = rawchunk; 158 : : else 159 : : { 160 : 328 : buffer = malloc (size); 161 [ - + ]: 328 : if (unlikely (buffer == NULL)) 162 : 0 : goto nomem; 163 : : flags = ELF_F_MALLOCED; 164 : : } 165 : : 166 : : /* Call the conversion function. */ 167 : 353 : (*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0); 168 : : } 169 : : 170 : : /* Allocate the dummy container to point at this buffer. */ 171 : 998 : Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk); 172 [ - + ]: 998 : if (chunk == NULL) 173 : : { 174 [ # # ]: 0 : if (flags) 175 : 0 : free (buffer); 176 : 0 : goto nomem; 177 : : } 178 : : 179 : 998 : chunk->dummy_scn.elf = elf; 180 : 998 : chunk->dummy_scn.flags = flags; 181 : 998 : chunk->data.s = &chunk->dummy_scn; 182 : 998 : chunk->data.d.d_buf = buffer; 183 : 998 : chunk->data.d.d_size = size; 184 : 998 : chunk->data.d.d_type = type; 185 : 998 : chunk->data.d.d_align = align; 186 : 998 : chunk->data.d.d_version = EV_CURRENT; 187 : 998 : chunk->offset = offset; 188 : : 189 : 998 : rwlock_unlock (elf->lock); 190 : 998 : rwlock_wrlock (elf->lock); 191 : : 192 : 998 : chunk->next = elf->state.elf.rawchunks; 193 : 998 : elf->state.elf.rawchunks = chunk; 194 : 998 : result = &chunk->data.d; 195 : : 196 : : out: 197 : : rwlock_unlock (elf->lock); 198 : : return result; 199 : : }