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