1 /* Return section header.
2 Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014, 2015 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/>. */
42 # define LIBELFBITS 32
46 static ElfW2(LIBELFBITS
,Shdr
) *
47 load_shdr_wrlock (Elf_Scn
*scn
)
49 ElfW2(LIBELFBITS
,Shdr
) *result
;
51 /* Read the section header table. */
53 ElfW2(LIBELFBITS
,Ehdr
) *ehdr
= elf
->state
.ELFW(elf
,LIBELFBITS
).ehdr
;
55 /* Try again, maybe the data is there now. */
56 result
= scn
->shdr
.ELFW(e
,LIBELFBITS
);
61 if (__elf_getshdrnum_rdlock (elf
, &shnum
) != 0
62 || shnum
> SIZE_MAX
/ sizeof (ElfW2(LIBELFBITS
,Shdr
)))
64 size_t size
= shnum
* sizeof (ElfW2(LIBELFBITS
,Shdr
));
66 /* Allocate memory for the section headers. We know the number
67 of entries from the ELF header. */
68 ElfW2(LIBELFBITS
,Shdr
) *shdr
= elf
->state
.ELFW(elf
,LIBELFBITS
).shdr
=
69 (ElfW2(LIBELFBITS
,Shdr
) *) malloc (size
);
70 if (elf
->state
.ELFW(elf
,LIBELFBITS
).shdr
== NULL
)
72 __libelf_seterrno (ELF_E_NOMEM
);
75 elf
->state
.ELFW(elf
,LIBELFBITS
).shdr_malloced
= 1;
77 if (elf
->map_address
!= NULL
)
79 /* First see whether the information in the ELF header is
80 valid and it does not ask for too much. */
81 if (unlikely (ehdr
->e_shoff
>= elf
->maximum_size
)
82 || unlikely (elf
->maximum_size
- ehdr
->e_shoff
< size
))
84 /* Something is wrong. */
85 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER
);
89 ElfW2(LIBELFBITS
,Shdr
) *notcvt
;
91 /* All the data is already mapped. If we could use it
92 directly this would already have happened. Unless
93 we allocated the memory ourselves and the ELF_F_MALLOCED
95 void *file_shdr
= ((char *) elf
->map_address
96 + elf
->start_offset
+ ehdr
->e_shoff
);
98 assert ((elf
->flags
& ELF_F_MALLOCED
)
99 || ehdr
->e_ident
[EI_DATA
] != MY_ELFDATA
100 || elf
->cmd
== ELF_C_READ_MMAP
101 || (! ALLOW_UNALIGNED
102 && ((uintptr_t) file_shdr
103 & (__alignof__ (ElfW2(LIBELFBITS
,Shdr
)) - 1)) != 0));
105 /* Now copy the data and at the same time convert the byte order. */
106 if (ehdr
->e_ident
[EI_DATA
] == MY_ELFDATA
)
108 assert ((elf
->flags
& ELF_F_MALLOCED
)
109 || elf
->cmd
== ELF_C_READ_MMAP
110 || ! ALLOW_UNALIGNED
);
111 memcpy (shdr
, file_shdr
, size
);
115 bool copy
= ! (ALLOW_UNALIGNED
116 || ((uintptr_t) file_shdr
117 & (__alignof__ (ElfW2(LIBELFBITS
,Shdr
)) - 1))
120 notcvt
= (ElfW2(LIBELFBITS
,Shdr
) *)
121 ((char *) elf
->map_address
122 + elf
->start_offset
+ ehdr
->e_shoff
);
125 notcvt
= (ElfW2(LIBELFBITS
,Shdr
) *) malloc (size
);
126 if (unlikely (notcvt
== NULL
))
128 __libelf_seterrno (ELF_E_NOMEM
);
131 memcpy (notcvt
, ((char *) elf
->map_address
132 + elf
->start_offset
+ ehdr
->e_shoff
),
136 for (size_t cnt
= 0; cnt
< shnum
; ++cnt
)
138 CONVERT_TO (shdr
[cnt
].sh_name
, notcvt
[cnt
].sh_name
);
139 CONVERT_TO (shdr
[cnt
].sh_type
, notcvt
[cnt
].sh_type
);
140 CONVERT_TO (shdr
[cnt
].sh_flags
, notcvt
[cnt
].sh_flags
);
141 CONVERT_TO (shdr
[cnt
].sh_addr
, notcvt
[cnt
].sh_addr
);
142 CONVERT_TO (shdr
[cnt
].sh_offset
, notcvt
[cnt
].sh_offset
);
143 CONVERT_TO (shdr
[cnt
].sh_size
, notcvt
[cnt
].sh_size
);
144 CONVERT_TO (shdr
[cnt
].sh_link
, notcvt
[cnt
].sh_link
);
145 CONVERT_TO (shdr
[cnt
].sh_info
, notcvt
[cnt
].sh_info
);
146 CONVERT_TO (shdr
[cnt
].sh_addralign
,
147 notcvt
[cnt
].sh_addralign
);
148 CONVERT_TO (shdr
[cnt
].sh_entsize
, notcvt
[cnt
].sh_entsize
);
150 /* If this is a section with an extended index add a
151 reference in the section which uses the extended
153 if (shdr
[cnt
].sh_type
== SHT_SYMTAB_SHNDX
154 && shdr
[cnt
].sh_link
< shnum
)
155 elf
->state
.ELFW(elf
,LIBELFBITS
).scns
.data
[shdr
[cnt
].sh_link
].shndx_index
158 /* Set the own shndx_index field in case it has not yet
160 if (elf
->state
.ELFW(elf
,LIBELFBITS
).scns
.data
[cnt
].shndx_index
== 0)
161 elf
->state
.ELFW(elf
,LIBELFBITS
).scns
.data
[cnt
].shndx_index
169 else if (likely (elf
->fildes
!= -1))
171 /* Read the header. */
172 ssize_t n
= pread_retry (elf
->fildes
,
173 elf
->state
.ELFW(elf
,LIBELFBITS
).shdr
, size
,
174 elf
->start_offset
+ ehdr
->e_shoff
);
175 if (unlikely ((size_t) n
!= size
))
177 /* Severe problems. We cannot read the data. */
178 __libelf_seterrno (ELF_E_READ_ERROR
);
182 /* If the byte order of the file is not the same as the one
183 of the host convert the data now. */
184 if (ehdr
->e_ident
[EI_DATA
] != MY_ELFDATA
)
185 for (size_t cnt
= 0; cnt
< shnum
; ++cnt
)
187 CONVERT (shdr
[cnt
].sh_name
);
188 CONVERT (shdr
[cnt
].sh_type
);
189 CONVERT (shdr
[cnt
].sh_flags
);
190 CONVERT (shdr
[cnt
].sh_addr
);
191 CONVERT (shdr
[cnt
].sh_offset
);
192 CONVERT (shdr
[cnt
].sh_size
);
193 CONVERT (shdr
[cnt
].sh_link
);
194 CONVERT (shdr
[cnt
].sh_info
);
195 CONVERT (shdr
[cnt
].sh_addralign
);
196 CONVERT (shdr
[cnt
].sh_entsize
);
201 /* The file descriptor was already enabled and not all data was
202 read. Undo the allocation. */
203 __libelf_seterrno (ELF_E_FD_DISABLED
);
207 elf
->state
.ELFW(elf
,LIBELFBITS
).shdr
= NULL
;
208 elf
->state
.ELFW(elf
,LIBELFBITS
).shdr_malloced
= 0;
213 /* Set the pointers in the `scn's. */
214 for (size_t cnt
= 0; cnt
< shnum
; ++cnt
)
215 elf
->state
.ELFW(elf
,LIBELFBITS
).scns
.data
[cnt
].shdr
.ELFW(e
,LIBELFBITS
)
216 = &elf
->state
.ELFW(elf
,LIBELFBITS
).shdr
[cnt
];
218 result
= scn
->shdr
.ELFW(e
,LIBELFBITS
);
219 assert (result
!= NULL
);
226 scn_valid (Elf_Scn
*scn
)
231 if (unlikely (scn
->elf
->state
.elf
.ehdr
== NULL
))
233 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR
);
237 if (unlikely (scn
->elf
->class != ELFW(ELFCLASS
,LIBELFBITS
)))
239 __libelf_seterrno (ELF_E_INVALID_CLASS
);
246 ElfW2(LIBELFBITS
,Shdr
) *
248 __elfw2(LIBELFBITS
,getshdr_rdlock
) (Elf_Scn
*scn
)
250 ElfW2(LIBELFBITS
,Shdr
) *result
;
252 if (!scn_valid (scn
))
255 result
= scn
->shdr
.ELFW(e
,LIBELFBITS
);
258 rwlock_unlock (scn
->elf
->lock
);
259 rwlock_wrlock (scn
->elf
->lock
);
260 result
= scn
->shdr
.ELFW(e
,LIBELFBITS
);
262 result
= load_shdr_wrlock (scn
);
268 ElfW2(LIBELFBITS
,Shdr
) *
270 __elfw2(LIBELFBITS
,getshdr_wrlock
) (Elf_Scn
*scn
)
272 ElfW2(LIBELFBITS
,Shdr
) *result
;
274 if (!scn_valid (scn
))
277 result
= scn
->shdr
.ELFW(e
,LIBELFBITS
);
279 result
= load_shdr_wrlock (scn
);
284 ElfW2(LIBELFBITS
,Shdr
) *
285 elfw2(LIBELFBITS
,getshdr
) (Elf_Scn
*scn
)
287 ElfW2(LIBELFBITS
,Shdr
) *result
;
289 if (!scn_valid (scn
))
292 rwlock_rdlock (scn
->elf
->lock
);
293 result
= __elfw2(LIBELFBITS
,getshdr_rdlock
) (scn
);
294 rwlock_unlock (scn
->elf
->lock
);