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