Skip to content

Support separate debug symbol files (as in GDB) #253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions backward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@
#else
#include <dlfcn.h>
#endif
#include <libgen.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect libgen.h header to exist when libdwarf is available, but that can be not true.

#endif

#if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1)
Expand Down Expand Up @@ -2152,7 +2153,7 @@ class TraceResolverLinuxImpl<trace_resolver_tag::libdwarf>
}

trace.object_filename = resolve_exec_path(symbol_info);
dwarf_fileobject &fobj = load_object_with_dwarf(symbol_info.dli_fname);
dwarf_fileobject &fobj = load_object_with_dwarf(symbol_info.dli_fname, trace.object_filename);
if (!fobj.dwarf_handle) {
return trace; // sad, we couldn't load the object :(
}
Expand Down Expand Up @@ -2312,7 +2313,7 @@ class TraceResolverLinuxImpl<trace_resolver_tag::libdwarf>
return strcmp(a, b) == 0;
}

dwarf_fileobject &load_object_with_dwarf(const std::string &filename_object) {
dwarf_fileobject &load_object_with_dwarf(const std::string &filename_object, const std::string &object_filename) {

if (!_dwarf_loaded) {
// Set the ELF library operating version
Expand Down Expand Up @@ -2431,17 +2432,25 @@ class TraceResolverLinuxImpl<trace_resolver_tag::libdwarf>
ELF_GET_DATA(32)
} else if (e_ident[EI_CLASS] == ELFCLASS64) {
// libelf might have been built without 64 bit support
#if __LIBELF64
Copy link
Contributor Author

@alexezeder alexezeder Jan 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit unrelated, but libelf installed on my PC (it's Arch Linux, but it's true also for Ubuntu 20.04 at least) does not have this definition, so the entire branch is omitted, so no 64-bit data, so no debuglink info. Probably we can work it around in a better way, but this line really stops me from having nice source locations.

ELF_GET_DATA(64)
#endif
}

if (!debuglink.empty()) {
// We have a debuglink section! Open an elf instance on that
// file instead. If we can't open the file, then return
// the elf handle we had already opened.
dwarf_file_t debuglink_file;
debuglink_file.reset(open(debuglink.c_str(), O_RDONLY));
{
char* object_filename_copy = strdup(object_filename.c_str());
const std::string directory_path = std::string(dirname(object_filename_copy));
free(object_filename_copy);
debuglink_file.reset(
open((directory_path + '/' + debuglink).c_str(), O_RDONLY));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect debuglink to have only filename since, according to docs:

The executable contains a debug link that specifies the name of the separate debug info file.

Also, objcopy tool writes only the filename component in the .gnu_debuglink section even if an absolute path is provided:
https://github.com/bminor/binutils-gdb/blob/b4edb38e827974ecdbc4a6712d8b21bf876018a2/bfd/opncls.c#L1707-L1708

if (debuglink_file.get() < 0) {
debuglink_file.reset(open(
(directory_path + "/.debug/" + debuglink).c_str(), O_RDONLY));
}
}
Comment on lines +2443 to +2453
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are only 2 locations covered since I don't know what global debug directories contain.

if (debuglink_file.get() > 0) {
dwarf_elf_t debuglink_elf;
debuglink_elf.reset(elf_begin(debuglink_file.get(), ELF_C_READ, NULL));
Expand Down