• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create descriptor from ELF descriptor for processing file.
2    Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 
26 #include "libdwP.h"
27 
28 
29 /* Section names.  */
30 static const char dwarf_scnnames[IDX_last][17] =
31 {
32   [IDX_debug_info] = ".debug_info",
33   [IDX_debug_abbrev] = ".debug_abbrev",
34   [IDX_debug_aranges] = ".debug_aranges",
35   [IDX_debug_line] = ".debug_line",
36   [IDX_debug_frame] = ".debug_frame",
37   [IDX_eh_frame] = ".eh_frame",
38   [IDX_debug_loc] = ".debug_loc",
39   [IDX_debug_pubnames] = ".debug_pubnames",
40   [IDX_debug_str] = ".debug_str",
41   [IDX_debug_funcnames] = ".debug_funcnames",
42   [IDX_debug_typenames] = ".debug_typenames",
43   [IDX_debug_varnames] = ".debug_varnames",
44   [IDX_debug_weaknames] = ".debug_weaknames",
45   [IDX_debug_macinfo] = ".debug_macinfo"
46 };
47 #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
48 
49 
50 static void
check_section(Dwarf * result,GElf_Ehdr * ehdr,Elf_Scn * scn,bool inscngrp)51 check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
52 {
53   GElf_Shdr shdr_mem;
54   GElf_Shdr *shdr;
55 
56   /* Get the section header data.  */
57   shdr = gelf_getshdr (scn, &shdr_mem);
58   if (shdr == NULL)
59     /* This should never happen.  If it does something is
60        wrong in the libelf library.  */
61     abort ();
62 
63 
64   /* Make sure the section is part of a section group only iff we
65      really need it.  If we are looking for the global (= non-section
66      group debug info) we have to ignore all the info in section
67      groups.  If we are looking into a section group we cannot look at
68      a section which isn't part of the section group.  */
69   if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
70     /* Ignore the section.  */
71     return;
72 
73 
74   /* We recognize the DWARF section by their names.  This is not very
75      safe and stable but the best we can do.  */
76   const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
77 				    shdr->sh_name);
78   if (scnname == NULL)
79     {
80       /* The section name must be valid.  Otherwise is the ELF file
81 	 invalid.  */
82       __libdw_seterrno (DWARF_E_INVALID_ELF);
83       free (result);
84       return;
85     }
86 
87 
88   /* Recognize the various sections.  Most names start with .debug_.  */
89   size_t cnt;
90   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
91     if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
92       {
93 	/* Found it.  Remember where the data is.  */
94 	if (unlikely (result->sectiondata[cnt] != NULL))
95 	  /* A section appears twice.  That's bad.  We ignore the section.  */
96 	  break;
97 
98 	/* Get the section data.  */
99 	Elf_Data *data = elf_getdata (scn, NULL);
100 	if (data != NULL && data->d_size != 0)
101 	  /* Yep, there is actually data available.  */
102 	  result->sectiondata[cnt] = data;
103 
104 	break;
105       }
106 }
107 
108 
109 /* Check whether all the necessary DWARF information is available.  */
110 static Dwarf *
valid_p(Dwarf * result)111 valid_p (Dwarf *result)
112 {
113   /* We looked at all the sections.  Now determine whether all the
114      sections with debugging information we need are there.
115 
116      XXX Which sections are absolutely necessary?  Add tests if
117      necessary.  For now we require only .debug_info.  Hopefully this
118      is correct.  */
119   if (unlikely (result->sectiondata[IDX_debug_info] == NULL))
120     {
121       __libdw_seterrno (DWARF_E_NO_DWARF);
122       result = NULL;
123     }
124 
125   return result;
126 }
127 
128 
129 static Dwarf *
global_read(Dwarf * result,Elf * elf,GElf_Ehdr * ehdr,Dwarf_Cmd cmd)130 global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd)
131 {
132   Elf_Scn *scn = NULL;
133 
134   while ((scn = elf_nextscn (elf, scn)) != NULL)
135     check_section (result, ehdr, scn, false);
136 
137   return valid_p (result);
138 }
139 
140 
141 static Dwarf *
scngrp_read(Dwarf * result,Elf * elf,GElf_Ehdr * ehdr,Dwarf_Cmd cmd,Elf_Scn * scngrp)142 scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd,
143 	     Elf_Scn *scngrp)
144 {
145   /* SCNGRP is the section descriptor for a section group which might
146      contain debug sections.  */
147   Elf_Data *data = elf_getdata (scngrp, NULL);
148   if (data == NULL)
149     {
150       /* We cannot read the section content.  Fail!  */
151       free (result);
152       return NULL;
153     }
154 
155   /* The content of the section is a number of 32-bit words which
156      represent section indices.  The first word is a flag word.  */
157   Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
158   size_t cnt;
159   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
160     {
161       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
162       if (scn == NULL)
163 	{
164 	  /* A section group refers to a non-existing section.  Should
165 	     never happen.  */
166 	  __libdw_seterrno (DWARF_E_INVALID_ELF);
167 	  free (result);
168 	  return NULL;
169 	}
170 
171       check_section (result, ehdr, scn, true);
172     }
173 
174   return valid_p (result);
175 }
176 
177 
178 Dwarf *
dwarf_begin_elf(elf,cmd,scngrp)179 dwarf_begin_elf (elf, cmd, scngrp)
180      Elf *elf;
181      Dwarf_Cmd cmd;
182      Elf_Scn *scngrp;
183 {
184   GElf_Ehdr *ehdr;
185   GElf_Ehdr ehdr_mem;
186 
187   /* Get the ELF header of the file.  We need various pieces of
188      information from it.  */
189   ehdr = gelf_getehdr (elf, &ehdr_mem);
190   if (ehdr == NULL)
191     {
192       if (elf_kind (elf) != ELF_K_ELF)
193 	__libdw_seterrno (DWARF_E_NOELF);
194       else
195 	__libdw_seterrno (DWARF_E_GETEHDR_ERROR);
196 
197       return NULL;
198     }
199 
200 
201   /* Default memory allocation size.  */
202   size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
203 
204   /* Allocate the data structure.  */
205   Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
206   if (result == NULL)
207     {
208       __libdw_seterrno (DWARF_E_NOMEM);
209       return NULL;
210     }
211 
212   /* Fill in some values.  */
213   if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
214       || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
215     result->other_byte_order = true;
216 
217   result->elf = elf;
218 
219   /* Initialize the memory handling.  */
220   result->mem_default_size = mem_default_size;
221   result->oom_handler = __libdw_oom;
222   result->mem_tail = (struct libdw_memblock *) (result + 1);
223   result->mem_tail->size = (result->mem_default_size
224 			    - offsetof (struct libdw_memblock, mem));
225   result->mem_tail->remaining = result->mem_tail->size;
226   result->mem_tail->prev = NULL;
227 
228 
229   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
230     {
231       /* If the caller provides a section group we get the DWARF
232 	 sections only from this setion group.  Otherwise we search
233 	 for the first section with the required name.  Further
234 	 sections with the name are ignored.  The DWARF specification
235 	 does not really say this is allowed.  */
236       if (scngrp == NULL)
237 	return global_read (result, elf, ehdr, cmd);
238       else
239 	return scngrp_read (result, elf, ehdr, cmd, scngrp);
240     }
241   else if (cmd == DWARF_C_WRITE)
242     {
243       __libdw_seterrno (DWARF_E_UNIMPL);
244       free (result);
245       return NULL;
246     }
247 
248   __libdw_seterrno (DWARF_E_INVALID_CMD);
249   free (result);
250   return NULL;
251 }
252