xref: /aosp_15_r20/external/elfutils/libelf/elf_getdata.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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