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 : 4 : __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
77 : : {
78 [ + - ]: 4 : if (dw == NULL)
79 : : return -1;
80 : :
81 : 4 : Elf *elf = dw->elf;
82 : 4 : Elf_Scn *scn = elf_nextscn (elf, NULL);
83 [ + - ]: 4 : if (scn == NULL)
84 : : return -1;
85 : :
86 : : do
87 : : {
88 : : GElf_Shdr shdr_mem;
89 : 4 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
90 [ + - ][ + - ]: 4 : if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
91 : : {
92 : 4 : size_t pos = 0;
93 : : GElf_Nhdr nhdr;
94 : : size_t name_pos;
95 : : size_t desc_pos;
96 : 4 : Elf_Data *data = elf_getdata (scn, NULL);
97 [ + - ]: 4 : while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos,
98 : : &desc_pos)) > 0)
99 [ + - ]: 4 : if (nhdr.n_type == NT_GNU_BUILD_ID
100 [ + - ]: 4 : && nhdr.n_namesz == sizeof "GNU"
101 [ + - ]: 4 : && ! memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU"))
102 : 4 : return (nhdr.n_descsz == id_len
103 : 4 : && ! memcmp (data->d_buf + desc_pos,
104 [ + - ][ + - ]: 4 : build_id, id_len)) ? 0 : 1;
105 : : }
106 : : }
107 [ # # ]: 4 : 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 : 5 : try_debugaltlink (Dwarf *result, const char *try_name,
116 : : const uint8_t *build_id, const size_t id_len)
117 : : {
118 : 5 : int fd = open (try_name, O_RDONLY);
119 [ + + ]: 5 : if (fd > 0)
120 : : {
121 : 4 : result->alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ);
122 [ + - ]: 4 : if (result->alt_dwarf != NULL)
123 : : {
124 : 4 : Elf *elf = result->alt_dwarf->elf;
125 [ + - ]: 4 : if (__check_build_id (result->alt_dwarf, build_id, id_len) == 0
126 [ + - ]: 4 : && elf_cntl (elf, ELF_C_FDREAD) == 0)
127 : : {
128 : 4 : close (fd);
129 : 4 : result->free_alt = 1;
130 : 4 : return result;
131 : : }
132 : 0 : INTUSE (dwarf_end) (result->alt_dwarf);
133 : : }
134 : 5 : close (fd);
135 : : }
136 : : return NULL;
137 : : }
138 : :
139 : : /* For dwz multifile support, ignore if it looks wrong. */
140 : : static Dwarf *
141 : 4 : 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 [ + + ]: 4 : 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 : 1 : char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1];
157 : 1 : strcpy (id_name, DEBUG_PREFIX);
158 : 1 : int n = snprintf (&id_name[PREFIX_LEN - 1],
159 : 1 : 4, "%02" PRIx8 "/", (uint8_t) build_id[0]);
160 [ + - ]: 1 : assert (n == 3);
161 [ + + ]: 20 : for (size_t i = 1; i < id_len; ++i)
162 : : {
163 : 19 : n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2],
164 : 19 : 3, "%02" PRIx8, (uint8_t) build_id[i]);
165 [ - + ]: 19 : assert (n == 2);
166 : : }
167 : 1 : strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2],
168 : : ".debug");
169 : :
170 [ - + ]: 1 : 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 : 4 : result->alt_dwarf = NULL;
177 : : return result;
178 : : }
179 : : #endif /* ENABLE_DWZ */
180 : :
181 : : static Dwarf *
182 : 205935 : 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 : 205935 : shdr = gelf_getshdr (scn, &shdr_mem);
189 [ - + ]: 205935 : 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 [ + + ]: 205935 : 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 [ + - ][ + - ]: 194544 : 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 : 194544 : const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
213 : 194544 : shdr->sh_name);
214 [ + + ]: 194544 : 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 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
220 : 1 : __libdw_seterrno (DWARF_E_INVALID_ELF);
221 : 1 : free (result);
222 : : return NULL;
223 : : }
224 : :
225 : : #ifdef ENABLE_DWZ
226 : : /* For dwz multifile support, ignore if it looks wrong. */
227 [ + + ]: 194543 : if (strcmp (scnname, ".gnu_debugaltlink") == 0)
228 : : {
229 : 4 : Elf_Data *data = elf_getdata (scn, NULL);
230 [ + - ][ + - ]: 4 : if (data != NULL && data->d_size != 0)
231 : : {
232 : 4 : const char *alt_name = data->d_buf;
233 : 4 : const void *build_id = memchr (data->d_buf, '\0', data->d_size);
234 : 4 : const int id_len = data->d_size - (build_id - data->d_buf + 1);
235 [ + - ][ + - ]: 4 : if (alt_name && build_id && id_len > 0)
236 : 4 : return open_debugaltlink (result, alt_name, build_id + 1, id_len);
237 : : }
238 : : }
239 : : #endif /* ENABLE_DWZ */
240 : :
241 : : /* Recognize the various sections. Most names start with .debug_. */
242 : : size_t cnt;
243 [ + + ]: 2307528 : for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
244 [ + + ]: 2101593 : if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
245 : : {
246 : : /* Found it. Remember where the data is. */
247 [ + - ]: 37832 : if (unlikely (result->sectiondata[cnt] != NULL))
248 : : /* A section appears twice. That's bad. We ignore the section. */
249 : : break;
250 : :
251 : : /* Get the section data. */
252 : 37832 : Elf_Data *data = elf_getdata (scn, NULL);
253 [ + - ][ + - ]: 37832 : if (data != NULL && data->d_size != 0)
254 : : /* Yep, there is actually data available. */
255 : 37832 : result->sectiondata[cnt] = data;
256 : :
257 : : break;
258 : : }
259 : : #if USE_ZLIB
260 [ + + ][ - + ]: 2063761 : else if (scnname[0] == '.' && scnname[1] == 'z'
261 [ # # ]: 0 : && strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0)
262 : : {
263 : : /* A compressed section. */
264 : :
265 [ # # ]: 0 : if (unlikely (result->sectiondata[cnt] != NULL))
266 : : /* A section appears twice. That's bad. We ignore the section. */
267 : : break;
268 : :
269 : : /* Get the section data. */
270 : 0 : Elf_Data *data = elf_getdata (scn, NULL);
271 [ # # ][ # # ]: 0 : if (data != NULL && data->d_size != 0)
272 : : {
273 : : /* There is a 12-byte header of "ZLIB" followed by
274 : : an 8-byte big-endian size. */
275 : :
276 [ # # ]: 0 : if (unlikely (data->d_size < 4 + 8)
277 [ # # ]: 0 : || unlikely (memcmp (data->d_buf, "ZLIB", 4) != 0))
278 : : break;
279 : :
280 : : uint64_t size;
281 : 0 : memcpy (&size, data->d_buf + 4, sizeof size);
282 : 0 : size = be64toh (size);
283 : :
284 : 0 : Elf_Data *zdata = malloc (sizeof (Elf_Data) + size);
285 [ # # ]: 0 : if (unlikely (zdata == NULL))
286 : : break;
287 : :
288 : 0 : zdata->d_buf = &zdata[1];
289 : 0 : zdata->d_type = ELF_T_BYTE;
290 : 0 : zdata->d_version = EV_CURRENT;
291 : 0 : zdata->d_size = size;
292 : 0 : zdata->d_off = 0;
293 : 0 : zdata->d_align = 1;
294 : :
295 : 0 : z_stream z =
296 : : {
297 : 0 : .next_in = data->d_buf + 4 + 8,
298 : 0 : .avail_in = data->d_size - 4 - 8,
299 : : .next_out = zdata->d_buf,
300 : : .avail_out = zdata->d_size
301 : : };
302 : 0 : int zrc = inflateInit (&z);
303 [ # # ][ # # ]: 0 : while (z.avail_in > 0 && likely (zrc == Z_OK))
304 : : {
305 : 0 : z.next_out = zdata->d_buf + (zdata->d_size - z.avail_out);
306 : 0 : zrc = inflate (&z, Z_FINISH);
307 [ # # ]: 0 : if (unlikely (zrc != Z_STREAM_END))
308 : : {
309 : : zrc = Z_DATA_ERROR;
310 : : break;
311 : : }
312 : 0 : zrc = inflateReset (&z);
313 : : }
314 [ # # ]: 0 : if (likely (zrc == Z_OK))
315 : 0 : zrc = inflateEnd (&z);
316 : :
317 [ # # ][ # # ]: 0 : if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
318 : 0 : free (zdata);
319 : : else
320 : : {
321 : 0 : result->sectiondata[cnt] = zdata;
322 : 0 : result->sectiondata_gzip_mask |= 1U << cnt;
323 : : }
324 : : }
325 : :
326 : : break;
327 : : }
328 : : #endif
329 : :
330 : : return result;
331 : : }
332 : :
333 : :
334 : : /* Check whether all the necessary DWARF information is available. */
335 : : static Dwarf *
336 : 5474 : valid_p (Dwarf *result)
337 : : {
338 : : /* We looked at all the sections. Now determine whether all the
339 : : sections with debugging information we need are there.
340 : :
341 : : XXX Which sections are absolutely necessary? Add tests if
342 : : necessary. For now we require only .debug_info. Hopefully this
343 : : is correct. */
344 [ + + ]: 5474 : if (likely (result != NULL)
345 [ + + ]: 5473 : && unlikely (result->sectiondata[IDX_debug_info] == NULL))
346 : : {
347 : 57 : __libdw_free_zdata (result);
348 : 57 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
349 : 57 : __libdw_seterrno (DWARF_E_NO_DWARF);
350 : 57 : free (result);
351 : 57 : result = NULL;
352 : : }
353 : :
354 : 5474 : return result;
355 : : }
356 : :
357 : :
358 : : static Dwarf *
359 : 5474 : global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
360 : : {
361 : 5474 : Elf_Scn *scn = NULL;
362 : :
363 [ + + ][ + + ]: 211409 : while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
364 : 205935 : result = check_section (result, ehdr, scn, false);
365 : :
366 : 5474 : return valid_p (result);
367 : : }
368 : :
369 : :
370 : : static Dwarf *
371 : 0 : scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
372 : : {
373 : : /* SCNGRP is the section descriptor for a section group which might
374 : : contain debug sections. */
375 : 0 : Elf_Data *data = elf_getdata (scngrp, NULL);
376 [ # # ]: 0 : if (data == NULL)
377 : : {
378 : : /* We cannot read the section content. Fail! */
379 : 0 : __libdw_free_zdata (result);
380 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
381 : 0 : free (result);
382 : 0 : return NULL;
383 : : }
384 : :
385 : : /* The content of the section is a number of 32-bit words which
386 : : represent section indices. The first word is a flag word. */
387 : 0 : Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
388 : : size_t cnt;
389 [ # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
390 : : {
391 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
392 [ # # ]: 0 : if (scn == NULL)
393 : : {
394 : : /* A section group refers to a non-existing section. Should
395 : : never happen. */
396 : 0 : __libdw_free_zdata (result);
397 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
398 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
399 : 0 : free (result);
400 : 0 : return NULL;
401 : : }
402 : :
403 : 0 : result = check_section (result, ehdr, scn, true);
404 [ # # ]: 0 : if (result == NULL)
405 : : break;
406 : : }
407 : :
408 : 0 : return valid_p (result);
409 : : }
410 : :
411 : :
412 : : Dwarf *
413 : 5474 : dwarf_begin_elf (elf, cmd, scngrp)
414 : : Elf *elf;
415 : : Dwarf_Cmd cmd;
416 : : Elf_Scn *scngrp;
417 : : {
418 : : GElf_Ehdr *ehdr;
419 : : GElf_Ehdr ehdr_mem;
420 : :
421 : : /* Get the ELF header of the file. We need various pieces of
422 : : information from it. */
423 : 5474 : ehdr = gelf_getehdr (elf, &ehdr_mem);
424 [ - + ]: 5474 : if (ehdr == NULL)
425 : : {
426 [ # # ]: 0 : if (elf_kind (elf) != ELF_K_ELF)
427 : 0 : __libdw_seterrno (DWARF_E_NOELF);
428 : : else
429 : 0 : __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
430 : :
431 : : return NULL;
432 : : }
433 : :
434 : :
435 : : /* Default memory allocation size. */
436 : 5474 : size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
437 : :
438 : : /* Allocate the data structure. */
439 : 5474 : Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
440 [ + - ]: 5474 : if (unlikely (result == NULL)
441 [ - + ]: 5474 : || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
442 : : {
443 : 0 : free (result);
444 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
445 : : return NULL;
446 : : }
447 : :
448 : : /* Fill in some values. */
449 [ + + ]: 5474 : if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
450 : : || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
451 : 20 : result->other_byte_order = true;
452 : :
453 : 5474 : result->elf = elf;
454 : :
455 : : /* Initialize the memory handling. */
456 : 5474 : result->mem_default_size = mem_default_size;
457 : 5474 : result->oom_handler = __libdw_oom;
458 : 5474 : result->mem_tail = (struct libdw_memblock *) (result + 1);
459 : 5474 : result->mem_tail->size = (result->mem_default_size
460 : 5474 : - offsetof (struct libdw_memblock, mem));
461 : 5474 : result->mem_tail->remaining = result->mem_tail->size;
462 : 5474 : result->mem_tail->prev = NULL;
463 : :
464 [ + - ]: 5474 : if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
465 : : {
466 : : /* If the caller provides a section group we get the DWARF
467 : : sections only from this setion group. Otherwise we search
468 : : for the first section with the required name. Further
469 : : sections with the name are ignored. The DWARF specification
470 : : does not really say this is allowed. */
471 [ + - ]: 5474 : if (scngrp == NULL)
472 : 5474 : return global_read (result, elf, ehdr);
473 : : else
474 : 0 : return scngrp_read (result, elf, ehdr, scngrp);
475 : : }
476 [ # # ]: 0 : else if (cmd == DWARF_C_WRITE)
477 : : {
478 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
479 : 0 : __libdw_seterrno (DWARF_E_UNIMPL);
480 : 0 : free (result);
481 : : return NULL;
482 : : }
483 : :
484 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
485 : 0 : __libdw_seterrno (DWARF_E_INVALID_CMD);
486 : 5474 : free (result);
487 : : return NULL;
488 : : }
489 : 205935 : INTDEF(dwarf_begin_elf)
|