xref: /aosp_15_r20/external/elfutils/libdw/dwarf_begin_elf.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Create descriptor from ELF descriptor for processing file.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2023, Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <system.h>
35*7304104dSAndroid Build Coastguard Worker 
36*7304104dSAndroid Build Coastguard Worker #include <assert.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
38*7304104dSAndroid Build Coastguard Worker #include <stddef.h>
39*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
40*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
41*7304104dSAndroid Build Coastguard Worker #include <string.h>
42*7304104dSAndroid Build Coastguard Worker #include <sys/types.h>
43*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
44*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
47*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
48*7304104dSAndroid Build Coastguard Worker 
49*7304104dSAndroid Build Coastguard Worker 
50*7304104dSAndroid Build Coastguard Worker /* Section names.  (Note .debug_str_offsets is the largest 19 chars.)  */
51*7304104dSAndroid Build Coastguard Worker static const char dwarf_scnnames[IDX_last][19] =
52*7304104dSAndroid Build Coastguard Worker {
53*7304104dSAndroid Build Coastguard Worker   [IDX_debug_info] = ".debug_info",
54*7304104dSAndroid Build Coastguard Worker   [IDX_debug_types] = ".debug_types",
55*7304104dSAndroid Build Coastguard Worker   [IDX_debug_abbrev] = ".debug_abbrev",
56*7304104dSAndroid Build Coastguard Worker   [IDX_debug_addr] = ".debug_addr",
57*7304104dSAndroid Build Coastguard Worker   [IDX_debug_aranges] = ".debug_aranges",
58*7304104dSAndroid Build Coastguard Worker   [IDX_debug_line] = ".debug_line",
59*7304104dSAndroid Build Coastguard Worker   [IDX_debug_line_str] = ".debug_line_str",
60*7304104dSAndroid Build Coastguard Worker   [IDX_debug_frame] = ".debug_frame",
61*7304104dSAndroid Build Coastguard Worker   [IDX_debug_loc] = ".debug_loc",
62*7304104dSAndroid Build Coastguard Worker   [IDX_debug_loclists] = ".debug_loclists",
63*7304104dSAndroid Build Coastguard Worker   [IDX_debug_pubnames] = ".debug_pubnames",
64*7304104dSAndroid Build Coastguard Worker   [IDX_debug_str] = ".debug_str",
65*7304104dSAndroid Build Coastguard Worker   [IDX_debug_str_offsets] = ".debug_str_offsets",
66*7304104dSAndroid Build Coastguard Worker   [IDX_debug_macinfo] = ".debug_macinfo",
67*7304104dSAndroid Build Coastguard Worker   [IDX_debug_macro] = ".debug_macro",
68*7304104dSAndroid Build Coastguard Worker   [IDX_debug_ranges] = ".debug_ranges",
69*7304104dSAndroid Build Coastguard Worker   [IDX_debug_rnglists] = ".debug_rnglists",
70*7304104dSAndroid Build Coastguard Worker   [IDX_debug_cu_index] = ".debug_cu_index",
71*7304104dSAndroid Build Coastguard Worker   [IDX_debug_tu_index] = ".debug_tu_index",
72*7304104dSAndroid Build Coastguard Worker   [IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
73*7304104dSAndroid Build Coastguard Worker };
74*7304104dSAndroid Build Coastguard Worker #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
75*7304104dSAndroid Build Coastguard Worker 
76*7304104dSAndroid Build Coastguard Worker /* Map from section index to string section index.
77*7304104dSAndroid Build Coastguard Worker    Non-string sections should have STR_SCN_IDX_last.  */
78*7304104dSAndroid Build Coastguard Worker static const enum string_section_index scn_to_string_section_idx[IDX_last] =
79*7304104dSAndroid Build Coastguard Worker {
80*7304104dSAndroid Build Coastguard Worker   [IDX_debug_info] = STR_SCN_IDX_last,
81*7304104dSAndroid Build Coastguard Worker   [IDX_debug_types] = STR_SCN_IDX_last,
82*7304104dSAndroid Build Coastguard Worker   [IDX_debug_abbrev] = STR_SCN_IDX_last,
83*7304104dSAndroid Build Coastguard Worker   [IDX_debug_addr] = STR_SCN_IDX_last,
84*7304104dSAndroid Build Coastguard Worker   [IDX_debug_aranges] = STR_SCN_IDX_last,
85*7304104dSAndroid Build Coastguard Worker   [IDX_debug_line] = STR_SCN_IDX_last,
86*7304104dSAndroid Build Coastguard Worker   [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str,
87*7304104dSAndroid Build Coastguard Worker   [IDX_debug_frame] = STR_SCN_IDX_last,
88*7304104dSAndroid Build Coastguard Worker   [IDX_debug_loc] = STR_SCN_IDX_last,
89*7304104dSAndroid Build Coastguard Worker   [IDX_debug_loclists] = STR_SCN_IDX_last,
90*7304104dSAndroid Build Coastguard Worker   [IDX_debug_pubnames] = STR_SCN_IDX_last,
91*7304104dSAndroid Build Coastguard Worker   [IDX_debug_str] = STR_SCN_IDX_debug_str,
92*7304104dSAndroid Build Coastguard Worker   [IDX_debug_str_offsets] = STR_SCN_IDX_last,
93*7304104dSAndroid Build Coastguard Worker   [IDX_debug_macinfo] = STR_SCN_IDX_last,
94*7304104dSAndroid Build Coastguard Worker   [IDX_debug_macro] = STR_SCN_IDX_last,
95*7304104dSAndroid Build Coastguard Worker   [IDX_debug_ranges] = STR_SCN_IDX_last,
96*7304104dSAndroid Build Coastguard Worker   [IDX_debug_rnglists] = STR_SCN_IDX_last,
97*7304104dSAndroid Build Coastguard Worker   [IDX_debug_cu_index] = STR_SCN_IDX_last,
98*7304104dSAndroid Build Coastguard Worker   [IDX_debug_tu_index] = STR_SCN_IDX_last,
99*7304104dSAndroid Build Coastguard Worker   [IDX_gnu_debugaltlink] = STR_SCN_IDX_last
100*7304104dSAndroid Build Coastguard Worker };
101*7304104dSAndroid Build Coastguard Worker 
102*7304104dSAndroid Build Coastguard Worker static enum dwarf_type
scn_dwarf_type(Dwarf * result,size_t shstrndx,Elf_Scn * scn)103*7304104dSAndroid Build Coastguard Worker scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
104*7304104dSAndroid Build Coastguard Worker {
105*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
106*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
107*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL)
108*7304104dSAndroid Build Coastguard Worker     return TYPE_UNKNOWN;
109*7304104dSAndroid Build Coastguard Worker 
110*7304104dSAndroid Build Coastguard Worker   const char *scnname = elf_strptr (result->elf, shstrndx,
111*7304104dSAndroid Build Coastguard Worker 				    shdr->sh_name);
112*7304104dSAndroid Build Coastguard Worker   if (scnname != NULL)
113*7304104dSAndroid Build Coastguard Worker     {
114*7304104dSAndroid Build Coastguard Worker       if (startswith (scnname, ".gnu.debuglto_.debug"))
115*7304104dSAndroid Build Coastguard Worker 	return TYPE_GNU_LTO;
116*7304104dSAndroid Build Coastguard Worker       else if (strcmp (scnname, ".debug_cu_index") == 0
117*7304104dSAndroid Build Coastguard Worker 	       || strcmp (scnname, ".debug_tu_index") == 0
118*7304104dSAndroid Build Coastguard Worker 	       || strcmp (scnname, ".zdebug_cu_index") == 0
119*7304104dSAndroid Build Coastguard Worker 	       || strcmp (scnname, ".zdebug_tu_index") == 0)
120*7304104dSAndroid Build Coastguard Worker 	return TYPE_DWO;
121*7304104dSAndroid Build Coastguard Worker       else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
122*7304104dSAndroid Build Coastguard Worker 	{
123*7304104dSAndroid Build Coastguard Worker 	  size_t len = strlen (scnname);
124*7304104dSAndroid Build Coastguard Worker 	  if (strcmp (scnname + len - 4, ".dwo") == 0)
125*7304104dSAndroid Build Coastguard Worker 	    return TYPE_DWO;
126*7304104dSAndroid Build Coastguard Worker 	  else
127*7304104dSAndroid Build Coastguard Worker 	    return TYPE_PLAIN;
128*7304104dSAndroid Build Coastguard Worker 	}
129*7304104dSAndroid Build Coastguard Worker     }
130*7304104dSAndroid Build Coastguard Worker   return TYPE_UNKNOWN;
131*7304104dSAndroid Build Coastguard Worker }
132*7304104dSAndroid Build Coastguard Worker static Dwarf *
check_section(Dwarf * result,size_t shstrndx,Elf_Scn * scn,bool inscngrp)133*7304104dSAndroid Build Coastguard Worker check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
134*7304104dSAndroid Build Coastguard Worker {
135*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
136*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr;
137*7304104dSAndroid Build Coastguard Worker 
138*7304104dSAndroid Build Coastguard Worker   /* Get the section header data.  */
139*7304104dSAndroid Build Coastguard Worker   shdr = gelf_getshdr (scn, &shdr_mem);
140*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL)
141*7304104dSAndroid Build Coastguard Worker     /* We may read /proc/PID/mem with only program headers mapped and section
142*7304104dSAndroid Build Coastguard Worker        headers out of the mapped pages.  */
143*7304104dSAndroid Build Coastguard Worker     goto err;
144*7304104dSAndroid Build Coastguard Worker 
145*7304104dSAndroid Build Coastguard Worker   /* Ignore any SHT_NOBITS sections.  Debugging sections should not
146*7304104dSAndroid Build Coastguard Worker      have been stripped, but in case of a corrupt file we won't try
147*7304104dSAndroid Build Coastguard Worker      to look at the missing data.  */
148*7304104dSAndroid Build Coastguard Worker   if (unlikely (shdr->sh_type == SHT_NOBITS))
149*7304104dSAndroid Build Coastguard Worker     return result;
150*7304104dSAndroid Build Coastguard Worker 
151*7304104dSAndroid Build Coastguard Worker   /* Make sure the section is part of a section group only iff we
152*7304104dSAndroid Build Coastguard Worker      really need it.  If we are looking for the global (= non-section
153*7304104dSAndroid Build Coastguard Worker      group debug info) we have to ignore all the info in section
154*7304104dSAndroid Build Coastguard Worker      groups.  If we are looking into a section group we cannot look at
155*7304104dSAndroid Build Coastguard Worker      a section which isn't part of the section group.  */
156*7304104dSAndroid Build Coastguard Worker   if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
157*7304104dSAndroid Build Coastguard Worker     /* Ignore the section.  */
158*7304104dSAndroid Build Coastguard Worker     return result;
159*7304104dSAndroid Build Coastguard Worker 
160*7304104dSAndroid Build Coastguard Worker 
161*7304104dSAndroid Build Coastguard Worker   /* We recognize the DWARF section by their names.  This is not very
162*7304104dSAndroid Build Coastguard Worker      safe and stable but the best we can do.  */
163*7304104dSAndroid Build Coastguard Worker   const char *scnname = elf_strptr (result->elf, shstrndx,
164*7304104dSAndroid Build Coastguard Worker 				    shdr->sh_name);
165*7304104dSAndroid Build Coastguard Worker   if (scnname == NULL)
166*7304104dSAndroid Build Coastguard Worker     {
167*7304104dSAndroid Build Coastguard Worker       /* The section name must be valid.  Otherwise is the ELF file
168*7304104dSAndroid Build Coastguard Worker 	 invalid.  */
169*7304104dSAndroid Build Coastguard Worker     err:
170*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
171*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_ELF);
172*7304104dSAndroid Build Coastguard Worker       free (result);
173*7304104dSAndroid Build Coastguard Worker       return NULL;
174*7304104dSAndroid Build Coastguard Worker     }
175*7304104dSAndroid Build Coastguard Worker 
176*7304104dSAndroid Build Coastguard Worker   /* Recognize the various sections.  Most names start with .debug_.
177*7304104dSAndroid Build Coastguard Worker      They might be compressed (and start with .z).  Or end with .dwo
178*7304104dSAndroid Build Coastguard Worker      for split dwarf sections.  Or start with .gnu.debuglto_ for
179*7304104dSAndroid Build Coastguard Worker      LTO debug sections.  We should only use one consistent set at
180*7304104dSAndroid Build Coastguard Worker      a time.  We prefer PLAIN over DWO over LTO.  */
181*7304104dSAndroid Build Coastguard Worker   size_t cnt;
182*7304104dSAndroid Build Coastguard Worker   bool gnu_compressed = false;
183*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
184*7304104dSAndroid Build Coastguard Worker     {
185*7304104dSAndroid Build Coastguard Worker       /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix,
186*7304104dSAndroid Build Coastguard Worker 	 but they are for DWO.  */
187*7304104dSAndroid Build Coastguard Worker       if (result->type != TYPE_DWO
188*7304104dSAndroid Build Coastguard Worker 	  && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
189*7304104dSAndroid Build Coastguard Worker 	continue;
190*7304104dSAndroid Build Coastguard Worker       bool need_dot_dwo =
191*7304104dSAndroid Build Coastguard Worker 	(result->type == TYPE_DWO
192*7304104dSAndroid Build Coastguard Worker 	 && cnt != IDX_debug_cu_index
193*7304104dSAndroid Build Coastguard Worker 	 && cnt != IDX_debug_tu_index);
194*7304104dSAndroid Build Coastguard Worker       size_t dbglen = strlen (dwarf_scnnames[cnt]);
195*7304104dSAndroid Build Coastguard Worker       size_t scnlen = strlen (scnname);
196*7304104dSAndroid Build Coastguard Worker       if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
197*7304104dSAndroid Build Coastguard Worker 	  && ((!need_dot_dwo && dbglen == scnlen)
198*7304104dSAndroid Build Coastguard Worker 	      || (need_dot_dwo
199*7304104dSAndroid Build Coastguard Worker 		  && scnlen == dbglen + 4
200*7304104dSAndroid Build Coastguard Worker 		  && strstr (scnname, ".dwo") == scnname + dbglen)))
201*7304104dSAndroid Build Coastguard Worker 	break;
202*7304104dSAndroid Build Coastguard Worker       else if (scnname[0] == '.' && scnname[1] == 'z'
203*7304104dSAndroid Build Coastguard Worker 	       && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
204*7304104dSAndroid Build Coastguard Worker 			    dbglen - 1) == 0
205*7304104dSAndroid Build Coastguard Worker 		   && ((!need_dot_dwo && scnlen == dbglen + 1)
206*7304104dSAndroid Build Coastguard Worker 		       || (need_dot_dwo
207*7304104dSAndroid Build Coastguard Worker 			   && scnlen == dbglen + 5
208*7304104dSAndroid Build Coastguard Worker 			   && strstr (scnname,
209*7304104dSAndroid Build Coastguard Worker 				      ".dwo") == scnname + dbglen + 1))))
210*7304104dSAndroid Build Coastguard Worker 	{
211*7304104dSAndroid Build Coastguard Worker 	  gnu_compressed = true;
212*7304104dSAndroid Build Coastguard Worker 	  break;
213*7304104dSAndroid Build Coastguard Worker 	}
214*7304104dSAndroid Build Coastguard Worker       else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
215*7304104dSAndroid Build Coastguard Worker 	       && startswith (scnname, ".gnu.debuglto_")
216*7304104dSAndroid Build Coastguard Worker 	       && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
217*7304104dSAndroid Build Coastguard Worker 	{
218*7304104dSAndroid Build Coastguard Worker 	  if (result->type == TYPE_GNU_LTO)
219*7304104dSAndroid Build Coastguard Worker 	    break;
220*7304104dSAndroid Build Coastguard Worker 	}
221*7304104dSAndroid Build Coastguard Worker     }
222*7304104dSAndroid Build Coastguard Worker 
223*7304104dSAndroid Build Coastguard Worker   if (cnt >= ndwarf_scnnames)
224*7304104dSAndroid Build Coastguard Worker     /* Not a debug section; ignore it. */
225*7304104dSAndroid Build Coastguard Worker     return result;
226*7304104dSAndroid Build Coastguard Worker 
227*7304104dSAndroid Build Coastguard Worker   if (unlikely (result->sectiondata[cnt] != NULL))
228*7304104dSAndroid Build Coastguard Worker     /* A section appears twice.  That's bad.  We ignore the section.  */
229*7304104dSAndroid Build Coastguard Worker     return result;
230*7304104dSAndroid Build Coastguard Worker 
231*7304104dSAndroid Build Coastguard Worker   /* We cannot know whether or not a GNU compressed section has already
232*7304104dSAndroid Build Coastguard Worker      been uncompressed or not, so ignore any errors.  */
233*7304104dSAndroid Build Coastguard Worker   if (gnu_compressed)
234*7304104dSAndroid Build Coastguard Worker     elf_compress_gnu (scn, 0, 0);
235*7304104dSAndroid Build Coastguard Worker 
236*7304104dSAndroid Build Coastguard Worker   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
237*7304104dSAndroid Build Coastguard Worker     {
238*7304104dSAndroid Build Coastguard Worker       if (elf_compress (scn, 0, 0) < 0)
239*7304104dSAndroid Build Coastguard Worker 	{
240*7304104dSAndroid Build Coastguard Worker 	  /* It would be nice if we could fail with a specific error.
241*7304104dSAndroid Build Coastguard Worker 	     But we don't know if this was an essential section or not.
242*7304104dSAndroid Build Coastguard Worker 	     So just continue for now. See also valid_p().  */
243*7304104dSAndroid Build Coastguard Worker 	  return result;
244*7304104dSAndroid Build Coastguard Worker 	}
245*7304104dSAndroid Build Coastguard Worker     }
246*7304104dSAndroid Build Coastguard Worker 
247*7304104dSAndroid Build Coastguard Worker   /* Get the section data.  Should be raw bytes, no conversion needed.  */
248*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_rawdata (scn, NULL);
249*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
250*7304104dSAndroid Build Coastguard Worker     goto err;
251*7304104dSAndroid Build Coastguard Worker 
252*7304104dSAndroid Build Coastguard Worker   if (data->d_buf == NULL || data->d_size == 0)
253*7304104dSAndroid Build Coastguard Worker     /* No data actually available, ignore it. */
254*7304104dSAndroid Build Coastguard Worker     return result;
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker   /* We can now read the section data into results. */
257*7304104dSAndroid Build Coastguard Worker   result->sectiondata[cnt] = data;
258*7304104dSAndroid Build Coastguard Worker 
259*7304104dSAndroid Build Coastguard Worker   /* If the section contains string data, we want to know a size of a prefix
260*7304104dSAndroid Build Coastguard Worker      where any string will be null-terminated. */
261*7304104dSAndroid Build Coastguard Worker   enum string_section_index string_section_idx = scn_to_string_section_idx[cnt];
262*7304104dSAndroid Build Coastguard Worker   if (string_section_idx < STR_SCN_IDX_last)
263*7304104dSAndroid Build Coastguard Worker     {
264*7304104dSAndroid Build Coastguard Worker       size_t size = data->d_size;
265*7304104dSAndroid Build Coastguard Worker       /* Reduce the size by the number of non-zero bytes at the end of the
266*7304104dSAndroid Build Coastguard Worker 	 section.  */
267*7304104dSAndroid Build Coastguard Worker       while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
268*7304104dSAndroid Build Coastguard Worker 	--size;
269*7304104dSAndroid Build Coastguard Worker       result->string_section_size[string_section_idx] = size;
270*7304104dSAndroid Build Coastguard Worker     }
271*7304104dSAndroid Build Coastguard Worker 
272*7304104dSAndroid Build Coastguard Worker   return result;
273*7304104dSAndroid Build Coastguard Worker }
274*7304104dSAndroid Build Coastguard Worker 
275*7304104dSAndroid Build Coastguard Worker char *
__libdw_elfpath(int fd)276*7304104dSAndroid Build Coastguard Worker __libdw_elfpath (int fd)
277*7304104dSAndroid Build Coastguard Worker {
278*7304104dSAndroid Build Coastguard Worker   /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
279*7304104dSAndroid Build Coastguard Worker   char devfdpath[25];
280*7304104dSAndroid Build Coastguard Worker   sprintf (devfdpath, "/proc/self/fd/%u", fd);
281*7304104dSAndroid Build Coastguard Worker   return realpath (devfdpath, NULL);
282*7304104dSAndroid Build Coastguard Worker }
283*7304104dSAndroid Build Coastguard Worker 
284*7304104dSAndroid Build Coastguard Worker 
285*7304104dSAndroid Build Coastguard Worker void
__libdw_set_debugdir(Dwarf * dbg)286*7304104dSAndroid Build Coastguard Worker __libdw_set_debugdir (Dwarf *dbg)
287*7304104dSAndroid Build Coastguard Worker {
288*7304104dSAndroid Build Coastguard Worker   if (dbg->elfpath == NULL || dbg->elfpath[0] != '/')
289*7304104dSAndroid Build Coastguard Worker     return;
290*7304104dSAndroid Build Coastguard Worker   size_t dirlen = strrchr (dbg->elfpath, '/') - dbg->elfpath + 1;
291*7304104dSAndroid Build Coastguard Worker   dbg->debugdir = malloc (dirlen + 1);
292*7304104dSAndroid Build Coastguard Worker   if (dbg->debugdir == NULL)
293*7304104dSAndroid Build Coastguard Worker     return;
294*7304104dSAndroid Build Coastguard Worker   memcpy (dbg->debugdir, dbg->elfpath, dirlen);
295*7304104dSAndroid Build Coastguard Worker   dbg->debugdir[dirlen] = '\0';
296*7304104dSAndroid Build Coastguard Worker }
297*7304104dSAndroid Build Coastguard Worker 
298*7304104dSAndroid Build Coastguard Worker 
299*7304104dSAndroid Build Coastguard Worker /* Check whether all the necessary DWARF information is available.  */
300*7304104dSAndroid Build Coastguard Worker static Dwarf *
valid_p(Dwarf * result)301*7304104dSAndroid Build Coastguard Worker valid_p (Dwarf *result)
302*7304104dSAndroid Build Coastguard Worker {
303*7304104dSAndroid Build Coastguard Worker   /* We looked at all the sections.  Now determine whether all the
304*7304104dSAndroid Build Coastguard Worker      sections with debugging information we need are there.
305*7304104dSAndroid Build Coastguard Worker 
306*7304104dSAndroid Build Coastguard Worker      Require at least one section that can be read "standalone".  */
307*7304104dSAndroid Build Coastguard Worker   if (likely (result != NULL)
308*7304104dSAndroid Build Coastguard Worker       && unlikely (result->sectiondata[IDX_debug_info] == NULL
309*7304104dSAndroid Build Coastguard Worker 		   && result->sectiondata[IDX_debug_line] == NULL
310*7304104dSAndroid Build Coastguard Worker 		   && result->sectiondata[IDX_debug_frame] == NULL))
311*7304104dSAndroid Build Coastguard Worker     {
312*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
313*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_NO_DWARF);
314*7304104dSAndroid Build Coastguard Worker       free (result);
315*7304104dSAndroid Build Coastguard Worker       result = NULL;
316*7304104dSAndroid Build Coastguard Worker     }
317*7304104dSAndroid Build Coastguard Worker 
318*7304104dSAndroid Build Coastguard Worker   /* We are setting up some "fake" CUs, which need an address size.
319*7304104dSAndroid Build Coastguard Worker      Check the ELF class to come up with something reasonable.  */
320*7304104dSAndroid Build Coastguard Worker   int elf_addr_size = 8;
321*7304104dSAndroid Build Coastguard Worker   if (result != NULL)
322*7304104dSAndroid Build Coastguard Worker     {
323*7304104dSAndroid Build Coastguard Worker       GElf_Ehdr ehdr;
324*7304104dSAndroid Build Coastguard Worker       if (gelf_getehdr (result->elf, &ehdr) == NULL)
325*7304104dSAndroid Build Coastguard Worker 	{
326*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
327*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_ELF);
328*7304104dSAndroid Build Coastguard Worker 	  free (result);
329*7304104dSAndroid Build Coastguard Worker 	  result = NULL;
330*7304104dSAndroid Build Coastguard Worker 	}
331*7304104dSAndroid Build Coastguard Worker       else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
332*7304104dSAndroid Build Coastguard Worker 	elf_addr_size = 4;
333*7304104dSAndroid Build Coastguard Worker     }
334*7304104dSAndroid Build Coastguard Worker 
335*7304104dSAndroid Build Coastguard Worker   /* For dwarf_location_attr () we need a "fake" CU to indicate
336*7304104dSAndroid Build Coastguard Worker      where the "fake" attribute data comes from.  This is a block
337*7304104dSAndroid Build Coastguard Worker      inside the .debug_loc or .debug_loclists section.  */
338*7304104dSAndroid Build Coastguard Worker   if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
339*7304104dSAndroid Build Coastguard Worker     {
340*7304104dSAndroid Build Coastguard Worker       result->fake_loc_cu = malloc (sizeof (Dwarf_CU));
341*7304104dSAndroid Build Coastguard Worker       if (unlikely (result->fake_loc_cu == NULL))
342*7304104dSAndroid Build Coastguard Worker 	{
343*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
344*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NOMEM);
345*7304104dSAndroid Build Coastguard Worker 	  free (result);
346*7304104dSAndroid Build Coastguard Worker 	  result = NULL;
347*7304104dSAndroid Build Coastguard Worker 	}
348*7304104dSAndroid Build Coastguard Worker       else
349*7304104dSAndroid Build Coastguard Worker 	{
350*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->sec_idx = IDX_debug_loc;
351*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->dbg = result;
352*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->startp
353*7304104dSAndroid Build Coastguard Worker 	    = result->sectiondata[IDX_debug_loc]->d_buf;
354*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->endp
355*7304104dSAndroid Build Coastguard Worker 	    = (result->sectiondata[IDX_debug_loc]->d_buf
356*7304104dSAndroid Build Coastguard Worker 	       + result->sectiondata[IDX_debug_loc]->d_size);
357*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->locs = NULL;
358*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->address_size = elf_addr_size;
359*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->offset_size = 4;
360*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->version = 4;
361*7304104dSAndroid Build Coastguard Worker 	  result->fake_loc_cu->split = NULL;
362*7304104dSAndroid Build Coastguard Worker 	}
363*7304104dSAndroid Build Coastguard Worker     }
364*7304104dSAndroid Build Coastguard Worker 
365*7304104dSAndroid Build Coastguard Worker   if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
366*7304104dSAndroid Build Coastguard Worker     {
367*7304104dSAndroid Build Coastguard Worker       result->fake_loclists_cu = malloc (sizeof (Dwarf_CU));
368*7304104dSAndroid Build Coastguard Worker       if (unlikely (result->fake_loclists_cu == NULL))
369*7304104dSAndroid Build Coastguard Worker 	{
370*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
371*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NOMEM);
372*7304104dSAndroid Build Coastguard Worker 	  free (result->fake_loc_cu);
373*7304104dSAndroid Build Coastguard Worker 	  free (result);
374*7304104dSAndroid Build Coastguard Worker 	  result = NULL;
375*7304104dSAndroid Build Coastguard Worker 	}
376*7304104dSAndroid Build Coastguard Worker       else
377*7304104dSAndroid Build Coastguard Worker 	{
378*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
379*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->dbg = result;
380*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->startp
381*7304104dSAndroid Build Coastguard Worker 	    = result->sectiondata[IDX_debug_loclists]->d_buf;
382*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->endp
383*7304104dSAndroid Build Coastguard Worker 	    = (result->sectiondata[IDX_debug_loclists]->d_buf
384*7304104dSAndroid Build Coastguard Worker 	       + result->sectiondata[IDX_debug_loclists]->d_size);
385*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->locs = NULL;
386*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->address_size = elf_addr_size;
387*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->offset_size = 4;
388*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->version = 5;
389*7304104dSAndroid Build Coastguard Worker 	  result->fake_loclists_cu->split = NULL;
390*7304104dSAndroid Build Coastguard Worker 	}
391*7304104dSAndroid Build Coastguard Worker     }
392*7304104dSAndroid Build Coastguard Worker 
393*7304104dSAndroid Build Coastguard Worker   /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
394*7304104dSAndroid Build Coastguard Worker      the dwarf_location_attr () will need a "fake" address CU to
395*7304104dSAndroid Build Coastguard Worker      indicate where the attribute data comes from.  This is a just
396*7304104dSAndroid Build Coastguard Worker      inside the .debug_addr section, if it exists.  */
397*7304104dSAndroid Build Coastguard Worker   if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
398*7304104dSAndroid Build Coastguard Worker     {
399*7304104dSAndroid Build Coastguard Worker       result->fake_addr_cu = malloc (sizeof (Dwarf_CU));
400*7304104dSAndroid Build Coastguard Worker       if (unlikely (result->fake_addr_cu == NULL))
401*7304104dSAndroid Build Coastguard Worker 	{
402*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
403*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NOMEM);
404*7304104dSAndroid Build Coastguard Worker 	  free (result->fake_loc_cu);
405*7304104dSAndroid Build Coastguard Worker 	  free (result->fake_loclists_cu);
406*7304104dSAndroid Build Coastguard Worker 	  free (result);
407*7304104dSAndroid Build Coastguard Worker 	  result = NULL;
408*7304104dSAndroid Build Coastguard Worker 	}
409*7304104dSAndroid Build Coastguard Worker       else
410*7304104dSAndroid Build Coastguard Worker 	{
411*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->sec_idx = IDX_debug_addr;
412*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->dbg = result;
413*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->startp
414*7304104dSAndroid Build Coastguard Worker 	    = result->sectiondata[IDX_debug_addr]->d_buf;
415*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->endp
416*7304104dSAndroid Build Coastguard Worker 	    = (result->sectiondata[IDX_debug_addr]->d_buf
417*7304104dSAndroid Build Coastguard Worker 	       + result->sectiondata[IDX_debug_addr]->d_size);
418*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->locs = NULL;
419*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->address_size = elf_addr_size;
420*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->offset_size = 4;
421*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->version = 5;
422*7304104dSAndroid Build Coastguard Worker 	  result->fake_addr_cu->split = NULL;
423*7304104dSAndroid Build Coastguard Worker 	}
424*7304104dSAndroid Build Coastguard Worker     }
425*7304104dSAndroid Build Coastguard Worker 
426*7304104dSAndroid Build Coastguard Worker   if (result != NULL)
427*7304104dSAndroid Build Coastguard Worker     {
428*7304104dSAndroid Build Coastguard Worker       result->elfpath = __libdw_elfpath (result->elf->fildes);
429*7304104dSAndroid Build Coastguard Worker       __libdw_set_debugdir(result);
430*7304104dSAndroid Build Coastguard Worker     }
431*7304104dSAndroid Build Coastguard Worker 
432*7304104dSAndroid Build Coastguard Worker   return result;
433*7304104dSAndroid Build Coastguard Worker }
434*7304104dSAndroid Build Coastguard Worker 
435*7304104dSAndroid Build Coastguard Worker 
436*7304104dSAndroid Build Coastguard Worker static Dwarf *
global_read(Dwarf * result,Elf * elf,size_t shstrndx)437*7304104dSAndroid Build Coastguard Worker global_read (Dwarf *result, Elf *elf, size_t shstrndx)
438*7304104dSAndroid Build Coastguard Worker {
439*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
440*7304104dSAndroid Build Coastguard Worker 
441*7304104dSAndroid Build Coastguard Worker   /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
442*7304104dSAndroid Build Coastguard Worker      prefer PLAIN if available over DWO, over LTO.  */
443*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN)
444*7304104dSAndroid Build Coastguard Worker     {
445*7304104dSAndroid Build Coastguard Worker       enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
446*7304104dSAndroid Build Coastguard Worker       if (type > result->type)
447*7304104dSAndroid Build Coastguard Worker 	result->type = type;
448*7304104dSAndroid Build Coastguard Worker     }
449*7304104dSAndroid Build Coastguard Worker 
450*7304104dSAndroid Build Coastguard Worker   scn = NULL;
451*7304104dSAndroid Build Coastguard Worker   while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
452*7304104dSAndroid Build Coastguard Worker     result = check_section (result, shstrndx, scn, false);
453*7304104dSAndroid Build Coastguard Worker 
454*7304104dSAndroid Build Coastguard Worker   return valid_p (result);
455*7304104dSAndroid Build Coastguard Worker }
456*7304104dSAndroid Build Coastguard Worker 
457*7304104dSAndroid Build Coastguard Worker 
458*7304104dSAndroid Build Coastguard Worker static Dwarf *
scngrp_read(Dwarf * result,Elf * elf,size_t shstrndx,Elf_Scn * scngrp)459*7304104dSAndroid Build Coastguard Worker scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
460*7304104dSAndroid Build Coastguard Worker {
461*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
462*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
463*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL)
464*7304104dSAndroid Build Coastguard Worker     {
465*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
466*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_ELF);
467*7304104dSAndroid Build Coastguard Worker       free (result);
468*7304104dSAndroid Build Coastguard Worker       return NULL;
469*7304104dSAndroid Build Coastguard Worker     }
470*7304104dSAndroid Build Coastguard Worker 
471*7304104dSAndroid Build Coastguard Worker   if ((shdr->sh_flags & SHF_COMPRESSED) != 0
472*7304104dSAndroid Build Coastguard Worker       && elf_compress (scngrp, 0, 0) < 0)
473*7304104dSAndroid Build Coastguard Worker     {
474*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
475*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
476*7304104dSAndroid Build Coastguard Worker       free (result);
477*7304104dSAndroid Build Coastguard Worker       return NULL;
478*7304104dSAndroid Build Coastguard Worker     }
479*7304104dSAndroid Build Coastguard Worker 
480*7304104dSAndroid Build Coastguard Worker   /* SCNGRP is the section descriptor for a section group which might
481*7304104dSAndroid Build Coastguard Worker      contain debug sections.  */
482*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scngrp, NULL);
483*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
484*7304104dSAndroid Build Coastguard Worker     {
485*7304104dSAndroid Build Coastguard Worker       /* We cannot read the section content.  Fail!  */
486*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
487*7304104dSAndroid Build Coastguard Worker       free (result);
488*7304104dSAndroid Build Coastguard Worker       return NULL;
489*7304104dSAndroid Build Coastguard Worker     }
490*7304104dSAndroid Build Coastguard Worker 
491*7304104dSAndroid Build Coastguard Worker   /* The content of the section is a number of 32-bit words which
492*7304104dSAndroid Build Coastguard Worker      represent section indices.  The first word is a flag word.  */
493*7304104dSAndroid Build Coastguard Worker   Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
494*7304104dSAndroid Build Coastguard Worker   size_t cnt;
495*7304104dSAndroid Build Coastguard Worker 
496*7304104dSAndroid Build Coastguard Worker   /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
497*7304104dSAndroid Build Coastguard Worker      prefer PLAIN if available over DWO, over LTO.  */
498*7304104dSAndroid Build Coastguard Worker   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
499*7304104dSAndroid Build Coastguard Worker     {
500*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
501*7304104dSAndroid Build Coastguard Worker       if (scn == NULL)
502*7304104dSAndroid Build Coastguard Worker 	{
503*7304104dSAndroid Build Coastguard Worker 	  /* A section group refers to a non-existing section.  Should
504*7304104dSAndroid Build Coastguard Worker 	     never happen.  */
505*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
506*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_ELF);
507*7304104dSAndroid Build Coastguard Worker 	  free (result);
508*7304104dSAndroid Build Coastguard Worker 	  return NULL;
509*7304104dSAndroid Build Coastguard Worker 	}
510*7304104dSAndroid Build Coastguard Worker 
511*7304104dSAndroid Build Coastguard Worker       enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
512*7304104dSAndroid Build Coastguard Worker       if (type > result->type)
513*7304104dSAndroid Build Coastguard Worker 	result->type = type;
514*7304104dSAndroid Build Coastguard Worker     }
515*7304104dSAndroid Build Coastguard Worker 
516*7304104dSAndroid Build Coastguard Worker   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
517*7304104dSAndroid Build Coastguard Worker     {
518*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
519*7304104dSAndroid Build Coastguard Worker       assert (scn != NULL); // checked above
520*7304104dSAndroid Build Coastguard Worker       result = check_section (result, shstrndx, scn, true);
521*7304104dSAndroid Build Coastguard Worker       if (result == NULL)
522*7304104dSAndroid Build Coastguard Worker 	break;
523*7304104dSAndroid Build Coastguard Worker     }
524*7304104dSAndroid Build Coastguard Worker 
525*7304104dSAndroid Build Coastguard Worker   return valid_p (result);
526*7304104dSAndroid Build Coastguard Worker }
527*7304104dSAndroid Build Coastguard Worker 
528*7304104dSAndroid Build Coastguard Worker 
529*7304104dSAndroid Build Coastguard Worker Dwarf *
dwarf_begin_elf(Elf * elf,Dwarf_Cmd cmd,Elf_Scn * scngrp)530*7304104dSAndroid Build Coastguard Worker dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
531*7304104dSAndroid Build Coastguard Worker {
532*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr *ehdr;
533*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem;
534*7304104dSAndroid Build Coastguard Worker 
535*7304104dSAndroid Build Coastguard Worker   /* Get the ELF header of the file.  We need various pieces of
536*7304104dSAndroid Build Coastguard Worker      information from it.  */
537*7304104dSAndroid Build Coastguard Worker   ehdr = gelf_getehdr (elf, &ehdr_mem);
538*7304104dSAndroid Build Coastguard Worker   if (ehdr == NULL)
539*7304104dSAndroid Build Coastguard Worker     {
540*7304104dSAndroid Build Coastguard Worker       if (elf_kind (elf) != ELF_K_ELF)
541*7304104dSAndroid Build Coastguard Worker 	__libdw_seterrno (DWARF_E_NOELF);
542*7304104dSAndroid Build Coastguard Worker       else
543*7304104dSAndroid Build Coastguard Worker 	__libdw_seterrno (DWARF_E_GETEHDR_ERROR);
544*7304104dSAndroid Build Coastguard Worker 
545*7304104dSAndroid Build Coastguard Worker       return NULL;
546*7304104dSAndroid Build Coastguard Worker     }
547*7304104dSAndroid Build Coastguard Worker 
548*7304104dSAndroid Build Coastguard Worker 
549*7304104dSAndroid Build Coastguard Worker   /* Default memory allocation size.  */
550*7304104dSAndroid Build Coastguard Worker   size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
551*7304104dSAndroid Build Coastguard Worker   assert (sizeof (struct Dwarf) < mem_default_size);
552*7304104dSAndroid Build Coastguard Worker 
553*7304104dSAndroid Build Coastguard Worker   /* Allocate the data structure.  */
554*7304104dSAndroid Build Coastguard Worker   Dwarf *result = calloc (1, sizeof (Dwarf));
555*7304104dSAndroid Build Coastguard Worker   if (unlikely (result == NULL)
556*7304104dSAndroid Build Coastguard Worker       || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
557*7304104dSAndroid Build Coastguard Worker     {
558*7304104dSAndroid Build Coastguard Worker       free (result);
559*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_NOMEM);
560*7304104dSAndroid Build Coastguard Worker       return NULL;
561*7304104dSAndroid Build Coastguard Worker     }
562*7304104dSAndroid Build Coastguard Worker 
563*7304104dSAndroid Build Coastguard Worker   /* Fill in some values.  */
564*7304104dSAndroid Build Coastguard Worker   if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
565*7304104dSAndroid Build Coastguard Worker       || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
566*7304104dSAndroid Build Coastguard Worker     result->other_byte_order = true;
567*7304104dSAndroid Build Coastguard Worker 
568*7304104dSAndroid Build Coastguard Worker   result->elf = elf;
569*7304104dSAndroid Build Coastguard Worker   result->alt_fd = -1;
570*7304104dSAndroid Build Coastguard Worker   result->dwp_fd = -1;
571*7304104dSAndroid Build Coastguard Worker 
572*7304104dSAndroid Build Coastguard Worker   /* Initialize the memory handling.  Initial blocks are allocated on first
573*7304104dSAndroid Build Coastguard Worker      actual allocation.  */
574*7304104dSAndroid Build Coastguard Worker   result->mem_default_size = mem_default_size;
575*7304104dSAndroid Build Coastguard Worker   result->oom_handler = __libdw_oom;
576*7304104dSAndroid Build Coastguard Worker   if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
577*7304104dSAndroid Build Coastguard Worker     {
578*7304104dSAndroid Build Coastguard Worker       free (result);
579*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
580*7304104dSAndroid Build Coastguard Worker       return NULL;
581*7304104dSAndroid Build Coastguard Worker     }
582*7304104dSAndroid Build Coastguard Worker   result->mem_stacks = 0;
583*7304104dSAndroid Build Coastguard Worker   result->mem_tails = NULL;
584*7304104dSAndroid Build Coastguard Worker 
585*7304104dSAndroid Build Coastguard Worker   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
586*7304104dSAndroid Build Coastguard Worker     {
587*7304104dSAndroid Build Coastguard Worker       /* All sections are recognized by name, so pass the section header
588*7304104dSAndroid Build Coastguard Worker 	 string index along to easily get the section names.  */
589*7304104dSAndroid Build Coastguard Worker       size_t shstrndx;
590*7304104dSAndroid Build Coastguard Worker       if (elf_getshdrstrndx (elf, &shstrndx) != 0)
591*7304104dSAndroid Build Coastguard Worker 	{
592*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
593*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_ELF);
594*7304104dSAndroid Build Coastguard Worker 	  free (result);
595*7304104dSAndroid Build Coastguard Worker 	  return NULL;
596*7304104dSAndroid Build Coastguard Worker 	}
597*7304104dSAndroid Build Coastguard Worker 
598*7304104dSAndroid Build Coastguard Worker       /* If the caller provides a section group we get the DWARF
599*7304104dSAndroid Build Coastguard Worker 	 sections only from this section group.  Otherwise we search
600*7304104dSAndroid Build Coastguard Worker 	 for the first section with the required name.  Further
601*7304104dSAndroid Build Coastguard Worker 	 sections with the name are ignored.  The DWARF specification
602*7304104dSAndroid Build Coastguard Worker 	 does not really say this is allowed.  */
603*7304104dSAndroid Build Coastguard Worker       if (scngrp == NULL)
604*7304104dSAndroid Build Coastguard Worker 	return global_read (result, elf, shstrndx);
605*7304104dSAndroid Build Coastguard Worker       else
606*7304104dSAndroid Build Coastguard Worker 	return scngrp_read (result, elf, shstrndx, scngrp);
607*7304104dSAndroid Build Coastguard Worker     }
608*7304104dSAndroid Build Coastguard Worker   else if (cmd == DWARF_C_WRITE)
609*7304104dSAndroid Build Coastguard Worker     {
610*7304104dSAndroid Build Coastguard Worker       Dwarf_Sig8_Hash_free (&result->sig8_hash);
611*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_UNIMPL);
612*7304104dSAndroid Build Coastguard Worker       free (result);
613*7304104dSAndroid Build Coastguard Worker       return NULL;
614*7304104dSAndroid Build Coastguard Worker     }
615*7304104dSAndroid Build Coastguard Worker 
616*7304104dSAndroid Build Coastguard Worker   Dwarf_Sig8_Hash_free (&result->sig8_hash);
617*7304104dSAndroid Build Coastguard Worker   __libdw_seterrno (DWARF_E_INVALID_CMD);
618*7304104dSAndroid Build Coastguard Worker   free (result);
619*7304104dSAndroid Build Coastguard Worker   return NULL;
620*7304104dSAndroid Build Coastguard Worker }
621*7304104dSAndroid Build Coastguard Worker INTDEF(dwarf_begin_elf)
622