diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index cc8bb74d083..d76341ac70e 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,9 @@ +2019-01-17 Tom de Vries + + * elf.c (elf_add): Add and handle with_buildid_data and + with_buildid_size parameters. Handle .gnu_debugaltlink section. + (phdr_callback, backtrace_initialize): Add arguments to elf_add calls. + 2019-01-16 Tom de Vries * dwarf.c (read_referenced_name_from_attr): New function. Factor out diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in index c595a8b4a3e..17e7ea86879 100644 --- a/libbacktrace/Makefile.in +++ b/libbacktrace/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # Makefile.am -- Backtrace Makefile. -# Copyright (C) 2012-2018 Free Software Foundation, Inc. +# Copyright (C) 2012-2019 Free Software Foundation, Inc. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index 85a323c5876..abe4cded5e9 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -2638,7 +2638,8 @@ static int elf_add (struct backtrace_state *state, const char *filename, int descriptor, uintptr_t base_address, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf, - int exe, int debuginfo) + int exe, int debuginfo, const char *with_buildid_data, + uint32_t with_buildid_size) { struct backtrace_view ehdr_view; b_elf_ehdr ehdr; @@ -2670,6 +2671,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, int debuglink_view_valid; const char *debuglink_name; uint32_t debuglink_crc; + struct backtrace_view debugaltlink_view; + int debugaltlink_view_valid; + const char *debugaltlink_name; + const char *debugaltlink_buildid_data; + uint32_t debugaltlink_buildid_size; off_t min_offset; off_t max_offset; struct backtrace_view debug_view; @@ -2694,6 +2700,10 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, debuglink_view_valid = 0; debuglink_name = NULL; debuglink_crc = 0; + debugaltlink_view_valid = 0; + debugaltlink_name = NULL; + debugaltlink_buildid_data = NULL; + debugaltlink_buildid_size = 0; debug_view_valid = 0; opd = NULL; @@ -2873,6 +2883,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~ 3); buildid_size = note->descsz; } + + if (with_buildid_size != 0) + { + if (buildid_size != with_buildid_size) + goto fail; + + if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0) + goto fail; + } } /* Read the debuglink file if present. */ @@ -2899,6 +2918,32 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, } } + if (!debugaltlink_view_valid + && strcmp (name, ".gnu_debugaltlink") == 0) + { + const char *debugaltlink_data; + size_t debugaltlink_name_len; + + if (!backtrace_get_view (state, descriptor, shdr->sh_offset, + shdr->sh_size, error_callback, data, + &debugaltlink_view)) + goto fail; + + debugaltlink_view_valid = 1; + debugaltlink_data = (const char *) debugaltlink_view.data; + debugaltlink_name = debugaltlink_data; + debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size); + if (debugaltlink_name_len < shdr->sh_size) + { + /* Include terminating zero. */ + debugaltlink_name_len =+ 1; + + debugaltlink_buildid_data + = debugaltlink_data + debugaltlink_name_len; + debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len; + } + } + /* Read the .opd section on PowerPC64 ELFv1. */ if (ehdr.e_machine == EM_PPC64 && (ehdr.e_flags & EF_PPC64_ABI) < 2 @@ -2993,8 +3038,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, if (debuglink_view_valid) backtrace_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + backtrace_release_view (state, &debugaltlink_view, error_callback, + data); ret = elf_add (state, NULL, d, base_address, error_callback, data, - fileline_fn, found_sym, found_dwarf, 0, 1); + fileline_fn, found_sym, found_dwarf, 0, 1, NULL, 0); if (ret < 0) backtrace_close (d, error_callback, data); else @@ -3028,8 +3076,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, backtrace_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + backtrace_release_view (state, &debugaltlink_view, error_callback, + data); ret = elf_add (state, NULL, d, base_address, error_callback, data, - fileline_fn, found_sym, found_dwarf, 0, 1); + fileline_fn, found_sym, found_dwarf, 0, 1, NULL, 0); if (ret < 0) backtrace_close (d, error_callback, data); else @@ -3044,6 +3095,36 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, debuglink_view_valid = 0; } + if (debugaltlink_name != NULL) + { + int d; + + d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name, + 0, error_callback, data); + if (d >= 0) + { + int ret; + + ret = elf_add (state, filename, d, base_address, error_callback, data, + fileline_fn, found_sym, found_dwarf, 0, 1, + debugaltlink_buildid_data, debugaltlink_buildid_size); + backtrace_release_view (state, &debugaltlink_view, error_callback, + data); + debugaltlink_view_valid = 0; + if (ret < 0) + { + backtrace_close (d, error_callback, data); + return ret; + } + } + } + + if (debugaltlink_view_valid) + { + backtrace_release_view (state, &debugaltlink_view, error_callback, data); + debugaltlink_view_valid = 0; + } + /* Read all the debug sections in a single view, since they are probably adjacent in the file. We never release this view. */ @@ -3199,6 +3280,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, backtrace_release_view (state, &strtab_view, error_callback, data); if (debuglink_view_valid) backtrace_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + backtrace_release_view (state, &debugaltlink_view, error_callback, data); if (buildid_view_valid) backtrace_release_view (state, &buildid_view, error_callback, data); if (debug_view_valid) @@ -3269,7 +3352,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, if (elf_add (pd->state, filename, descriptor, info->dlpi_addr, pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, - &found_dwarf, 0, 0)) + &found_dwarf, 0, 0, NULL, 0)) { if (found_dwarf) { @@ -3297,7 +3380,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename, struct phdr_data pd; ret = elf_add (state, filename, descriptor, 0, error_callback, data, - &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0); + &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0, NULL, 0); if (!ret) return 0;