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