Branch data Line data Source code
1 : : /* Create descriptor from ELF descriptor for processing file.
2 : : Copyright (C) 2002-2011 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <assert.h>
35 : : #include <inttypes.h>
36 : : #include <stdbool.h>
37 : : #include <stddef.h>
38 : : #include <stdlib.h>
39 : : #include <stdio.h>
40 : : #include <string.h>
41 : : #include <unistd.h>
42 : : #include <sys/types.h>
43 : : #include <sys/stat.h>
44 : : #include <fcntl.h>
45 : :
46 : : #include "libdwP.h"
47 : :
48 : : #if USE_ZLIB
49 : : # include <endian.h>
50 : : # define crc32 loser_crc32
51 : : # include <zlib.h>
52 : : # undef crc32
53 : : #endif
54 : :
55 : :
56 : : /* Section names. */
57 : : static const char dwarf_scnnames[IDX_last][17] =
58 : : {
59 : : [IDX_debug_info] = ".debug_info",
60 : : [IDX_debug_types] = ".debug_types",
61 : : [IDX_debug_abbrev] = ".debug_abbrev",
62 : : [IDX_debug_aranges] = ".debug_aranges",
63 : : [IDX_debug_line] = ".debug_line",
64 : : [IDX_debug_frame] = ".debug_frame",
65 : : [IDX_debug_loc] = ".debug_loc",
66 : : [IDX_debug_pubnames] = ".debug_pubnames",
67 : : [IDX_debug_str] = ".debug_str",
68 : : [IDX_debug_macinfo] = ".debug_macinfo",
69 : : [IDX_debug_macro] = ".debug_macro",
70 : : [IDX_debug_ranges] = ".debug_ranges"
71 : : };
72 : : #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
73 : :
74 : : #ifdef ENABLE_DWZ
75 : : internal_function int
76 : 2 : __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
77 : : {
78 [ + - ]: 2 : if (dw == NULL)
79 : : return -1;
80 : :
81 : 2 : Elf *elf = dw->elf;
82 : 2 : Elf_Scn *scn = elf_nextscn (elf, NULL);
83 [ + - ]: 2 : if (scn == NULL)
84 : : return -1;
85 : :
86 : : do
87 : : {
88 : : GElf_Shdr shdr_mem;
89 : 2 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
90 [ + - ][ + - ]: 2 : if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
91 : : {
92 : 2 : size_t pos = 0;
93 : : GElf_Nhdr nhdr;
94 : : size_t name_pos;
95 : : size_t desc_pos;
96 : 2 : Elf_Data *data = elf_getdata (scn, NULL);
97 [ + - ]: 2 : while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos,
98 : : &desc_pos)) > 0)
99 [ + - ]: 2 : if (nhdr.n_type == NT_GNU_BUILD_ID
100 [ + - ]: 2 : && nhdr.n_namesz == sizeof "GNU"
101 [ + - ]: 2 : && ! memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU"))
102 : 2 : return (nhdr.n_descsz == id_len
103 : 2 : && ! memcmp (data->d_buf + desc_pos,
104 [ + - ][ + - ]: 2 : build_id, id_len)) ? 0 : 1;
105 : : }
106 : : }
107 [ # # ]: 2 : while ((scn = elf_nextscn (elf, scn)) != NULL);
108 : :
109 : : return -1;
110 : : }
111 : :
112 : : /* Try to open an debug alt link by name, checking build_id.
113 : : Marks free_alt on success, return NULL on failure. */
114 : : static Dwarf *
115 : 2 : try_debugaltlink (Dwarf *result, const char *try_name,
116 : : const uint8_t *build_id, const size_t id_len)
117 : : {
118 : 2 : int fd = open (try_name, O_RDONLY);
119 [ + - ]: 2 : if (fd > 0)
120 : : {
121 : 2 : result->alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ);
122 [ + - ]: 2 : if (result->alt_dwarf != NULL)
123 : : {
124 : 2 : Elf *elf = result->alt_dwarf->elf;
125 [ + - ]: 2 : if (__check_build_id (result->alt_dwarf, build_id, id_len) == 0
126 [ + - ]: 2 : && elf_cntl (elf, ELF_C_FDREAD) == 0)
127 : : {
128 : 2 : close (fd);
129 : 2 : result->free_alt = 1;
130 : 2 : return result;
131 : : }
132 : 0 : INTUSE (dwarf_end) (result->alt_dwarf);
133 : : }
134 : 2 : close (fd);
135 : : }
136 : : return NULL;
137 : : }
138 : :
139 : : /* For dwz multifile support, ignore if it looks wrong. */
140 : : static Dwarf *
141 : 2 : open_debugaltlink (Dwarf *result, const char *alt_name,
142 : : const uint8_t *build_id, const size_t id_len)
143 : : {
144 : : /* First try the name itself, it is either an absolute path or
145 : : a relative one. Sadly we don't know relative from where at
146 : : this point. */
147 [ - + ]: 2 : if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
148 : : return result;
149 : :
150 : : /* Lets try based on the build-id. This is somewhat distro specific,
151 : : we are following the Fedora implementation described at
152 : : https://fedoraproject.org/wiki/Releases/FeatureBuildId#Find_files_by_build_ID
153 : : */
154 : : #define DEBUG_PREFIX "/usr/lib/debug/.build-id/"
155 : : #define PREFIX_LEN sizeof (DEBUG_PREFIX)
156 : 0 : char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1];
157 : 0 : strcpy (id_name, DEBUG_PREFIX);
158 : 0 : int n = snprintf (&id_name[PREFIX_LEN - 1],
159 : 0 : 4, "%02" PRIx8 "/", (uint8_t) build_id[0]);
160 [ # # ]: 0 : assert (n == 3);
161 [ # # ]: 0 : for (size_t i = 1; i < id_len; ++i)
162 : : {
163 : 0 : n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2],
164 : 0 : 3, "%02" PRIx8, (uint8_t) build_id[i]);
165 [ # # ]: 0 : assert (n == 2);
166 : : }
167 : 0 : strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2],
168 : : ".debug");
169 : :
170 [ # # ]: 0 : if (try_debugaltlink (result, id_name, build_id, id_len))
171 : : return result;
172 : :
173 : : /* Everything failed, mark this Dwarf as not having an alternate,
174 : : but don't fail the load. The user may want to set it by hand
175 : : before usage. */
176 : 2 : result->alt_dwarf = NULL;
177 : : return result;
178 : : }
179 : : #endif /* ENABLE_DWZ */
180 : :
181 : : static Dwarf *
182 : 205709 : check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
183 : : {
184 : : GElf_Shdr shdr_mem;
185 : : GElf_Shdr *shdr;
186 : :
187 : : /* Get the section header data. */
188 : 205709 : shdr = gelf_getshdr (scn, &shdr_mem);
189 [ - + ]: 205709 : if (shdr == NULL)
190 : : /* This should never happen. If it does something is
191 : : wrong in the libelf library. */
192 : 0 : abort ();
193 : :
194 : : /* Ignore any SHT_NOBITS sections. Debugging sections should not
195 : : have been stripped, but in case of a corrupt file we won't try
196 : : to look at the missing data. */
197 [ + + ]: 205709 : if (unlikely (shdr->sh_type == SHT_NOBITS))
198 : : return result;
199 : :
200 : : /* Make sure the section is part of a section group only iff we
201 : : really need it. If we are looking for the global (= non-section
202 : : group debug info) we have to ignore all the info in section
203 : : groups. If we are looking into a section group we cannot look at
204 : : a section which isn't part of the section group. */
205 [ + - ][ + - ]: 194328 : if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
206 : : /* Ignore the section. */
207 : : return result;
208 : :
209 : :
210 : : /* We recognize the DWARF section by their names. This is not very
211 : : safe and stable but the best we can do. */
212 : 194328 : const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
213 : 194328 : shdr->sh_name);
214 [ + + ]: 194328 : if (scnname == NULL)
215 : : {
216 : : /* The section name must be valid. Otherwise is the ELF file
217 : : invalid. */
218 : 1 : __libdw_free_zdata (result);
219 : 1 : __libdw_seterrno (DWARF_E_INVALID_ELF);
220 : 1 : free (result);
221 : : return NULL;
222 : : }
223 : :
224 : : #ifdef ENABLE_DWZ
225 : : /* For dwz multifile support, ignore if it looks wrong. */
226 [ + + ]: 194327 : if (strcmp (scnname, ".gnu_debugaltlink") == 0)
227 : : {
228 : 2 : Elf_Data *data = elf_getdata (scn, NULL);
229 [ + - ][ + - ]: 2 : if (data != NULL && data->d_size != 0)
230 : : {
231 : 2 : const char *alt_name = data->d_buf;
232 : 2 : const void *build_id = memchr (data->d_buf, '\0', data->d_size);
233 : 2 : const int id_len = data->d_size - (build_id - data->d_buf + 1);
234 [ + - ][ + - ]: 2 : if (alt_name && build_id && id_len > 0)
235 : 2 : return open_debugaltlink (result, alt_name, build_id + 1, id_len);
236 : : }
237 : : }
238 : : #endif /* ENABLE_DWZ */
239 : :
240 : : /* Recognize the various sections. Most names start with .debug_. */
241 : : size_t cnt;
242 [ + + ]: 2304970 : for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
243 [ + + ]: 2099261 : if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
244 : : {
245 : : /* Found it. Remember where the data is. */
246 [ + - ]: 37783 : if (unlikely (result->sectiondata[cnt] != NULL))
247 : : /* A section appears twice. That's bad. We ignore the section. */
248 : : break;
249 : :
250 : : /* Get the section data. */
251 : 37783 : Elf_Data *data = elf_getdata (scn, NULL);
252 [ + - ][ + - ]: 37783 : if (data != NULL && data->d_size != 0)
253 : : /* Yep, there is actually data available. */
254 : 37783 : result->sectiondata[cnt] = data;
255 : :
256 : : break;
257 : : }
258 : : #if USE_ZLIB
259 [ + + ][ - + ]: 2061478 : else if (scnname[0] == '.' && scnname[1] == 'z'
260 [ # # ]: 0 : && strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0)
261 : : {
262 : : /* A compressed section. */
263 : :
264 [ # # ]: 0 : if (unlikely (result->sectiondata[cnt] != NULL))
265 : : /* A section appears twice. That's bad. We ignore the section. */
266 : : break;
267 : :
268 : : /* Get the section data. */
269 : 0 : Elf_Data *data = elf_getdata (scn, NULL);
270 [ # # ][ # # ]: 0 : if (data != NULL && data->d_size != 0)
271 : : {
272 : : /* There is a 12-byte header of "ZLIB" followed by
273 : : an 8-byte big-endian size. */
274 : :
275 [ # # ]: 0 : if (unlikely (data->d_size < 4 + 8)
276 [ # # ]: 0 : || unlikely (memcmp (data->d_buf, "ZLIB", 4) != 0))
277 : : break;
278 : :
279 : : uint64_t size;
280 : 0 : memcpy (&size, data->d_buf + 4, sizeof size);
281 [ # # ]: 0 : size = be64toh (size);
282 : :
283 : 0 : Elf_Data *zdata = malloc (sizeof (Elf_Data) + size);
284 [ # # ]: 0 : if (unlikely (zdata == NULL))
285 : : break;
286 : :
287 : 0 : zdata->d_buf = &zdata[1];
288 : 0 : zdata->d_type = ELF_T_BYTE;
289 : 0 : zdata->d_version = EV_CURRENT;
290 : 0 : zdata->d_size = size;
291 : 0 : zdata->d_off = 0;
292 : 0 : zdata->d_align = 1;
293 : :
294 : 0 : z_stream z =
295 : : {
296 : 0 : .next_in = data->d_buf + 4 + 8,
297 : 0 : .avail_in = data->d_size - 4 - 8,
298 : : .next_out = zdata->d_buf,
299 : : .avail_out = zdata->d_size
300 : : };
301 : 0 : int zrc = inflateInit (&z);
302 [ # # ][ # # ]: 0 : while (z.avail_in > 0 && likely (zrc == Z_OK))
303 : : {
304 : 0 : z.next_out = zdata->d_buf + (zdata->d_size - z.avail_out);
305 : 0 : zrc = inflate (&z, Z_FINISH);
306 [ # # ]: 0 : if (unlikely (zrc != Z_STREAM_END))
307 : : {
308 : : zrc = Z_DATA_ERROR;
309 : : break;
310 : : }
311 : 0 : zrc = inflateReset (&z);
312 : : }
313 [ # # ]: 0 : if (likely (zrc == Z_OK))
314 : 0 : zrc = inflateEnd (&z);
315 : :
316 [ # # ][ # # ]: 0 : if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
317 : 0 : free (zdata);
318 : : else
319 : : {
320 : 0 : result->sectiondata[cnt] = zdata;
321 : 0 : result->sectiondata_gzip_mask |= 1U << cnt;
322 : : }
323 : : }
324 : :
325 : : break;
326 : : }
327 : : #endif
328 : :
329 : : return result;
330 : : }
331 : :
332 : :
333 : : /* Check whether all the necessary DWARF information is available. */
334 : : static Dwarf *
335 : 5466 : valid_p (Dwarf *result)
336 : : {
337 : : /* We looked at all the sections. Now determine whether all the
338 : : sections with debugging information we need are there.
339 : :
340 : : XXX Which sections are absolutely necessary? Add tests if
341 : : necessary. For now we require only .debug_info. Hopefully this
342 : : is correct. */
343 [ + + ]: 5466 : if (likely (result != NULL)
344 [ + + ]: 5465 : && unlikely (result->sectiondata[IDX_debug_info] == NULL))
345 : : {
346 : 55 : __libdw_free_zdata (result);
347 : 55 : __libdw_seterrno (DWARF_E_NO_DWARF);
348 : 55 : free (result);
349 : 55 : result = NULL;
350 : : }
351 : :
352 : 5466 : return result;
353 : : }
354 : :
355 : :
356 : : static Dwarf *
357 : 5466 : global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
358 : : {
359 : 5466 : Elf_Scn *scn = NULL;
360 : :
361 [ + + ][ + + ]: 211175 : while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
362 : 205709 : result = check_section (result, ehdr, scn, false);
363 : :
364 : 5466 : return valid_p (result);
365 : : }
366 : :
367 : :
368 : : static Dwarf *
369 : 0 : scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
370 : : {
371 : : /* SCNGRP is the section descriptor for a section group which might
372 : : contain debug sections. */
373 : 0 : Elf_Data *data = elf_getdata (scngrp, NULL);
374 [ # # ]: 0 : if (data == NULL)
375 : : {
376 : : /* We cannot read the section content. Fail! */
377 : 0 : __libdw_free_zdata (result);
378 : 0 : free (result);
379 : 0 : return NULL;
380 : : }
381 : :
382 : : /* The content of the section is a number of 32-bit words which
383 : : represent section indices. The first word is a flag word. */
384 : 0 : Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
385 : : size_t cnt;
386 [ # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
387 : : {
388 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
389 [ # # ]: 0 : if (scn == NULL)
390 : : {
391 : : /* A section group refers to a non-existing section. Should
392 : : never happen. */
393 : 0 : __libdw_free_zdata (result);
394 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
395 : 0 : free (result);
396 : 0 : return NULL;
397 : : }
398 : :
399 : 0 : result = check_section (result, ehdr, scn, true);
400 [ # # ]: 0 : if (result == NULL)
401 : : break;
402 : : }
403 : :
404 : 0 : return valid_p (result);
405 : : }
406 : :
407 : :
408 : : Dwarf *
409 : 5466 : dwarf_begin_elf (elf, cmd, scngrp)
410 : : Elf *elf;
411 : : Dwarf_Cmd cmd;
412 : : Elf_Scn *scngrp;
413 : : {
414 : : GElf_Ehdr *ehdr;
415 : : GElf_Ehdr ehdr_mem;
416 : :
417 : : /* Get the ELF header of the file. We need various pieces of
418 : : information from it. */
419 : 5466 : ehdr = gelf_getehdr (elf, &ehdr_mem);
420 [ - + ]: 5466 : if (ehdr == NULL)
421 : : {
422 [ # # ]: 0 : if (elf_kind (elf) != ELF_K_ELF)
423 : 0 : __libdw_seterrno (DWARF_E_NOELF);
424 : : else
425 : 0 : __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
426 : :
427 : : return NULL;
428 : : }
429 : :
430 : :
431 : : /* Default memory allocation size. */
432 : 5466 : size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
433 : :
434 : : /* Allocate the data structure. */
435 : 5466 : Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
436 [ + - ]: 5466 : if (unlikely (result == NULL)
437 [ - + ]: 5466 : || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
438 : : {
439 : 0 : free (result);
440 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
441 : : return NULL;
442 : : }
443 : :
444 : : /* Fill in some values. */
445 [ + + ]: 5466 : if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
446 : : || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
447 : 20 : result->other_byte_order = true;
448 : :
449 : 5466 : result->elf = elf;
450 : :
451 : : /* Initialize the memory handling. */
452 : 5466 : result->mem_default_size = mem_default_size;
453 : 5466 : result->oom_handler = __libdw_oom;
454 : 5466 : result->mem_tail = (struct libdw_memblock *) (result + 1);
455 : 5466 : result->mem_tail->size = (result->mem_default_size
456 : 5466 : - offsetof (struct libdw_memblock, mem));
457 : 5466 : result->mem_tail->remaining = result->mem_tail->size;
458 : 5466 : result->mem_tail->prev = NULL;
459 : :
460 [ + - ]: 5466 : if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
461 : : {
462 : : /* If the caller provides a section group we get the DWARF
463 : : sections only from this setion group. Otherwise we search
464 : : for the first section with the required name. Further
465 : : sections with the name are ignored. The DWARF specification
466 : : does not really say this is allowed. */
467 [ + - ]: 5466 : if (scngrp == NULL)
468 : 5466 : return global_read (result, elf, ehdr);
469 : : else
470 : 0 : return scngrp_read (result, elf, ehdr, scngrp);
471 : : }
472 [ # # ]: 0 : else if (cmd == DWARF_C_WRITE)
473 : : {
474 : 0 : __libdw_seterrno (DWARF_E_UNIMPL);
475 : 0 : free (result);
476 : : return NULL;
477 : : }
478 : :
479 : 0 : __libdw_seterrno (DWARF_E_INVALID_CMD);
480 : 5466 : free (result);
481 : : return NULL;
482 : : }
483 : 205709 : INTDEF(dwarf_begin_elf)
|