Branch data Line data Source code
1 : : /* Return section index of section header string table. 2 : : Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2002. 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 <gelf.h> 37 : : #include <stddef.h> 38 : : 39 : : #include "libelfP.h" 40 : : #include "common.h" 41 : : 42 : : 43 : : int 44 : 1036960 : elf_getshdrstrndx (Elf *elf, size_t *dst) 45 : : { 46 : 1036960 : int result = 0; 47 : : 48 [ + - ]: 1036960 : if (elf == NULL) 49 : : return -1; 50 : : 51 [ - + ]: 1036960 : if (unlikely (elf->kind != ELF_K_ELF)) 52 : : { 53 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 54 : 0 : return -1; 55 : : } 56 : : 57 : 1036960 : rwlock_rdlock (elf->lock); 58 : : 59 : : /* We rely here on the fact that the `elf' element is a common prefix 60 : : of `elf32' and `elf64'. */ 61 : 1036960 : assert (offsetof (struct Elf, state.elf.ehdr) 62 : : == offsetof (struct Elf, state.elf32.ehdr)); 63 : 1036960 : assert (sizeof (elf->state.elf.ehdr) 64 : : == sizeof (elf->state.elf32.ehdr)); 65 : 1036960 : assert (offsetof (struct Elf, state.elf.ehdr) 66 : : == offsetof (struct Elf, state.elf64.ehdr)); 67 : 1036960 : assert (sizeof (elf->state.elf.ehdr) 68 : : == sizeof (elf->state.elf64.ehdr)); 69 : : 70 [ - + ]: 1036960 : if (unlikely (elf->state.elf.ehdr == NULL)) 71 : : { 72 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 73 : 0 : result = -1; 74 : : } 75 : : else 76 : : { 77 : 1036960 : Elf32_Word num; 78 : : 79 : 2073920 : num = (elf->class == ELFCLASS32 80 : 17485 : ? elf->state.elf32.ehdr->e_shstrndx 81 [ + + ]: 1036960 : : elf->state.elf64.ehdr->e_shstrndx); 82 : : 83 : : /* Determine whether the index is too big to fit in the ELF 84 : : header. */ 85 [ + + ]: 1036960 : if (unlikely (num == SHN_XINDEX)) 86 : : { 87 : : /* Yes. Search the zeroth section header. */ 88 [ + + ]: 98 : if (elf->class == ELFCLASS32) 89 : : { 90 : 53 : size_t offset; 91 [ - + ]: 53 : if (unlikely (elf->state.elf32.scns.cnt == 0)) 92 : : { 93 : : /* Cannot use SHN_XINDEX without section headers. */ 94 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 95 : 0 : result = -1; 96 : 0 : goto out; 97 : : } 98 : : 99 [ + + ]: 53 : if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) 100 : : { 101 : 17 : num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; 102 : 17 : goto success; 103 : : } 104 : : 105 : 36 : offset = elf->state.elf32.ehdr->e_shoff; 106 : : 107 [ + + ]: 36 : if (elf->map_address != NULL 108 : 24 : && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA 109 [ + + ]: 24 : && (ALLOW_UNALIGNED 110 : : || (((size_t) ((char *) elf->map_address 111 : : + elf->start_offset + offset)) 112 : : & (__alignof__ (Elf32_Shdr) - 1)) == 0)) 113 : : { 114 : : /* First see whether the information in the ELF header is 115 : : valid and it does not ask for too much. */ 116 [ - + ]: 12 : if (unlikely (elf->maximum_size - offset 117 : : < sizeof (Elf32_Shdr))) 118 : : { 119 : : /* Something is wrong. */ 120 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 121 : 0 : result = -1; 122 : 0 : goto out; 123 : : } 124 : : 125 : : /* We can directly access the memory. */ 126 : 12 : num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset 127 : 12 : + offset))->sh_link; 128 : : } 129 : : else 130 : : { 131 : : /* We avoid reading in all the section headers. Just read 132 : : the first one. */ 133 : 24 : Elf32_Shdr shdr_mem; 134 : 24 : ssize_t r; 135 : : 136 [ - + ]: 24 : if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, 137 : : sizeof (Elf32_Shdr), offset)) 138 : : != sizeof (Elf32_Shdr))) 139 : : { 140 : : /* We must be able to read this ELF section header. */ 141 [ # # ]: 0 : if (r < 0) 142 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE); 143 : : else 144 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF); 145 : 0 : result = -1; 146 : 0 : goto out; 147 : : } 148 : : 149 [ + + ]: 24 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 150 : 16 : CONVERT (shdr_mem.sh_link); 151 : 24 : num = shdr_mem.sh_link; 152 : : } 153 : : } 154 : : else 155 : : { 156 [ - + ]: 45 : if (unlikely (elf->state.elf64.scns.cnt == 0)) 157 : : { 158 : : /* Cannot use SHN_XINDEX without section headers. */ 159 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 160 : 0 : result = -1; 161 : 0 : goto out; 162 : : } 163 : : 164 [ + + ]: 45 : if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) 165 : : { 166 : 14 : num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; 167 : 14 : goto success; 168 : : } 169 : : 170 : 31 : size_t offset = elf->state.elf64.ehdr->e_shoff; 171 : : 172 [ + + ]: 31 : if (elf->map_address != NULL 173 : 23 : && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA 174 [ + + ]: 23 : && (ALLOW_UNALIGNED 175 : : || (((size_t) ((char *) elf->map_address 176 : : + elf->start_offset + offset)) 177 : : & (__alignof__ (Elf64_Shdr) - 1)) == 0)) 178 : : { 179 : : /* First see whether the information in the ELF header is 180 : : valid and it does not ask for too much. */ 181 [ - + ]: 11 : if (unlikely (elf->maximum_size - offset 182 : : < sizeof (Elf64_Shdr))) 183 : : { 184 : : /* Something is wrong. */ 185 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 186 : 0 : result = -1; 187 : 0 : goto out; 188 : : } 189 : : 190 : : /* We can directly access the memory. */ 191 : 11 : num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset 192 : 11 : + offset))->sh_link; 193 : : } 194 : : else 195 : : { 196 : : /* We avoid reading in all the section headers. Just read 197 : : the first one. */ 198 : 20 : Elf64_Shdr shdr_mem; 199 : 20 : ssize_t r; 200 : : 201 [ - + ]: 20 : if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, 202 : : sizeof (Elf64_Shdr), offset)) 203 : : != sizeof (Elf64_Shdr))) 204 : : { 205 : : /* We must be able to read this ELF section header. */ 206 [ # # ]: 0 : if (r < 0) 207 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE); 208 : : else 209 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF); 210 : 0 : result = -1; 211 : 0 : goto out; 212 : : } 213 : : 214 [ + + ]: 20 : if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 215 : 16 : CONVERT (shdr_mem.sh_link); 216 : 20 : num = shdr_mem.sh_link; 217 : : } 218 : : } 219 : : } 220 : : 221 : : /* Store the result. */ 222 : 1036862 : success: 223 : 1036960 : *dst = num; 224 : : } 225 : : 226 : : out: 227 : : rwlock_unlock (elf->lock); 228 : : 229 : : return result; 230 : : } 231 : : INTDEF(elf_getshdrstrndx) 232 : : /* Alias for the deprecated name. */ 233 : : strong_alias (elf_getshdrstrndx, elf_getshstrndx)