1 /* Return section header.
2 Copyright (C) 1998-2002, 2005, 2007, 2009, 2012 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
44 # define LIBELFBITS 32
48 static ElfW2(LIBELFBITS,Shdr) *
49 load_shdr_wrlock (Elf_Scn *scn)
51 ElfW2(LIBELFBITS,Shdr) *result;
53 /* Read the section header table. */
55 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
57 /* Try again, maybe the data is there now. */
58 result = scn->shdr.ELFW(e,LIBELFBITS);
63 if (__elf_getshdrnum_rdlock (elf, &shnum) != 0)
65 size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
67 /* Allocate memory for the section headers. We know the number
68 of entries from the ELF header. */
69 ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
70 (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
71 if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
73 __libelf_seterrno (ELF_E_NOMEM);
76 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
78 if (elf->map_address != NULL)
80 ElfW2(LIBELFBITS,Shdr) *notcvt;
82 /* All the data is already mapped. If we could use it
83 directly this would already have happened. Unless
84 we allocated the memory ourselves and the ELF_F_MALLOCED
86 void *file_shdr = ((char *) elf->map_address
87 + elf->start_offset + ehdr->e_shoff);
89 assert ((elf->flags & ELF_F_MALLOCED)
90 || ehdr->e_ident[EI_DATA] != MY_ELFDATA
92 && ((uintptr_t) file_shdr
93 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
95 /* Now copy the data and at the same time convert the byte order. */
96 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
98 assert ((elf->flags & ELF_F_MALLOCED) || ! ALLOW_UNALIGNED);
99 memcpy (shdr, file_shdr, size);
104 || ((uintptr_t) file_shdr
105 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0)
106 notcvt = (ElfW2(LIBELFBITS,Shdr) *)
107 ((char *) elf->map_address
108 + elf->start_offset + ehdr->e_shoff);
111 notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size);
112 memcpy (notcvt, ((char *) elf->map_address
113 + elf->start_offset + ehdr->e_shoff),
117 for (size_t cnt = 0; cnt < shnum; ++cnt)
119 CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
120 CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
121 CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
122 CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
123 CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
124 CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
125 CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
126 CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
127 CONVERT_TO (shdr[cnt].sh_addralign,
128 notcvt[cnt].sh_addralign);
129 CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
131 /* If this is a section with an extended index add a
132 reference in the section which uses the extended
134 if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
135 && shdr[cnt].sh_link < shnum)
136 elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
139 /* Set the own shndx_index field in case it has not yet
141 if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
142 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
147 else if (likely (elf->fildes != -1))
149 /* Read the header. */
150 ssize_t n = pread_retry (elf->fildes,
151 elf->state.ELFW(elf,LIBELFBITS).shdr, size,
152 elf->start_offset + ehdr->e_shoff);
153 if (unlikely ((size_t) n != size))
155 /* Severe problems. We cannot read the data. */
156 __libelf_seterrno (ELF_E_READ_ERROR);
160 /* If the byte order of the file is not the same as the one
161 of the host convert the data now. */
162 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
163 for (size_t cnt = 0; cnt < shnum; ++cnt)
165 CONVERT (shdr[cnt].sh_name);
166 CONVERT (shdr[cnt].sh_type);
167 CONVERT (shdr[cnt].sh_flags);
168 CONVERT (shdr[cnt].sh_addr);
169 CONVERT (shdr[cnt].sh_offset);
170 CONVERT (shdr[cnt].sh_size);
171 CONVERT (shdr[cnt].sh_link);
172 CONVERT (shdr[cnt].sh_info);
173 CONVERT (shdr[cnt].sh_addralign);
174 CONVERT (shdr[cnt].sh_entsize);
179 /* The file descriptor was already enabled and not all data was
180 read. Undo the allocation. */
181 __libelf_seterrno (ELF_E_FD_DISABLED);
185 elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
186 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
191 /* Set the pointers in the `scn's. */
192 for (size_t cnt = 0; cnt < shnum; ++cnt)
193 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
194 = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
196 result = scn->shdr.ELFW(e,LIBELFBITS);
197 assert (result != NULL);
204 scn_valid (Elf_Scn *scn)
209 if (unlikely (scn->elf->state.elf.ehdr == NULL))
211 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
215 if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
217 __libelf_seterrno (ELF_E_INVALID_CLASS);
224 ElfW2(LIBELFBITS,Shdr) *
225 __elfw2(LIBELFBITS,getshdr_rdlock) (scn)
228 ElfW2(LIBELFBITS,Shdr) *result;
230 if (!scn_valid (scn))
233 result = scn->shdr.ELFW(e,LIBELFBITS);
236 rwlock_unlock (scn->elf->lock);
237 rwlock_wrlock (scn->elf->lock);
238 result = scn->shdr.ELFW(e,LIBELFBITS);
240 result = load_shdr_wrlock (scn);
246 ElfW2(LIBELFBITS,Shdr) *
247 __elfw2(LIBELFBITS,getshdr_wrlock) (scn)
250 ElfW2(LIBELFBITS,Shdr) *result;
252 if (!scn_valid (scn))
255 result = scn->shdr.ELFW(e,LIBELFBITS);
257 result = load_shdr_wrlock (scn);
262 ElfW2(LIBELFBITS,Shdr) *
263 elfw2(LIBELFBITS,getshdr) (scn)
266 ElfW2(LIBELFBITS,Shdr) *result;
268 if (!scn_valid (scn))
271 rwlock_rdlock (scn->elf->lock);
272 result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
273 rwlock_unlock (scn->elf->lock);