1 /* Return section header. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 1998. 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 <unistd.h> 24 25 #include "libelfP.h" 26 #include "common.h" 27 28 #ifndef LIBELFBITS 29 # define LIBELFBITS 32 30 #endif 31 32 33 ElfW2(LIBELFBITS,Shdr) * 34 elfw2(LIBELFBITS,getshdr) (scn) 35 Elf_Scn *scn; 36 { ElfW2(LIBELFBITS,Shdr)37 ElfW2(LIBELFBITS,Shdr) *result; 38 39 if (scn == NULL) 40 return NULL; 41 42 if (unlikely (scn->elf->state.elf.ehdr == NULL)) 43 { 44 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 45 return NULL; 46 } 47 48 if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS))) 49 { 50 __libelf_seterrno (ELF_E_INVALID_CLASS); 51 return NULL; 52 } 53 54 result = scn->shdr.ELFW(e,LIBELFBITS); 55 if (result == NULL) 56 { 57 /* Read the section header table. */ 58 Elf *elf = scn->elf; 59 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; 60 size_t shnum; 61 ElfW2(LIBELFBITS,Shdr) *shdr; 62 size_t size; 63 size_t cnt; 64 65 rwlock_wrlock (elf->lock); 66 67 /* Try again, maybe the data is there now. */ 68 result = scn->shdr.ELFW(e,LIBELFBITS); 69 if (result != NULL) 70 goto out; 71 72 if (INTUSE (elf_getshnum) (elf, &shnum) != 0) 73 goto out; 74 size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr)); 75 76 /* Allocate memory for the program headers. We know the number 77 of entries from the ELF header. */ 78 shdr = elf->state.ELFW(elf,LIBELFBITS).shdr = 79 (ElfW2(LIBELFBITS,Shdr) *) malloc (size); 80 if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL) 81 { 82 __libelf_seterrno (ELF_E_NOMEM); 83 goto out; 84 } 85 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1; 86 87 if (elf->map_address != NULL) 88 { 89 ElfW2(LIBELFBITS,Shdr) *notcvt; 90 91 /* All the data is already mapped. If we could use it 92 directly this would already have happened. */ 93 assert (ehdr->e_ident[EI_DATA] != MY_ELFDATA 94 || (! ALLOW_UNALIGNED 95 && (ehdr->e_shoff 96 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0)); 97 98 /* Now copy the data and at the same time convert the byte 99 order. */ 100 if (ALLOW_UNALIGNED 101 || (ehdr->e_shoff 102 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0) 103 notcvt = (ElfW2(LIBELFBITS,Shdr) *) 104 ((char *) elf->map_address 105 + elf->start_offset + ehdr->e_shoff); 106 else 107 { 108 notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size); 109 memcpy (notcvt, ((char *) elf->map_address 110 + elf->start_offset + ehdr->e_shoff), 111 size); 112 } 113 114 for (cnt = 0; cnt < shnum; ++cnt) 115 { 116 CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name); 117 CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type); 118 CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags); 119 CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr); 120 CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset); 121 CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size); 122 CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link); 123 CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info); 124 CONVERT_TO (shdr[cnt].sh_addralign, notcvt[cnt].sh_addralign); 125 CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize); 126 } 127 } 128 else if (elf->fildes != -1) 129 { 130 /* Read the header. */ 131 if ((size_t) pread (elf->fildes, 132 elf->state.ELFW(elf,LIBELFBITS).shdr, size, 133 elf->start_offset + ehdr->e_shoff) != size) 134 { 135 /* Severe problems. We cannot read the data. */ 136 __libelf_seterrno (ELF_E_READ_ERROR); 137 goto free_and_out; 138 } 139 140 /* If the byte order of the file is not the same as the one 141 of the host convert the data now. */ 142 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA) 143 for (cnt = 0; cnt < shnum; ++cnt) 144 { 145 CONVERT (shdr[cnt].sh_name); 146 CONVERT (shdr[cnt].sh_type); 147 CONVERT (shdr[cnt].sh_flags); 148 CONVERT (shdr[cnt].sh_addr); 149 CONVERT (shdr[cnt].sh_offset); 150 CONVERT (shdr[cnt].sh_size); 151 CONVERT (shdr[cnt].sh_link); 152 CONVERT (shdr[cnt].sh_info); 153 CONVERT (shdr[cnt].sh_addralign); 154 CONVERT (shdr[cnt].sh_entsize); 155 } 156 } 157 else 158 { 159 /* The file descriptor was already enabled and not all data was 160 read. Undo the allocation. */ 161 __libelf_seterrno (ELF_E_FD_DISABLED); 162 163 free_and_out: 164 free (shdr); 165 elf->state.ELFW(elf,LIBELFBITS).shdr = NULL; 166 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0; 167 168 goto out; 169 } 170 171 /* Set the pointers in the `scn's. */ 172 for (cnt = 0; cnt < shnum; ++cnt) 173 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS) 174 = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt]; 175 176 result = scn->shdr.ELFW(e,LIBELFBITS); 177 assert (result != NULL); 178 179 out: 180 rwlock_unlock (elf->lock); 181 } 182 183 return result; 184 } 185 INTDEF(elfw2(LIBELFBITS,getshdr)) 186