1da0c48c4Sopenharmony_ci/* Return section index of section header string table. 2da0c48c4Sopenharmony_ci Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2002. 5da0c48c4Sopenharmony_ci 6da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 7da0c48c4Sopenharmony_ci it under the terms of either 8da0c48c4Sopenharmony_ci 9da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 10da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 11da0c48c4Sopenharmony_ci your option) any later version 12da0c48c4Sopenharmony_ci 13da0c48c4Sopenharmony_ci or 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 16da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 17da0c48c4Sopenharmony_ci your option) any later version 18da0c48c4Sopenharmony_ci 19da0c48c4Sopenharmony_ci or both in parallel, as here. 20da0c48c4Sopenharmony_ci 21da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 22da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 23da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24da0c48c4Sopenharmony_ci General Public License for more details. 25da0c48c4Sopenharmony_ci 26da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 27da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 28da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 31da0c48c4Sopenharmony_ci# include <config.h> 32da0c48c4Sopenharmony_ci#endif 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_ci#include <assert.h> 35da0c48c4Sopenharmony_ci#include <errno.h> 36da0c48c4Sopenharmony_ci#include <gelf.h> 37da0c48c4Sopenharmony_ci#include <stddef.h> 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_ci#include "libelfP.h" 40da0c48c4Sopenharmony_ci#include "common.h" 41da0c48c4Sopenharmony_ci 42da0c48c4Sopenharmony_ci 43da0c48c4Sopenharmony_ciint 44da0c48c4Sopenharmony_cielf_getshdrstrndx (Elf *elf, size_t *dst) 45da0c48c4Sopenharmony_ci{ 46da0c48c4Sopenharmony_ci int result = 0; 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_ci if (elf == NULL) 49da0c48c4Sopenharmony_ci return -1; 50da0c48c4Sopenharmony_ci 51da0c48c4Sopenharmony_ci if (unlikely (elf->kind != ELF_K_ELF)) 52da0c48c4Sopenharmony_ci { 53da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_HANDLE); 54da0c48c4Sopenharmony_ci return -1; 55da0c48c4Sopenharmony_ci } 56da0c48c4Sopenharmony_ci 57da0c48c4Sopenharmony_ci rwlock_rdlock (elf->lock); 58da0c48c4Sopenharmony_ci 59da0c48c4Sopenharmony_ci /* We rely here on the fact that the `elf' element is a common prefix 60da0c48c4Sopenharmony_ci of `elf32' and `elf64'. */ 61da0c48c4Sopenharmony_ci assert (offsetof (struct Elf, state.elf.ehdr) 62da0c48c4Sopenharmony_ci == offsetof (struct Elf, state.elf32.ehdr)); 63da0c48c4Sopenharmony_ci assert (sizeof (elf->state.elf.ehdr) 64da0c48c4Sopenharmony_ci == sizeof (elf->state.elf32.ehdr)); 65da0c48c4Sopenharmony_ci assert (offsetof (struct Elf, state.elf.ehdr) 66da0c48c4Sopenharmony_ci == offsetof (struct Elf, state.elf64.ehdr)); 67da0c48c4Sopenharmony_ci assert (sizeof (elf->state.elf.ehdr) 68da0c48c4Sopenharmony_ci == sizeof (elf->state.elf64.ehdr)); 69da0c48c4Sopenharmony_ci 70da0c48c4Sopenharmony_ci if (unlikely (elf->state.elf.ehdr == NULL)) 71da0c48c4Sopenharmony_ci { 72da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 73da0c48c4Sopenharmony_ci result = -1; 74da0c48c4Sopenharmony_ci } 75da0c48c4Sopenharmony_ci else 76da0c48c4Sopenharmony_ci { 77da0c48c4Sopenharmony_ci Elf32_Word num; 78da0c48c4Sopenharmony_ci 79da0c48c4Sopenharmony_ci num = (elf->class == ELFCLASS32 80da0c48c4Sopenharmony_ci ? elf->state.elf32.ehdr->e_shstrndx 81da0c48c4Sopenharmony_ci : elf->state.elf64.ehdr->e_shstrndx); 82da0c48c4Sopenharmony_ci 83da0c48c4Sopenharmony_ci /* Determine whether the index is too big to fit in the ELF 84da0c48c4Sopenharmony_ci header. */ 85da0c48c4Sopenharmony_ci if (unlikely (num == SHN_XINDEX)) 86da0c48c4Sopenharmony_ci { 87da0c48c4Sopenharmony_ci /* Yes. Search the zeroth section header. */ 88da0c48c4Sopenharmony_ci if (elf->class == ELFCLASS32) 89da0c48c4Sopenharmony_ci { 90da0c48c4Sopenharmony_ci size_t offset; 91da0c48c4Sopenharmony_ci if (unlikely (elf->state.elf32.scns.cnt == 0)) 92da0c48c4Sopenharmony_ci { 93da0c48c4Sopenharmony_ci /* Cannot use SHN_XINDEX without section headers. */ 94da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 95da0c48c4Sopenharmony_ci result = -1; 96da0c48c4Sopenharmony_ci goto out; 97da0c48c4Sopenharmony_ci } 98da0c48c4Sopenharmony_ci 99da0c48c4Sopenharmony_ci if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) 100da0c48c4Sopenharmony_ci { 101da0c48c4Sopenharmony_ci num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; 102da0c48c4Sopenharmony_ci goto success; 103da0c48c4Sopenharmony_ci } 104da0c48c4Sopenharmony_ci 105da0c48c4Sopenharmony_ci offset = elf->state.elf32.ehdr->e_shoff; 106da0c48c4Sopenharmony_ci 107da0c48c4Sopenharmony_ci if (elf->map_address != NULL 108da0c48c4Sopenharmony_ci && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA 109da0c48c4Sopenharmony_ci && (ALLOW_UNALIGNED 110da0c48c4Sopenharmony_ci || (((size_t) ((char *) elf->map_address 111da0c48c4Sopenharmony_ci + elf->start_offset + offset)) 112da0c48c4Sopenharmony_ci & (__alignof__ (Elf32_Shdr) - 1)) == 0)) 113da0c48c4Sopenharmony_ci { 114da0c48c4Sopenharmony_ci /* First see whether the information in the ELF header is 115da0c48c4Sopenharmony_ci valid and it does not ask for too much. */ 116da0c48c4Sopenharmony_ci if (unlikely (elf->maximum_size - offset 117da0c48c4Sopenharmony_ci < sizeof (Elf32_Shdr))) 118da0c48c4Sopenharmony_ci { 119da0c48c4Sopenharmony_ci /* Something is wrong. */ 120da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 121da0c48c4Sopenharmony_ci result = -1; 122da0c48c4Sopenharmony_ci goto out; 123da0c48c4Sopenharmony_ci } 124da0c48c4Sopenharmony_ci 125da0c48c4Sopenharmony_ci /* We can directly access the memory. */ 126da0c48c4Sopenharmony_ci num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset 127da0c48c4Sopenharmony_ci + offset))->sh_link; 128da0c48c4Sopenharmony_ci } 129da0c48c4Sopenharmony_ci else 130da0c48c4Sopenharmony_ci { 131da0c48c4Sopenharmony_ci /* We avoid reading in all the section headers. Just read 132da0c48c4Sopenharmony_ci the first one. */ 133da0c48c4Sopenharmony_ci Elf32_Shdr shdr_mem; 134da0c48c4Sopenharmony_ci ssize_t r; 135da0c48c4Sopenharmony_ci 136da0c48c4Sopenharmony_ci if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, 137da0c48c4Sopenharmony_ci sizeof (Elf32_Shdr), offset)) 138da0c48c4Sopenharmony_ci != sizeof (Elf32_Shdr))) 139da0c48c4Sopenharmony_ci { 140da0c48c4Sopenharmony_ci /* We must be able to read this ELF section header. */ 141da0c48c4Sopenharmony_ci if (r < 0) 142da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_FILE); 143da0c48c4Sopenharmony_ci else 144da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_ELF); 145da0c48c4Sopenharmony_ci result = -1; 146da0c48c4Sopenharmony_ci goto out; 147da0c48c4Sopenharmony_ci } 148da0c48c4Sopenharmony_ci 149da0c48c4Sopenharmony_ci if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 150da0c48c4Sopenharmony_ci CONVERT (shdr_mem.sh_link); 151da0c48c4Sopenharmony_ci num = shdr_mem.sh_link; 152da0c48c4Sopenharmony_ci } 153da0c48c4Sopenharmony_ci } 154da0c48c4Sopenharmony_ci else 155da0c48c4Sopenharmony_ci { 156da0c48c4Sopenharmony_ci if (unlikely (elf->state.elf64.scns.cnt == 0)) 157da0c48c4Sopenharmony_ci { 158da0c48c4Sopenharmony_ci /* Cannot use SHN_XINDEX without section headers. */ 159da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 160da0c48c4Sopenharmony_ci result = -1; 161da0c48c4Sopenharmony_ci goto out; 162da0c48c4Sopenharmony_ci } 163da0c48c4Sopenharmony_ci 164da0c48c4Sopenharmony_ci if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) 165da0c48c4Sopenharmony_ci { 166da0c48c4Sopenharmony_ci num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; 167da0c48c4Sopenharmony_ci goto success; 168da0c48c4Sopenharmony_ci } 169da0c48c4Sopenharmony_ci 170da0c48c4Sopenharmony_ci size_t offset = elf->state.elf64.ehdr->e_shoff; 171da0c48c4Sopenharmony_ci 172da0c48c4Sopenharmony_ci if (elf->map_address != NULL 173da0c48c4Sopenharmony_ci && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA 174da0c48c4Sopenharmony_ci && (ALLOW_UNALIGNED 175da0c48c4Sopenharmony_ci || (((size_t) ((char *) elf->map_address 176da0c48c4Sopenharmony_ci + elf->start_offset + offset)) 177da0c48c4Sopenharmony_ci & (__alignof__ (Elf64_Shdr) - 1)) == 0)) 178da0c48c4Sopenharmony_ci { 179da0c48c4Sopenharmony_ci /* First see whether the information in the ELF header is 180da0c48c4Sopenharmony_ci valid and it does not ask for too much. */ 181da0c48c4Sopenharmony_ci if (unlikely (elf->maximum_size - offset 182da0c48c4Sopenharmony_ci < sizeof (Elf64_Shdr))) 183da0c48c4Sopenharmony_ci { 184da0c48c4Sopenharmony_ci /* Something is wrong. */ 185da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 186da0c48c4Sopenharmony_ci result = -1; 187da0c48c4Sopenharmony_ci goto out; 188da0c48c4Sopenharmony_ci } 189da0c48c4Sopenharmony_ci 190da0c48c4Sopenharmony_ci /* We can directly access the memory. */ 191da0c48c4Sopenharmony_ci num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset 192da0c48c4Sopenharmony_ci + offset))->sh_link; 193da0c48c4Sopenharmony_ci } 194da0c48c4Sopenharmony_ci else 195da0c48c4Sopenharmony_ci { 196da0c48c4Sopenharmony_ci /* We avoid reading in all the section headers. Just read 197da0c48c4Sopenharmony_ci the first one. */ 198da0c48c4Sopenharmony_ci Elf64_Shdr shdr_mem; 199da0c48c4Sopenharmony_ci ssize_t r; 200da0c48c4Sopenharmony_ci 201da0c48c4Sopenharmony_ci if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, 202da0c48c4Sopenharmony_ci sizeof (Elf64_Shdr), offset)) 203da0c48c4Sopenharmony_ci != sizeof (Elf64_Shdr))) 204da0c48c4Sopenharmony_ci { 205da0c48c4Sopenharmony_ci /* We must be able to read this ELF section header. */ 206da0c48c4Sopenharmony_ci if (r < 0) 207da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_FILE); 208da0c48c4Sopenharmony_ci else 209da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_ELF); 210da0c48c4Sopenharmony_ci result = -1; 211da0c48c4Sopenharmony_ci goto out; 212da0c48c4Sopenharmony_ci } 213da0c48c4Sopenharmony_ci 214da0c48c4Sopenharmony_ci if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 215da0c48c4Sopenharmony_ci CONVERT (shdr_mem.sh_link); 216da0c48c4Sopenharmony_ci num = shdr_mem.sh_link; 217da0c48c4Sopenharmony_ci } 218da0c48c4Sopenharmony_ci } 219da0c48c4Sopenharmony_ci } 220da0c48c4Sopenharmony_ci 221da0c48c4Sopenharmony_ci /* Store the result. */ 222da0c48c4Sopenharmony_ci success: 223da0c48c4Sopenharmony_ci *dst = num; 224da0c48c4Sopenharmony_ci } 225da0c48c4Sopenharmony_ci 226da0c48c4Sopenharmony_ci out: 227da0c48c4Sopenharmony_ci rwlock_unlock (elf->lock); 228da0c48c4Sopenharmony_ci 229da0c48c4Sopenharmony_ci return result; 230da0c48c4Sopenharmony_ci} 231da0c48c4Sopenharmony_ciINTDEF(elf_getshdrstrndx) 232da0c48c4Sopenharmony_ci/* Alias for the deprecated name. */ 233da0c48c4Sopenharmony_cistrong_alias (elf_getshdrstrndx, elf_getshstrndx) 234