1/* Return section index of section header string table. 2 Copyright (C) 2002 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 2002. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <assert.h> 23#include <gelf.h> 24#include <stddef.h> 25#include <unistd.h> 26 27#include "libelfP.h" 28#include "common.h" 29 30 31int 32elf_getshstrndx (elf, dst) 33 Elf *elf; 34 size_t *dst; 35{ 36 int result = 0; 37 38 if (elf == NULL) 39 return -1; 40 41 if (unlikely (elf->kind != ELF_K_ELF)) 42 { 43 __libelf_seterrno (ELF_E_INVALID_HANDLE); 44 return -1; 45 } 46 47 rwlock_rdlock (elf->lock); 48 49 /* We rely here on the fact that the `elf' element is a common prefix 50 of `elf32' and `elf64'. */ 51 assert (offsetof (struct Elf, state.elf.ehdr) 52 == offsetof (struct Elf, state.elf32.ehdr)); 53 assert (sizeof (elf->state.elf.ehdr) 54 == sizeof (elf->state.elf32.ehdr)); 55 assert (offsetof (struct Elf, state.elf.ehdr) 56 == offsetof (struct Elf, state.elf64.ehdr)); 57 assert (sizeof (elf->state.elf.ehdr) 58 == sizeof (elf->state.elf64.ehdr)); 59 60 if (unlikely (elf->state.elf.ehdr == NULL)) 61 { 62 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 63 result = -1; 64 } 65 else 66 { 67 Elf32_Word num; 68 69 num = (elf->class == ELFCLASS32 70 ? elf->state.elf32.ehdr->e_shstrndx 71 : elf->state.elf64.ehdr->e_shstrndx); 72 73 /* Determine whether the index is too big to fit in the ELF 74 header. */ 75 if (unlikely (num == SHN_XINDEX)) 76 { 77 /* Yes. Search the zeroth section header. */ 78 if (elf->class == ELFCLASS32) 79 { 80 size_t offset; 81 82 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) 83 { 84 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; 85 goto success; 86 } 87 88 offset = elf->state.elf32.ehdr->e_shoff; 89 90 if (elf->map_address != NULL 91 && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA 92 && (ALLOW_UNALIGNED 93 || (((size_t) ((char *) elf->map_address + offset)) 94 & (__alignof__ (Elf32_Shdr) - 1)) == 0)) 95 /* We can directly access the memory. */ 96 num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link; 97 else 98 { 99 /* We avoid reading in all the section headers. Just read 100 the first one. */ 101 Elf32_Shdr shdr_mem; 102 103 if (pread (elf->fildes, &shdr_mem, sizeof (Elf32_Shdr), 104 offset) != sizeof (Elf32_Shdr)) 105 { 106 /* We must be able to read this ELF section header. */ 107 __libelf_seterrno (ELF_E_INVALID_FILE); 108 result = -1; 109 goto out; 110 } 111 112 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 113 CONVERT (shdr_mem.sh_link); 114 num = shdr_mem.sh_link; 115 } 116 } 117 else 118 { 119 size_t offset; 120 121 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) 122 { 123 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; 124 goto success; 125 } 126 127 offset = elf->state.elf64.ehdr->e_shoff; 128 129 if (elf->map_address != NULL 130 && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA 131 && (ALLOW_UNALIGNED 132 || (((size_t) ((char *) elf->map_address + offset)) 133 & (__alignof__ (Elf64_Shdr) - 1)) == 0)) 134 /* We can directly access the memory. */ 135 num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link; 136 else 137 { 138 /* We avoid reading in all the section headers. Just read 139 the first one. */ 140 Elf64_Shdr shdr_mem; 141 142 if (pread (elf->fildes, &shdr_mem, sizeof (Elf64_Shdr), 143 offset) != sizeof (Elf64_Shdr)) 144 { 145 /* We must be able to read this ELF section header. */ 146 __libelf_seterrno (ELF_E_INVALID_FILE); 147 result = -1; 148 goto out; 149 } 150 151 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) 152 CONVERT (shdr_mem.sh_link); 153 num = shdr_mem.sh_link; 154 } 155 } 156 } 157 158 /* Store the result. */ 159 success: 160 *dst = num; 161 } 162 163 out: 164 rwlock_unlock (elf->lock); 165 166 return result; 167} 168INTDEF(elf_getshstrndx) 169