elf_getshdrstrndx.c revision 720383c53b435de6647edd78060dd7d38ade25a5
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 96 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) 97 { 98 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; 99 goto success; 100 } 101 102 offset = elf->state.elf32.ehdr->e_shoff; 103 104 if (elf->map_address != NULL 105 && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA 106 && (ALLOW_UNALIGNED 107 || (((size_t) ((char *) elf->map_address 108 + elf->start_offset + offset)) 109 & (__alignof__ (Elf32_Shdr) - 1)) == 0)) 110 { 111 /* First see whether the information in the ELF header is 112 valid and it does not ask for too much. */ 113 if (unlikely (elf->maximum_size - offset 114 < sizeof (Elf32_Shdr))) 115 { 116 /* Something is wrong. */ 117 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 118 result = -1; 119 goto out; 120 } 121 122 /* We can directly access the memory. */ 123 num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset 124 + offset))->sh_link; 125 } 126 else 127 { 128 /* We avoid reading in all the section headers. Just read 129 the first one. */ 130 Elf32_Shdr shdr_mem; 131 132 if (unlikely (pread_retry (elf->fildes, &shdr_mem, 133 sizeof (Elf32_Shdr), offset) 134 != sizeof (Elf32_Shdr))) 135 { 136 /* We must be able to read this ELF section header. */ 137 __libelf_seterrno (ELF_E_INVALID_FILE); 138 result = -1; 139 goto out; 140 } 141 142 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 143 CONVERT (shdr_mem.sh_link); 144 num = shdr_mem.sh_link; 145 } 146 } 147 else 148 { 149 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) 150 { 151 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; 152 goto success; 153 } 154 155 size_t offset = elf->state.elf64.ehdr->e_shoff; 156 157 if (elf->map_address != NULL 158 && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA 159 && (ALLOW_UNALIGNED 160 || (((size_t) ((char *) elf->map_address 161 + elf->start_offset + offset)) 162 & (__alignof__ (Elf64_Shdr) - 1)) == 0)) 163 { 164 /* First see whether the information in the ELF header is 165 valid and it does not ask for too much. */ 166 if (unlikely (elf->maximum_size - offset 167 < sizeof (Elf64_Shdr))) 168 { 169 /* Something is wrong. */ 170 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 171 result = -1; 172 goto out; 173 } 174 175 /* We can directly access the memory. */ 176 num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset 177 + offset))->sh_link; 178 } 179 else 180 { 181 /* We avoid reading in all the section headers. Just read 182 the first one. */ 183 Elf64_Shdr shdr_mem; 184 185 if (unlikely (pread_retry (elf->fildes, &shdr_mem, 186 sizeof (Elf64_Shdr), offset) 187 != sizeof (Elf64_Shdr))) 188 { 189 /* We must be able to read this ELF section header. */ 190 __libelf_seterrno (ELF_E_INVALID_FILE); 191 result = -1; 192 goto out; 193 } 194 195 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 196 CONVERT (shdr_mem.sh_link); 197 num = shdr_mem.sh_link; 198 } 199 } 200 } 201 202 /* Store the result. */ 203 success: 204 *dst = num; 205 } 206 207 out: 208 rwlock_unlock (elf->lock); 209 210 return result; 211} 212INTDEF(elf_getshdrstrndx) 213/* Alias for the deprecated name. */ 214strong_alias (elf_getshdrstrndx, elf_getshstrndx) 215