[PATCH v2 3/3] dwarf_begin, dwarf_begin_elf: DWARF_C_FLAG_NO_DEBUGALTLINK command flag

Mark Wielaard mjw at redhat.com
Fri Apr 11 09:24:47 UTC 2014


On Thu, 2014-04-10 at 20:26 +0200, Florian Weimer wrote:
> On 04/10/2014 08:16 PM, Mark Wielaard wrote:
> > I don't really like this. This assumes we keep the magic opening of the
> > altfile in dw. But I think we should just drop it eventually
> 
> Yes, but that's not really backwards-compatible.  Even the test suite 
> breaks.

Yes, if we make that change, then we should document clearly that people
should add alt-files explicitly, if they aren't using libdwfl functions
yet to get at the Dwarf. The current support is behind an experimental
configure flag: --enable-dwz enable experimental GNU ref_alt FORM, dwz
multi file support in libdw. So I don't feel too bad for breaking things
a little as long as it doesn't break ABI. But we will see how severe it
all is before doing it.

>  > and move any magic to the dwfl side. When we provide dwarf_setalt() 
> then users
> > should just explicitly always use that IMHO.
> 
> I have a patch for that as well, but I couldn't find a way to emulate 
> the old dwarf_begin behavior using dwfl in the tests/allfcts.c test 
> case.  Pointers to documentation or example code much appreciated. :-)

In the case of the tests/run-allfcts-multi.sh testcase I think the "fix"
is simply to be explicit about the Dwarf and alt-Dwarf under test. So
just change tests/allfcts.c to take as argument both the main Dwarf and
the alt-file, and then change the invocation to something like:
  allfcts testfile_multi_main:testfile_multi.dwz \
    libtestfile_multi_shared.so:testfile_multi.dwz \
    testfile-dwzstr:testfile-dwzstr.multi
Or if you like to extend the test, just use your newly proposed
dwarf_debugaltlink function (or how we will call it) to fetch it in the
testcase. The test is about the Dwarf and alt-file handling, so better
be explicit about it in the first place.

We really should have more libdwfl use documentation... But for a
generic dwfl setup example see src/stack.c. That does a bit more than
most, but then you can easily handle the interesting life pid and core
file cases. Or see libdwfl/argp-std.c that wraps it all in a convenient
argp handler (and shows some examples of handling online kernels). See
below that code, plus extended to handle simple elf-files (with
automatic separate .debug file searching).

// You might want to set this to influence the standard dwfl debuginfo
// search path. See "Standard callbacks" comment in elfutils/libdwfl.h
static char *debuginfo_path = NULL;

// Life pid case...
static const Dwfl_Callbacks proc_callbacks =
  {
    .find_elf = dwfl_linux_proc_find_elf,
    .find_debuginfo = dwfl_standard_find_debuginfo,
    .debuginfo_path = &debuginfo_path,
  };

  int pid = ...;

  dwfl = dwfl_begin (&proc_callbacks);
  if (dwfl == NULL)
    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));

  int err = dwfl_linux_proc_report (dwfl, pid);
  if (err < 0)
    error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %d: %s", pid,
           dwfl_errmsg (-1));
  else if (err > 0)
    error (EXIT_BAD, err, "dwfl_linux_proc_report pid %d", pid);

  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
    error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));

  // Optionally if you need the proc state:
  int err = dwfl_linux_proc_attach (dwfl, pid, false);
  if (err < 0)
    error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
           dwfl_errmsg (-1));
  else if (err > 0)
    error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid);


// Core file case...
static const Dwfl_Callbacks core_callbacks =
  {
    .find_elf = dwfl_build_id_find_elf,
    .find_debuginfo = dwfl_standard_find_debuginfo,
    .debuginfo_path = &debuginfo_path,
  };

  /* Core file opened with libelf.  */
  Elf *core = ...;
  /* Optional path to original executable, may be NULL.  */
  const char *exec = ...;

  dwfl = dwfl_begin (&core_callbacks);
  if (dwfl == NULL)
    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
  if (dwfl_core_file_report (dwfl, core, exec) < 0)
    error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));

  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
    error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));

  // Optionally if you need the core state:
  if (dwfl_core_file_attach (dwfl, core) < 0)
    error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));


// Single static ELF file case... (also handles ET_REL kernel modules)
// You can also combine the core_callbacks and file_callbacks in one
// to handle both cases. And you can keep adding more ET_DYN files with
// dwfl_report_offline as long as you report the ET_EXEC one first.
static const Dwfl_Callbacks file_callbacks =
  {
    .section_address = dwfl_offline_section_address,
    .find_debuginfo = dwfl_standard_find_debuginfo,
    .debuginfo_path = &debuginfo_path,
  };

  const char *elf_file = ...;

  dwfl = dwfl_begin (&file_callbacks);
  if (dwfl == NULL)
    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
  if (dwfl_report_offline (dwfl, elf_file, elf_file, -1) == NULL)
    error (EXIT_BAD, 0, "dwfl_report_offline: %s", dwfl_errmsg (-1));

  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
    error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));

Then you can simply walk all Dwarf found for the reported modules
through things like:

  Dwarf_Die *cu = NULL;
  Dwarf_Addr bias;
  while ((cu = dwfl_nextcu (dwfl, cu, &bias)) != NULL)
    {
      Dwarf_Die *die = cu;
      printf ("Compile Unit: %s\n", dwarf_diename (die));
    }

I'll work on making sure the alt-files are properly attached in these
cases, even if we drop the automatic alt-file search from libdw proper.

Cheers,

Mark



More information about the elfutils-devel mailing list