1*7304104dSAndroid Build Coastguard Worker /* Return the next data element from the section after possibly converting it.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker Copyright (C) 2022 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 1998.
6*7304104dSAndroid Build Coastguard Worker
7*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker it under the terms of either
9*7304104dSAndroid Build Coastguard Worker
10*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
11*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
12*7304104dSAndroid Build Coastguard Worker your option) any later version
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker or
15*7304104dSAndroid Build Coastguard Worker
16*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
17*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
18*7304104dSAndroid Build Coastguard Worker your option) any later version
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
21*7304104dSAndroid Build Coastguard Worker
22*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
23*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
24*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25*7304104dSAndroid Build Coastguard Worker General Public License for more details.
26*7304104dSAndroid Build Coastguard Worker
27*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
28*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
29*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
30*7304104dSAndroid Build Coastguard Worker
31*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
32*7304104dSAndroid Build Coastguard Worker # include <config.h>
33*7304104dSAndroid Build Coastguard Worker #endif
34*7304104dSAndroid Build Coastguard Worker
35*7304104dSAndroid Build Coastguard Worker #include <errno.h>
36*7304104dSAndroid Build Coastguard Worker #include <stddef.h>
37*7304104dSAndroid Build Coastguard Worker #include <string.h>
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
40*7304104dSAndroid Build Coastguard Worker #include "common.h"
41*7304104dSAndroid Build Coastguard Worker #include "elf-knowledge.h"
42*7304104dSAndroid Build Coastguard Worker
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker #define TYPEIDX(Sh_Type) \
45*7304104dSAndroid Build Coastguard Worker (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
46*7304104dSAndroid Build Coastguard Worker ? Sh_Type \
47*7304104dSAndroid Build Coastguard Worker : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
48*7304104dSAndroid Build Coastguard Worker ? SHT_NUM + Sh_Type - SHT_GNU_HASH \
49*7304104dSAndroid Build Coastguard Worker : 0))
50*7304104dSAndroid Build Coastguard Worker
51*7304104dSAndroid Build Coastguard Worker /* Associate section types with libelf types. */
52*7304104dSAndroid Build Coastguard Worker static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
53*7304104dSAndroid Build Coastguard Worker {
54*7304104dSAndroid Build Coastguard Worker [SHT_SYMTAB] = ELF_T_SYM,
55*7304104dSAndroid Build Coastguard Worker [SHT_RELA] = ELF_T_RELA,
56*7304104dSAndroid Build Coastguard Worker [SHT_HASH] = ELF_T_WORD,
57*7304104dSAndroid Build Coastguard Worker [SHT_DYNAMIC] = ELF_T_DYN,
58*7304104dSAndroid Build Coastguard Worker [SHT_REL] = ELF_T_REL,
59*7304104dSAndroid Build Coastguard Worker [SHT_DYNSYM] = ELF_T_SYM,
60*7304104dSAndroid Build Coastguard Worker [SHT_INIT_ARRAY] = ELF_T_ADDR,
61*7304104dSAndroid Build Coastguard Worker [SHT_FINI_ARRAY] = ELF_T_ADDR,
62*7304104dSAndroid Build Coastguard Worker [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
63*7304104dSAndroid Build Coastguard Worker [SHT_GROUP] = ELF_T_WORD,
64*7304104dSAndroid Build Coastguard Worker [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
65*7304104dSAndroid Build Coastguard Worker [SHT_NOTE] = ELF_T_NHDR, /* Need alignment to guess ELF_T_NHDR8. */
66*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
67*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
68*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
69*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
70*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
71*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
72*7304104dSAndroid Build Coastguard Worker [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
73*7304104dSAndroid Build Coastguard Worker };
74*7304104dSAndroid Build Coastguard Worker
75*7304104dSAndroid Build Coastguard Worker /* Associate libelf types with their internal alignment requirements. */
76*7304104dSAndroid Build Coastguard Worker const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
77*7304104dSAndroid Build Coastguard Worker {
78*7304104dSAndroid Build Coastguard Worker # define TYPE_ALIGNS(Bits) \
79*7304104dSAndroid Build Coastguard Worker [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
80*7304104dSAndroid Build Coastguard Worker [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
81*7304104dSAndroid Build Coastguard Worker [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
82*7304104dSAndroid Build Coastguard Worker [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \
83*7304104dSAndroid Build Coastguard Worker [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \
84*7304104dSAndroid Build Coastguard Worker [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \
85*7304104dSAndroid Build Coastguard Worker [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \
86*7304104dSAndroid Build Coastguard Worker [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
87*7304104dSAndroid Build Coastguard Worker [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \
88*7304104dSAndroid Build Coastguard Worker [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \
89*7304104dSAndroid Build Coastguard Worker [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
90*7304104dSAndroid Build Coastguard Worker [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
91*7304104dSAndroid Build Coastguard Worker [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
92*7304104dSAndroid Build Coastguard Worker [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \
93*7304104dSAndroid Build Coastguard Worker [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \
94*7304104dSAndroid Build Coastguard Worker [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \
95*7304104dSAndroid Build Coastguard Worker [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \
96*7304104dSAndroid Build Coastguard Worker [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \
97*7304104dSAndroid Build Coastguard Worker [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \
98*7304104dSAndroid Build Coastguard Worker [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
99*7304104dSAndroid Build Coastguard Worker [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
100*7304104dSAndroid Build Coastguard Worker [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
101*7304104dSAndroid Build Coastguard Worker [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
102*7304104dSAndroid Build Coastguard Worker [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
103*7304104dSAndroid Build Coastguard Worker [ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */
104*7304104dSAndroid Build Coastguard Worker [ELFCLASS32 - 1] = {
105*7304104dSAndroid Build Coastguard Worker TYPE_ALIGNS (32),
106*7304104dSAndroid Build Coastguard Worker [ELF_T_GNUHASH] = __alignof__ (Elf32_Word),
107*7304104dSAndroid Build Coastguard Worker },
108*7304104dSAndroid Build Coastguard Worker [ELFCLASS64 - 1] = {
109*7304104dSAndroid Build Coastguard Worker TYPE_ALIGNS (64),
110*7304104dSAndroid Build Coastguard Worker [ELF_T_GNUHASH] = __alignof__ (Elf64_Xword),
111*7304104dSAndroid Build Coastguard Worker },
112*7304104dSAndroid Build Coastguard Worker # undef TYPE_ALIGNS
113*7304104dSAndroid Build Coastguard Worker };
114*7304104dSAndroid Build Coastguard Worker
115*7304104dSAndroid Build Coastguard Worker
116*7304104dSAndroid Build Coastguard Worker Elf_Type
117*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_data_type(GElf_Ehdr * ehdr,int sh_type,GElf_Xword align)118*7304104dSAndroid Build Coastguard Worker __libelf_data_type (GElf_Ehdr *ehdr, int sh_type, GElf_Xword align)
119*7304104dSAndroid Build Coastguard Worker {
120*7304104dSAndroid Build Coastguard Worker /* Some broken ELF ABI for 64-bit machines use the wrong hash table
121*7304104dSAndroid Build Coastguard Worker entry size. See elf-knowledge.h for more information. */
122*7304104dSAndroid Build Coastguard Worker if (sh_type == SHT_HASH && ehdr->e_ident[EI_CLASS] == ELFCLASS64)
123*7304104dSAndroid Build Coastguard Worker {
124*7304104dSAndroid Build Coastguard Worker return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
125*7304104dSAndroid Build Coastguard Worker }
126*7304104dSAndroid Build Coastguard Worker else
127*7304104dSAndroid Build Coastguard Worker {
128*7304104dSAndroid Build Coastguard Worker Elf_Type t = shtype_map[TYPEIDX (sh_type)];
129*7304104dSAndroid Build Coastguard Worker /* Special case for GNU Property notes. */
130*7304104dSAndroid Build Coastguard Worker if (t == ELF_T_NHDR && align == 8)
131*7304104dSAndroid Build Coastguard Worker t = ELF_T_NHDR8;
132*7304104dSAndroid Build Coastguard Worker return t;
133*7304104dSAndroid Build Coastguard Worker }
134*7304104dSAndroid Build Coastguard Worker }
135*7304104dSAndroid Build Coastguard Worker
136*7304104dSAndroid Build Coastguard Worker /* Convert the data in the current section. */
137*7304104dSAndroid Build Coastguard Worker static void
convert_data(Elf_Scn * scn,int eclass,int data,size_t size,Elf_Type type)138*7304104dSAndroid Build Coastguard Worker convert_data (Elf_Scn *scn, int eclass,
139*7304104dSAndroid Build Coastguard Worker int data, size_t size, Elf_Type type)
140*7304104dSAndroid Build Coastguard Worker {
141*7304104dSAndroid Build Coastguard Worker const size_t align = __libelf_type_align (eclass, type);
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker /* Do we need to convert the data and/or adjust for alignment? */
144*7304104dSAndroid Build Coastguard Worker if (data == MY_ELFDATA || type == ELF_T_BYTE)
145*7304104dSAndroid Build Coastguard Worker {
146*7304104dSAndroid Build Coastguard Worker if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
147*7304104dSAndroid Build Coastguard Worker /* No need to copy, we can use the raw data. */
148*7304104dSAndroid Build Coastguard Worker scn->data_base = scn->rawdata_base;
149*7304104dSAndroid Build Coastguard Worker else
150*7304104dSAndroid Build Coastguard Worker {
151*7304104dSAndroid Build Coastguard Worker scn->data_base = malloc (size);
152*7304104dSAndroid Build Coastguard Worker if (scn->data_base == NULL)
153*7304104dSAndroid Build Coastguard Worker {
154*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_NOMEM);
155*7304104dSAndroid Build Coastguard Worker return;
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker /* The copy will be appropriately aligned for direct access. */
159*7304104dSAndroid Build Coastguard Worker memcpy (scn->data_base, scn->rawdata_base, size);
160*7304104dSAndroid Build Coastguard Worker }
161*7304104dSAndroid Build Coastguard Worker }
162*7304104dSAndroid Build Coastguard Worker else
163*7304104dSAndroid Build Coastguard Worker {
164*7304104dSAndroid Build Coastguard Worker xfct_t fp;
165*7304104dSAndroid Build Coastguard Worker
166*7304104dSAndroid Build Coastguard Worker scn->data_base = malloc (size);
167*7304104dSAndroid Build Coastguard Worker if (scn->data_base == NULL)
168*7304104dSAndroid Build Coastguard Worker {
169*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_NOMEM);
170*7304104dSAndroid Build Coastguard Worker return;
171*7304104dSAndroid Build Coastguard Worker }
172*7304104dSAndroid Build Coastguard Worker
173*7304104dSAndroid Build Coastguard Worker /* Make sure the source is correctly aligned for the conversion
174*7304104dSAndroid Build Coastguard Worker function to directly access the data elements. */
175*7304104dSAndroid Build Coastguard Worker char *rawdata_source;
176*7304104dSAndroid Build Coastguard Worker if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
177*7304104dSAndroid Build Coastguard Worker rawdata_source = scn->rawdata_base;
178*7304104dSAndroid Build Coastguard Worker else
179*7304104dSAndroid Build Coastguard Worker {
180*7304104dSAndroid Build Coastguard Worker rawdata_source = malloc (size);
181*7304104dSAndroid Build Coastguard Worker if (rawdata_source == NULL)
182*7304104dSAndroid Build Coastguard Worker {
183*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_NOMEM);
184*7304104dSAndroid Build Coastguard Worker return;
185*7304104dSAndroid Build Coastguard Worker }
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker /* The copy will be appropriately aligned for direct access. */
188*7304104dSAndroid Build Coastguard Worker memcpy (rawdata_source, scn->rawdata_base, size);
189*7304104dSAndroid Build Coastguard Worker }
190*7304104dSAndroid Build Coastguard Worker
191*7304104dSAndroid Build Coastguard Worker /* Get the conversion function. */
192*7304104dSAndroid Build Coastguard Worker fp = __elf_xfctstom[eclass - 1][type];
193*7304104dSAndroid Build Coastguard Worker
194*7304104dSAndroid Build Coastguard Worker fp (scn->data_base, rawdata_source, size, 0);
195*7304104dSAndroid Build Coastguard Worker
196*7304104dSAndroid Build Coastguard Worker if (rawdata_source != scn->rawdata_base)
197*7304104dSAndroid Build Coastguard Worker free (rawdata_source);
198*7304104dSAndroid Build Coastguard Worker }
199*7304104dSAndroid Build Coastguard Worker
200*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_buf = scn->data_base;
201*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_size = size;
202*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_type = type;
203*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
204*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
205*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
206*7304104dSAndroid Build Coastguard Worker
207*7304104dSAndroid Build Coastguard Worker scn->data_list.data.s = scn;
208*7304104dSAndroid Build Coastguard Worker }
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker
211*7304104dSAndroid Build Coastguard Worker /* Store the information for the raw data in the `rawdata' element. */
212*7304104dSAndroid Build Coastguard Worker int
213*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_set_rawdata_wrlock(Elf_Scn * scn)214*7304104dSAndroid Build Coastguard Worker __libelf_set_rawdata_wrlock (Elf_Scn *scn)
215*7304104dSAndroid Build Coastguard Worker {
216*7304104dSAndroid Build Coastguard Worker Elf64_Off offset;
217*7304104dSAndroid Build Coastguard Worker Elf64_Xword size;
218*7304104dSAndroid Build Coastguard Worker Elf64_Xword align;
219*7304104dSAndroid Build Coastguard Worker Elf64_Xword flags;
220*7304104dSAndroid Build Coastguard Worker int type;
221*7304104dSAndroid Build Coastguard Worker Elf *elf = scn->elf;
222*7304104dSAndroid Build Coastguard Worker
223*7304104dSAndroid Build Coastguard Worker if (elf->class == ELFCLASS32)
224*7304104dSAndroid Build Coastguard Worker {
225*7304104dSAndroid Build Coastguard Worker Elf32_Shdr *shdr
226*7304104dSAndroid Build Coastguard Worker = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
227*7304104dSAndroid Build Coastguard Worker
228*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
229*7304104dSAndroid Build Coastguard Worker /* Something went terribly wrong. */
230*7304104dSAndroid Build Coastguard Worker return 1;
231*7304104dSAndroid Build Coastguard Worker
232*7304104dSAndroid Build Coastguard Worker offset = shdr->sh_offset;
233*7304104dSAndroid Build Coastguard Worker size = shdr->sh_size;
234*7304104dSAndroid Build Coastguard Worker type = shdr->sh_type;
235*7304104dSAndroid Build Coastguard Worker align = shdr->sh_addralign;
236*7304104dSAndroid Build Coastguard Worker flags = shdr->sh_flags;
237*7304104dSAndroid Build Coastguard Worker }
238*7304104dSAndroid Build Coastguard Worker else
239*7304104dSAndroid Build Coastguard Worker {
240*7304104dSAndroid Build Coastguard Worker Elf64_Shdr *shdr
241*7304104dSAndroid Build Coastguard Worker = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
242*7304104dSAndroid Build Coastguard Worker
243*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
244*7304104dSAndroid Build Coastguard Worker /* Something went terribly wrong. */
245*7304104dSAndroid Build Coastguard Worker return 1;
246*7304104dSAndroid Build Coastguard Worker
247*7304104dSAndroid Build Coastguard Worker offset = shdr->sh_offset;
248*7304104dSAndroid Build Coastguard Worker size = shdr->sh_size;
249*7304104dSAndroid Build Coastguard Worker type = shdr->sh_type;
250*7304104dSAndroid Build Coastguard Worker align = shdr->sh_addralign;
251*7304104dSAndroid Build Coastguard Worker flags = shdr->sh_flags;
252*7304104dSAndroid Build Coastguard Worker }
253*7304104dSAndroid Build Coastguard Worker
254*7304104dSAndroid Build Coastguard Worker /* If the section has no data (for whatever reason), leave the `d_buf'
255*7304104dSAndroid Build Coastguard Worker pointer NULL. */
256*7304104dSAndroid Build Coastguard Worker if (size != 0 && type != SHT_NOBITS)
257*7304104dSAndroid Build Coastguard Worker {
258*7304104dSAndroid Build Coastguard Worker /* First a test whether the section is valid at all. */
259*7304104dSAndroid Build Coastguard Worker size_t entsize;
260*7304104dSAndroid Build Coastguard Worker
261*7304104dSAndroid Build Coastguard Worker /* Compressed data has a header, but then compressed data.
262*7304104dSAndroid Build Coastguard Worker Make sure to set the alignment of the header explicitly,
263*7304104dSAndroid Build Coastguard Worker don't trust the file alignment for the section, it is
264*7304104dSAndroid Build Coastguard Worker often wrong. */
265*7304104dSAndroid Build Coastguard Worker if ((flags & SHF_COMPRESSED) != 0)
266*7304104dSAndroid Build Coastguard Worker {
267*7304104dSAndroid Build Coastguard Worker entsize = 1;
268*7304104dSAndroid Build Coastguard Worker align = __libelf_type_align (elf->class, ELF_T_CHDR);
269*7304104dSAndroid Build Coastguard Worker }
270*7304104dSAndroid Build Coastguard Worker else if (type == SHT_HASH)
271*7304104dSAndroid Build Coastguard Worker {
272*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
273*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
274*7304104dSAndroid Build Coastguard Worker if (unlikely (ehdr == NULL))
275*7304104dSAndroid Build Coastguard Worker return 1;
276*7304104dSAndroid Build Coastguard Worker entsize = SH_ENTSIZE_HASH (ehdr);
277*7304104dSAndroid Build Coastguard Worker }
278*7304104dSAndroid Build Coastguard Worker else
279*7304104dSAndroid Build Coastguard Worker {
280*7304104dSAndroid Build Coastguard Worker Elf_Type t = shtype_map[TYPEIDX (type)];
281*7304104dSAndroid Build Coastguard Worker if (t == ELF_T_NHDR && align == 8)
282*7304104dSAndroid Build Coastguard Worker t = ELF_T_NHDR8;
283*7304104dSAndroid Build Coastguard Worker if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
284*7304104dSAndroid Build Coastguard Worker || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
285*7304104dSAndroid Build Coastguard Worker entsize = 1;
286*7304104dSAndroid Build Coastguard Worker else
287*7304104dSAndroid Build Coastguard Worker entsize = __libelf_type_sizes[elf->class - 1][t];
288*7304104dSAndroid Build Coastguard Worker }
289*7304104dSAndroid Build Coastguard Worker
290*7304104dSAndroid Build Coastguard Worker /* We assume it is an array of bytes if it is none of the structured
291*7304104dSAndroid Build Coastguard Worker sections we know of. */
292*7304104dSAndroid Build Coastguard Worker if (entsize == 0)
293*7304104dSAndroid Build Coastguard Worker entsize = 1;
294*7304104dSAndroid Build Coastguard Worker
295*7304104dSAndroid Build Coastguard Worker if (unlikely (size % entsize != 0))
296*7304104dSAndroid Build Coastguard Worker {
297*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_INVALID_DATA);
298*7304104dSAndroid Build Coastguard Worker return 1;
299*7304104dSAndroid Build Coastguard Worker }
300*7304104dSAndroid Build Coastguard Worker
301*7304104dSAndroid Build Coastguard Worker /* We can use the mapped or loaded data if available. */
302*7304104dSAndroid Build Coastguard Worker if (elf->map_address != NULL)
303*7304104dSAndroid Build Coastguard Worker {
304*7304104dSAndroid Build Coastguard Worker /* First see whether the information in the section header is
305*7304104dSAndroid Build Coastguard Worker valid and it does not ask for too much. Check for unsigned
306*7304104dSAndroid Build Coastguard Worker overflow. */
307*7304104dSAndroid Build Coastguard Worker if (unlikely (offset > elf->maximum_size
308*7304104dSAndroid Build Coastguard Worker || elf->maximum_size - offset < size))
309*7304104dSAndroid Build Coastguard Worker {
310*7304104dSAndroid Build Coastguard Worker /* Something is wrong. */
311*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
312*7304104dSAndroid Build Coastguard Worker return 1;
313*7304104dSAndroid Build Coastguard Worker }
314*7304104dSAndroid Build Coastguard Worker
315*7304104dSAndroid Build Coastguard Worker scn->rawdata_base = scn->rawdata.d.d_buf
316*7304104dSAndroid Build Coastguard Worker = (char *) elf->map_address + elf->start_offset + offset;
317*7304104dSAndroid Build Coastguard Worker }
318*7304104dSAndroid Build Coastguard Worker else if (likely (elf->fildes != -1))
319*7304104dSAndroid Build Coastguard Worker {
320*7304104dSAndroid Build Coastguard Worker /* First see whether the information in the section header is
321*7304104dSAndroid Build Coastguard Worker valid and it does not ask for too much. Check for unsigned
322*7304104dSAndroid Build Coastguard Worker overflow. */
323*7304104dSAndroid Build Coastguard Worker if (unlikely (offset > elf->maximum_size
324*7304104dSAndroid Build Coastguard Worker || elf->maximum_size - offset < size))
325*7304104dSAndroid Build Coastguard Worker {
326*7304104dSAndroid Build Coastguard Worker /* Something is wrong. */
327*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
328*7304104dSAndroid Build Coastguard Worker return 1;
329*7304104dSAndroid Build Coastguard Worker }
330*7304104dSAndroid Build Coastguard Worker
331*7304104dSAndroid Build Coastguard Worker /* We have to read the data from the file. Allocate the needed
332*7304104dSAndroid Build Coastguard Worker memory. */
333*7304104dSAndroid Build Coastguard Worker scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size);
334*7304104dSAndroid Build Coastguard Worker if (scn->rawdata.d.d_buf == NULL)
335*7304104dSAndroid Build Coastguard Worker {
336*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_NOMEM);
337*7304104dSAndroid Build Coastguard Worker return 1;
338*7304104dSAndroid Build Coastguard Worker }
339*7304104dSAndroid Build Coastguard Worker
340*7304104dSAndroid Build Coastguard Worker ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
341*7304104dSAndroid Build Coastguard Worker elf->start_offset + offset);
342*7304104dSAndroid Build Coastguard Worker if (unlikely ((size_t) n != size))
343*7304104dSAndroid Build Coastguard Worker {
344*7304104dSAndroid Build Coastguard Worker /* Cannot read the data. */
345*7304104dSAndroid Build Coastguard Worker free (scn->rawdata.d.d_buf);
346*7304104dSAndroid Build Coastguard Worker scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
347*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_READ_ERROR);
348*7304104dSAndroid Build Coastguard Worker return 1;
349*7304104dSAndroid Build Coastguard Worker }
350*7304104dSAndroid Build Coastguard Worker }
351*7304104dSAndroid Build Coastguard Worker else
352*7304104dSAndroid Build Coastguard Worker {
353*7304104dSAndroid Build Coastguard Worker /* The file descriptor is already closed, we cannot get the data
354*7304104dSAndroid Build Coastguard Worker anymore. */
355*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_FD_DISABLED);
356*7304104dSAndroid Build Coastguard Worker return 1;
357*7304104dSAndroid Build Coastguard Worker }
358*7304104dSAndroid Build Coastguard Worker }
359*7304104dSAndroid Build Coastguard Worker
360*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_size = size;
361*7304104dSAndroid Build Coastguard Worker
362*7304104dSAndroid Build Coastguard Worker /* Compressed data always has type ELF_T_CHDR regardless of the
363*7304104dSAndroid Build Coastguard Worker section type. */
364*7304104dSAndroid Build Coastguard Worker if ((flags & SHF_COMPRESSED) != 0)
365*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_type = ELF_T_CHDR;
366*7304104dSAndroid Build Coastguard Worker else
367*7304104dSAndroid Build Coastguard Worker {
368*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
369*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
370*7304104dSAndroid Build Coastguard Worker if (unlikely (ehdr == NULL))
371*7304104dSAndroid Build Coastguard Worker return 1;
372*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
373*7304104dSAndroid Build Coastguard Worker }
374*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_off = 0;
375*7304104dSAndroid Build Coastguard Worker
376*7304104dSAndroid Build Coastguard Worker /* Make sure the alignment makes sense. d_align should be aligned both
377*7304104dSAndroid Build Coastguard Worker in the section (trivially true since d_off is zero) and in the file.
378*7304104dSAndroid Build Coastguard Worker Unfortunately we cannot be too strict because there are ELF files
379*7304104dSAndroid Build Coastguard Worker out there that fail this requirement. We will try to fix those up
380*7304104dSAndroid Build Coastguard Worker in elf_update when writing out the image. But for very large
381*7304104dSAndroid Build Coastguard Worker alignment values this can bloat the image considerably. So here
382*7304104dSAndroid Build Coastguard Worker just check and clamp the alignment value to not be bigger than the
383*7304104dSAndroid Build Coastguard Worker actual offset of the data in the file. Given that there is always
384*7304104dSAndroid Build Coastguard Worker at least an ehdr this will only trigger for alignment values > 64
385*7304104dSAndroid Build Coastguard Worker which should be uncommon. */
386*7304104dSAndroid Build Coastguard Worker align = align ?: 1;
387*7304104dSAndroid Build Coastguard Worker if (type != SHT_NOBITS && align > offset)
388*7304104dSAndroid Build Coastguard Worker {
389*7304104dSAndroid Build Coastguard Worker /* Align the offset to the next power of two. Uses algorithm from
390*7304104dSAndroid Build Coastguard Worker https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
391*7304104dSAndroid Build Coastguard Worker align = offset - 1;
392*7304104dSAndroid Build Coastguard Worker align |= align >> 1;
393*7304104dSAndroid Build Coastguard Worker align |= align >> 2;
394*7304104dSAndroid Build Coastguard Worker align |= align >> 4;
395*7304104dSAndroid Build Coastguard Worker align |= align >> 8;
396*7304104dSAndroid Build Coastguard Worker align |= align >> 16;
397*7304104dSAndroid Build Coastguard Worker align |= align >> 32;
398*7304104dSAndroid Build Coastguard Worker align++;
399*7304104dSAndroid Build Coastguard Worker }
400*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_align = align;
401*7304104dSAndroid Build Coastguard Worker if (elf->class == ELFCLASS32
402*7304104dSAndroid Build Coastguard Worker || (offsetof (struct Elf, state.elf32.ehdr)
403*7304104dSAndroid Build Coastguard Worker == offsetof (struct Elf, state.elf64.ehdr)))
404*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_version =
405*7304104dSAndroid Build Coastguard Worker elf->state.elf32.ehdr->e_ident[EI_VERSION];
406*7304104dSAndroid Build Coastguard Worker else
407*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_version =
408*7304104dSAndroid Build Coastguard Worker elf->state.elf64.ehdr->e_ident[EI_VERSION];
409*7304104dSAndroid Build Coastguard Worker
410*7304104dSAndroid Build Coastguard Worker scn->rawdata.s = scn;
411*7304104dSAndroid Build Coastguard Worker
412*7304104dSAndroid Build Coastguard Worker scn->data_read = 1;
413*7304104dSAndroid Build Coastguard Worker
414*7304104dSAndroid Build Coastguard Worker /* We actually read data from the file. At least we tried. */
415*7304104dSAndroid Build Coastguard Worker scn->flags |= ELF_F_FILEDATA;
416*7304104dSAndroid Build Coastguard Worker
417*7304104dSAndroid Build Coastguard Worker return 0;
418*7304104dSAndroid Build Coastguard Worker }
419*7304104dSAndroid Build Coastguard Worker
420*7304104dSAndroid Build Coastguard Worker int
421*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_set_rawdata(Elf_Scn * scn)422*7304104dSAndroid Build Coastguard Worker __libelf_set_rawdata (Elf_Scn *scn)
423*7304104dSAndroid Build Coastguard Worker {
424*7304104dSAndroid Build Coastguard Worker int result;
425*7304104dSAndroid Build Coastguard Worker
426*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
427*7304104dSAndroid Build Coastguard Worker return 1;
428*7304104dSAndroid Build Coastguard Worker
429*7304104dSAndroid Build Coastguard Worker rwlock_wrlock (scn->elf->lock);
430*7304104dSAndroid Build Coastguard Worker result = __libelf_set_rawdata_wrlock (scn);
431*7304104dSAndroid Build Coastguard Worker rwlock_unlock (scn->elf->lock);
432*7304104dSAndroid Build Coastguard Worker
433*7304104dSAndroid Build Coastguard Worker return result;
434*7304104dSAndroid Build Coastguard Worker }
435*7304104dSAndroid Build Coastguard Worker
436*7304104dSAndroid Build Coastguard Worker void
437*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_set_data_list_rdlock(Elf_Scn * scn,int wrlocked)438*7304104dSAndroid Build Coastguard Worker __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
439*7304104dSAndroid Build Coastguard Worker {
440*7304104dSAndroid Build Coastguard Worker if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
441*7304104dSAndroid Build Coastguard Worker {
442*7304104dSAndroid Build Coastguard Worker Elf *elf = scn->elf;
443*7304104dSAndroid Build Coastguard Worker
444*7304104dSAndroid Build Coastguard Worker /* Upgrade the lock to a write lock if necessary and check
445*7304104dSAndroid Build Coastguard Worker nobody else already did the work. */
446*7304104dSAndroid Build Coastguard Worker if (!wrlocked)
447*7304104dSAndroid Build Coastguard Worker {
448*7304104dSAndroid Build Coastguard Worker rwlock_unlock (elf->lock);
449*7304104dSAndroid Build Coastguard Worker rwlock_wrlock (elf->lock);
450*7304104dSAndroid Build Coastguard Worker if (scn->data_list_rear != NULL)
451*7304104dSAndroid Build Coastguard Worker return;
452*7304104dSAndroid Build Coastguard Worker }
453*7304104dSAndroid Build Coastguard Worker
454*7304104dSAndroid Build Coastguard Worker /* Convert according to the version and the type. */
455*7304104dSAndroid Build Coastguard Worker convert_data (scn, elf->class,
456*7304104dSAndroid Build Coastguard Worker (elf->class == ELFCLASS32
457*7304104dSAndroid Build Coastguard Worker || (offsetof (struct Elf, state.elf32.ehdr)
458*7304104dSAndroid Build Coastguard Worker == offsetof (struct Elf, state.elf64.ehdr))
459*7304104dSAndroid Build Coastguard Worker ? elf->state.elf32.ehdr->e_ident[EI_DATA]
460*7304104dSAndroid Build Coastguard Worker : elf->state.elf64.ehdr->e_ident[EI_DATA]),
461*7304104dSAndroid Build Coastguard Worker scn->rawdata.d.d_size, scn->rawdata.d.d_type);
462*7304104dSAndroid Build Coastguard Worker }
463*7304104dSAndroid Build Coastguard Worker else
464*7304104dSAndroid Build Coastguard Worker {
465*7304104dSAndroid Build Coastguard Worker /* This is an empty or NOBITS section. There is no buffer but
466*7304104dSAndroid Build Coastguard Worker the size information etc is important. */
467*7304104dSAndroid Build Coastguard Worker scn->data_list.data.d = scn->rawdata.d;
468*7304104dSAndroid Build Coastguard Worker scn->data_list.data.s = scn;
469*7304104dSAndroid Build Coastguard Worker }
470*7304104dSAndroid Build Coastguard Worker
471*7304104dSAndroid Build Coastguard Worker scn->data_list_rear = &scn->data_list;
472*7304104dSAndroid Build Coastguard Worker }
473*7304104dSAndroid Build Coastguard Worker
474*7304104dSAndroid Build Coastguard Worker Elf_Data *
475*7304104dSAndroid Build Coastguard Worker internal_function
__elf_getdata_rdlock(Elf_Scn * scn,Elf_Data * data)476*7304104dSAndroid Build Coastguard Worker __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
477*7304104dSAndroid Build Coastguard Worker {
478*7304104dSAndroid Build Coastguard Worker Elf_Data *result = NULL;
479*7304104dSAndroid Build Coastguard Worker Elf *elf;
480*7304104dSAndroid Build Coastguard Worker int locked = 0;
481*7304104dSAndroid Build Coastguard Worker
482*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
483*7304104dSAndroid Build Coastguard Worker return NULL;
484*7304104dSAndroid Build Coastguard Worker
485*7304104dSAndroid Build Coastguard Worker if (unlikely (scn->elf->kind != ELF_K_ELF))
486*7304104dSAndroid Build Coastguard Worker {
487*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_INVALID_HANDLE);
488*7304104dSAndroid Build Coastguard Worker return NULL;
489*7304104dSAndroid Build Coastguard Worker }
490*7304104dSAndroid Build Coastguard Worker
491*7304104dSAndroid Build Coastguard Worker /* We will need this multiple times later on. */
492*7304104dSAndroid Build Coastguard Worker elf = scn->elf;
493*7304104dSAndroid Build Coastguard Worker
494*7304104dSAndroid Build Coastguard Worker /* If `data' is not NULL this means we are not addressing the initial
495*7304104dSAndroid Build Coastguard Worker data in the file. But this also means this data is already read
496*7304104dSAndroid Build Coastguard Worker (since otherwise it is not possible to have a valid `data' pointer)
497*7304104dSAndroid Build Coastguard Worker and all the data structures are initialized as well. In this case
498*7304104dSAndroid Build Coastguard Worker we can simply walk the list of data records. */
499*7304104dSAndroid Build Coastguard Worker if (data != NULL)
500*7304104dSAndroid Build Coastguard Worker {
501*7304104dSAndroid Build Coastguard Worker Elf_Data_List *runp;
502*7304104dSAndroid Build Coastguard Worker
503*7304104dSAndroid Build Coastguard Worker /* It is not possible that if DATA is not NULL the first entry is
504*7304104dSAndroid Build Coastguard Worker returned. But this also means that there must be a first data
505*7304104dSAndroid Build Coastguard Worker entry. */
506*7304104dSAndroid Build Coastguard Worker if (scn->data_list_rear == NULL
507*7304104dSAndroid Build Coastguard Worker /* The section the reference data is for must match the section
508*7304104dSAndroid Build Coastguard Worker parameter. */
509*7304104dSAndroid Build Coastguard Worker || unlikely (((Elf_Data_Scn *) data)->s != scn))
510*7304104dSAndroid Build Coastguard Worker {
511*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_DATA_MISMATCH);
512*7304104dSAndroid Build Coastguard Worker goto out;
513*7304104dSAndroid Build Coastguard Worker }
514*7304104dSAndroid Build Coastguard Worker
515*7304104dSAndroid Build Coastguard Worker /* We start searching with the first entry. */
516*7304104dSAndroid Build Coastguard Worker runp = &scn->data_list;
517*7304104dSAndroid Build Coastguard Worker
518*7304104dSAndroid Build Coastguard Worker while (1)
519*7304104dSAndroid Build Coastguard Worker {
520*7304104dSAndroid Build Coastguard Worker /* If `data' does not match any known record punt. */
521*7304104dSAndroid Build Coastguard Worker if (runp == NULL)
522*7304104dSAndroid Build Coastguard Worker {
523*7304104dSAndroid Build Coastguard Worker __libelf_seterrno (ELF_E_DATA_MISMATCH);
524*7304104dSAndroid Build Coastguard Worker goto out;
525*7304104dSAndroid Build Coastguard Worker }
526*7304104dSAndroid Build Coastguard Worker
527*7304104dSAndroid Build Coastguard Worker if (&runp->data.d == data)
528*7304104dSAndroid Build Coastguard Worker /* Found the entry. */
529*7304104dSAndroid Build Coastguard Worker break;
530*7304104dSAndroid Build Coastguard Worker
531*7304104dSAndroid Build Coastguard Worker runp = runp->next;
532*7304104dSAndroid Build Coastguard Worker }
533*7304104dSAndroid Build Coastguard Worker
534*7304104dSAndroid Build Coastguard Worker /* Return the data for the next data record. */
535*7304104dSAndroid Build Coastguard Worker result = runp->next ? &runp->next->data.d : NULL;
536*7304104dSAndroid Build Coastguard Worker goto out;
537*7304104dSAndroid Build Coastguard Worker }
538*7304104dSAndroid Build Coastguard Worker
539*7304104dSAndroid Build Coastguard Worker /* If the data for this section was not yet initialized do it now. */
540*7304104dSAndroid Build Coastguard Worker if (scn->data_read == 0)
541*7304104dSAndroid Build Coastguard Worker {
542*7304104dSAndroid Build Coastguard Worker /* We cannot acquire a write lock while we are holding a read
543*7304104dSAndroid Build Coastguard Worker lock. Therefore give up the read lock and then get the write
544*7304104dSAndroid Build Coastguard Worker lock. But this means that the data could meanwhile be
545*7304104dSAndroid Build Coastguard Worker modified, therefore start the tests again. */
546*7304104dSAndroid Build Coastguard Worker rwlock_unlock (elf->lock);
547*7304104dSAndroid Build Coastguard Worker rwlock_wrlock (elf->lock);
548*7304104dSAndroid Build Coastguard Worker locked = 1;
549*7304104dSAndroid Build Coastguard Worker
550*7304104dSAndroid Build Coastguard Worker /* Read the data from the file. There is always a file (or
551*7304104dSAndroid Build Coastguard Worker memory region) associated with this descriptor since
552*7304104dSAndroid Build Coastguard Worker otherwise the `data_read' flag would be set. */
553*7304104dSAndroid Build Coastguard Worker if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
554*7304104dSAndroid Build Coastguard Worker /* Something went wrong. The error value is already set. */
555*7304104dSAndroid Build Coastguard Worker goto out;
556*7304104dSAndroid Build Coastguard Worker }
557*7304104dSAndroid Build Coastguard Worker
558*7304104dSAndroid Build Coastguard Worker /* At this point we know the raw data is available. But it might be
559*7304104dSAndroid Build Coastguard Worker empty in case the section has size zero (for whatever reason).
560*7304104dSAndroid Build Coastguard Worker Now create the converted data in case this is necessary. */
561*7304104dSAndroid Build Coastguard Worker if (scn->data_list_rear == NULL)
562*7304104dSAndroid Build Coastguard Worker __libelf_set_data_list_rdlock (scn, locked);
563*7304104dSAndroid Build Coastguard Worker
564*7304104dSAndroid Build Coastguard Worker /* Return the first data element in the list. */
565*7304104dSAndroid Build Coastguard Worker result = &scn->data_list.data.d;
566*7304104dSAndroid Build Coastguard Worker
567*7304104dSAndroid Build Coastguard Worker out:
568*7304104dSAndroid Build Coastguard Worker return result;
569*7304104dSAndroid Build Coastguard Worker }
570*7304104dSAndroid Build Coastguard Worker
571*7304104dSAndroid Build Coastguard Worker Elf_Data *
elf_getdata(Elf_Scn * scn,Elf_Data * data)572*7304104dSAndroid Build Coastguard Worker elf_getdata (Elf_Scn *scn, Elf_Data *data)
573*7304104dSAndroid Build Coastguard Worker {
574*7304104dSAndroid Build Coastguard Worker Elf_Data *result;
575*7304104dSAndroid Build Coastguard Worker
576*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
577*7304104dSAndroid Build Coastguard Worker return NULL;
578*7304104dSAndroid Build Coastguard Worker
579*7304104dSAndroid Build Coastguard Worker rwlock_rdlock (scn->elf->lock);
580*7304104dSAndroid Build Coastguard Worker result = __elf_getdata_rdlock (scn, data);
581*7304104dSAndroid Build Coastguard Worker rwlock_unlock (scn->elf->lock);
582*7304104dSAndroid Build Coastguard Worker
583*7304104dSAndroid Build Coastguard Worker return result;
584*7304104dSAndroid Build Coastguard Worker }
585*7304104dSAndroid Build Coastguard Worker
586*7304104dSAndroid Build Coastguard Worker Elf_Data *
587*7304104dSAndroid Build Coastguard Worker internal_function
__elf_getdata_wrlock(Elf_Scn * scn,Elf_Data * data)588*7304104dSAndroid Build Coastguard Worker __elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data)
589*7304104dSAndroid Build Coastguard Worker {
590*7304104dSAndroid Build Coastguard Worker Elf_Data *result;
591*7304104dSAndroid Build Coastguard Worker
592*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
593*7304104dSAndroid Build Coastguard Worker return NULL;
594*7304104dSAndroid Build Coastguard Worker
595*7304104dSAndroid Build Coastguard Worker result = __elf_getdata_rdlock (scn, data);
596*7304104dSAndroid Build Coastguard Worker
597*7304104dSAndroid Build Coastguard Worker return result;
598*7304104dSAndroid Build Coastguard Worker }
599*7304104dSAndroid Build Coastguard Worker INTDEF(elf_getdata)
600