blob: cf7a41fd7d0f0cb6efba730ca0aff19e83994aa7 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return section header.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 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>
Ulrich Drepper6abe27b2005-08-29 06:25:06 +000023#include <errno.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000024#include <unistd.h>
25
Ulrich Drepper6abe27b2005-08-29 06:25:06 +000026#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000027#include "libelfP.h"
28#include "common.h"
29
30#ifndef LIBELFBITS
31# define LIBELFBITS 32
32#endif
33
34
35ElfW2(LIBELFBITS,Shdr) *
36elfw2(LIBELFBITS,getshdr) (scn)
37 Elf_Scn *scn;
38{
39 ElfW2(LIBELFBITS,Shdr) *result;
40
41 if (scn == NULL)
42 return NULL;
43
44 if (unlikely (scn->elf->state.elf.ehdr == NULL))
45 {
46 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
47 return NULL;
48 }
49
50 if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
51 {
52 __libelf_seterrno (ELF_E_INVALID_CLASS);
53 return NULL;
54 }
55
56 result = scn->shdr.ELFW(e,LIBELFBITS);
57 if (result == NULL)
58 {
59 /* Read the section header table. */
60 Elf *elf = scn->elf;
61 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
62
63 rwlock_wrlock (elf->lock);
64
65 /* Try again, maybe the data is there now. */
66 result = scn->shdr.ELFW(e,LIBELFBITS);
67 if (result != NULL)
68 goto out;
69
70 size_t shnum;
71 if (INTUSE (elf_getshnum) (elf, &shnum) != 0)
72 goto out;
73 size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
74
75 /* Allocate memory for the program headers. We know the number
76 of entries from the ELF header. */
77 ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
78 (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
79 if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
80 {
81 __libelf_seterrno (ELF_E_NOMEM);
82 goto out;
83 }
84 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
85
86 if (elf->map_address != NULL)
87 {
88 ElfW2(LIBELFBITS,Shdr) *notcvt;
89
90 /* All the data is already mapped. If we could use it
91 directly this would already have happened. */
92 assert (ehdr->e_ident[EI_DATA] != MY_ELFDATA
93 || (! ALLOW_UNALIGNED
94 && (ehdr->e_shoff
95 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
96
97 /* Now copy the data and at the same time convert the byte
98 order. */
99 if (ALLOW_UNALIGNED
100 || (ehdr->e_shoff
101 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0)
102 notcvt = (ElfW2(LIBELFBITS,Shdr) *)
103 ((char *) elf->map_address
104 + elf->start_offset + ehdr->e_shoff);
105 else
106 {
107 notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size);
108 memcpy (notcvt, ((char *) elf->map_address
109 + elf->start_offset + ehdr->e_shoff),
110 size);
111 }
112
113 for (size_t cnt = 0; cnt < shnum; ++cnt)
114 {
115 CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
116 CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
117 CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
118 CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
119 CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
120 CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
121 CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
122 CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
123 CONVERT_TO (shdr[cnt].sh_addralign, notcvt[cnt].sh_addralign);
124 CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
125 }
126 }
Ulrich Drepper6abe27b2005-08-29 06:25:06 +0000127 else if (likely (elf->fildes != -1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000128 {
129 /* Read the header. */
Ulrich Drepper6abe27b2005-08-29 06:25:06 +0000130 ssize_t n = pread_retry (elf->fildes,
131 elf->state.ELFW(elf,LIBELFBITS).shdr, size,
132 elf->start_offset + ehdr->e_shoff);
133 if (unlikely ((size_t) n != size))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000134 {
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 (size_t 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 (size_t 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}
185INTDEF(elfw2(LIBELFBITS,getshdr))