Blame libdwfl/find-debuginfo.c

Packit Service 97d2fb
/* Standard find_debuginfo callback for libdwfl.
Packit Service 97d2fb
   Copyright (C) 2005-2010, 2014, 2015, 2019 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include "libdwflP.h"
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
#include <sys/stat.h>
Packit Service 97d2fb
#include "system.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Try to open [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1.
Packit Service 97d2fb
   On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file.  */
Packit Service 97d2fb
static int
Packit Service 97d2fb
try_open (const struct stat *main_stat,
Packit Service 97d2fb
	  const char *dir, const char *subdir, const char *debuglink,
Packit Service 97d2fb
	  char **debuginfo_file_name)
Packit Service 97d2fb
{
Packit Service 97d2fb
  char *fname;
Packit Service 97d2fb
  if (dir == NULL && subdir == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      fname = strdup (debuglink);
Packit Service 97d2fb
      if (unlikely (fname == NULL))
Packit Service 97d2fb
	return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else if ((subdir == NULL ? asprintf (&fname, "%s/%s", dir, debuglink)
Packit Service 97d2fb
	    : dir == NULL ? asprintf (&fname, "%s/%s", subdir, debuglink)
Packit Service 97d2fb
	    : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0)
Packit Service 97d2fb
    return -1;
Packit Service 97d2fb
Packit Service 97d2fb
  struct stat st;
Packit Service 97d2fb
  int fd = TEMP_FAILURE_RETRY (open (fname, O_RDONLY));
Packit Service 97d2fb
  if (fd < 0)
Packit Service 97d2fb
    free (fname);
Packit Service 97d2fb
  else if (fstat (fd, &st) == 0
Packit Service 97d2fb
	   && st.st_ino == main_stat->st_ino
Packit Service 97d2fb
	   && st.st_dev == main_stat->st_dev)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* This is the main file by another name.  Don't look at it again.  */
Packit Service 97d2fb
      free (fname);
Packit Service 97d2fb
      close (fd);
Packit Service 97d2fb
      errno = ENOENT;
Packit Service 97d2fb
      fd = -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    *debuginfo_file_name = fname;
Packit Service 97d2fb
Packit Service 97d2fb
  return fd;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Return true iff the FD's contents CRC matches DEBUGLINK_CRC.  */
Packit Service 97d2fb
static inline bool
Packit Service 97d2fb
check_crc (int fd, GElf_Word debuglink_crc)
Packit Service 97d2fb
{
Packit Service 97d2fb
  uint32_t file_crc;
Packit Service 97d2fb
  return (__libdwfl_crc32_file (fd, &file_crc) == 0
Packit Service 97d2fb
	  && file_crc == debuglink_crc);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static bool
Packit Service 97d2fb
validate (Dwfl_Module *mod, int fd, bool check, GElf_Word debuglink_crc)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* For alt debug files always check the build-id from the Dwarf and alt.  */
Packit Service 97d2fb
  if (mod->dw != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      bool valid = false;
Packit Service 97d2fb
      const void *build_id;
Packit Service 97d2fb
      const char *altname;
Packit Service 97d2fb
      ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
Packit Service 97d2fb
								   &altname,
Packit Service 97d2fb
								   &build_id);
Packit Service 97d2fb
      if (build_id_len > 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* We need to open an Elf handle on the file so we can check its
Packit Service 97d2fb
	     build ID note for validation.  Backdoor the handle into the
Packit Service 97d2fb
	     module data structure since we had to open it early anyway.  */
Packit Service 97d2fb
	  Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
Packit Service 97d2fb
						false, false);
Packit Service 97d2fb
	  if (error != DWFL_E_NOERROR)
Packit Service 97d2fb
	    __libdwfl_seterrno (error);
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      const void *alt_build_id;
Packit Service 97d2fb
	      ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
Packit Service 97d2fb
								&alt_build_id);
Packit Service 97d2fb
	      if (alt_len > 0 && alt_len == build_id_len
Packit Service 97d2fb
		  && memcmp (build_id, alt_build_id, alt_len) == 0)
Packit Service 97d2fb
		valid = true;
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  /* A mismatch!  */
Packit Service 97d2fb
		  elf_end (mod->alt_elf);
Packit Service 97d2fb
		  mod->alt_elf = NULL;
Packit Service 97d2fb
		  close (fd);
Packit Service 97d2fb
		  fd = -1;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
      return valid;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* If we have a build ID, check only that.  */
Packit Service 97d2fb
  if (mod->build_id_len > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* We need to open an Elf handle on the file so we can check its
Packit Service 97d2fb
	 build ID note for validation.  Backdoor the handle into the
Packit Service 97d2fb
	 module data structure since we had to open it early anyway.  */
Packit Service 97d2fb
Packit Service 97d2fb
      mod->debug.valid = false;
Packit Service 97d2fb
      Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, false, false);
Packit Service 97d2fb
      if (error != DWFL_E_NOERROR)
Packit Service 97d2fb
	__libdwfl_seterrno (error);
Packit Service 97d2fb
      else if (likely (__libdwfl_find_build_id (mod, false,
Packit Service 97d2fb
						mod->debug.elf) == 2))
Packit Service 97d2fb
	/* Also backdoor the gratuitous flag.  */
Packit Service 97d2fb
	mod->debug.valid = true;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* A mismatch!  */
Packit Service 97d2fb
	  elf_end (mod->debug.elf);
Packit Service 97d2fb
	  mod->debug.elf = NULL;
Packit Service 97d2fb
	  close (fd);
Packit Service 97d2fb
	  fd = -1;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      return mod->debug.valid;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return !check || check_crc (fd, debuglink_crc);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
Packit Service 97d2fb
			const char *debuglink_file, GElf_Word debuglink_crc,
Packit Service 97d2fb
			char **debuginfo_file_name)
Packit Service 97d2fb
{
Packit Service 97d2fb
  bool cancheck = debuglink_crc != (GElf_Word) 0;
Packit Service 97d2fb
Packit Service 97d2fb
  const char *file_basename = file_name == NULL ? NULL : basename (file_name);
Packit Service 97d2fb
  char *localname = NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  /* We invent a debuglink .debug name if NULL, but then want to try the
Packit Service 97d2fb
     basename too.  */
Packit Service 97d2fb
  bool debuglink_null = debuglink_file == NULL;
Packit Service 97d2fb
  if (debuglink_null)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* For a alt debug multi file we need a name, for a separate debug
Packit Service 97d2fb
	 name we may be able to fall back on file_basename.debug.  */
Packit Service 97d2fb
      if (file_basename == NULL || mod->dw != NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  errno = 0;
Packit Service 97d2fb
	  return -1;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      size_t len = strlen (file_basename);
Packit Service 97d2fb
      localname = malloc (len + sizeof ".debug");
Packit Service 97d2fb
      if (unlikely (localname == NULL))
Packit Service 97d2fb
	return -1;
Packit Service 97d2fb
      memcpy (localname, file_basename, len);
Packit Service 97d2fb
      memcpy (&localname[len], ".debug", sizeof ".debug");
Packit Service 97d2fb
      debuglink_file = localname;
Packit Service 97d2fb
      cancheck = false;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Look for a file named DEBUGLINK_FILE in the directories
Packit Service 97d2fb
     indicated by the debug directory path setting.  */
Packit Service 97d2fb
Packit Service 97d2fb
  const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
Packit Service 97d2fb
  char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
Packit Service 97d2fb
			    ?: DEFAULT_DEBUGINFO_PATH);
Packit Service 97d2fb
  if (unlikely (localpath == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (localname);
Packit Service 97d2fb
      return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* A leading - or + in the whole path sets whether to check file CRCs.  */
Packit Service 97d2fb
  bool defcheck = true;
Packit Service 97d2fb
  char *path = localpath;
Packit Service 97d2fb
  if (path[0] == '-' || path[0] == '+')
Packit Service 97d2fb
    {
Packit Service 97d2fb
      defcheck = path[0] == '+';
Packit Service 97d2fb
      ++path;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* XXX dev/ino should be cached in struct dwfl_file.  */
Packit Service 97d2fb
  struct stat main_stat;
Packit Service 97d2fb
  if (unlikely ((mod->main.fd != -1 ? fstat (mod->main.fd, &main_stat)
Packit Service 97d2fb
		 : file_name != NULL ? stat (file_name, &main_stat)
Packit Service 97d2fb
		 : -1) < 0))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      main_stat.st_dev = 0;
Packit Service 97d2fb
      main_stat.st_ino = 0;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  char *file_dirname = (file_basename == file_name ? NULL
Packit Service 97d2fb
			: strndup (file_name, file_basename - 1 - file_name));
Packit Service 97d2fb
  if (file_basename != file_name && file_dirname == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (localpath);
Packit Service 97d2fb
      free (localname);
Packit Service 97d2fb
      return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  char *p;
Packit Service 97d2fb
  while ((p = strsep (&path, ":")) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* A leading - or + says whether to check file CRCs for this element.  */
Packit Service 97d2fb
      bool check = defcheck;
Packit Service 97d2fb
      if (*p == '+' || *p == '-')
Packit Service 97d2fb
	check = *p++ == '+';
Packit Service 97d2fb
      check = check && cancheck;
Packit Service 97d2fb
Packit Service 97d2fb
      /* Try the basename too, if we made up the debuglink name and this
Packit Service 97d2fb
	 is not the main directory.  */
Packit Service 97d2fb
      bool try_file_basename;
Packit Service 97d2fb
Packit Service 97d2fb
      const char *dir, *subdir, *file;
Packit Service 97d2fb
      switch (p[0])
Packit Service 97d2fb
	{
Packit Service 97d2fb
	case '\0':
Packit Service 97d2fb
	  /* An empty entry says to try the main file's directory.  */
Packit Service 97d2fb
	  dir = file_dirname;
Packit Service 97d2fb
	  subdir = NULL;
Packit Service 97d2fb
	  file = debuglink_file;
Packit Service 97d2fb
	  try_file_basename = false;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	case '/':
Packit Service 97d2fb
	  /* An absolute path says to look there for a subdirectory
Packit Service 97d2fb
	     named by the main file's absolute directory.  This cannot
Packit Service 97d2fb
	     be applied to a relative file name.  For alt debug files
Packit Service 97d2fb
	     it means to look for the basename file in that dir or the
Packit Service 97d2fb
	     .dwz subdir (see below).  */
Packit Service 97d2fb
	  if (mod->dw == NULL
Packit Service 97d2fb
	      && (file_dirname == NULL || file_dirname[0] != '/'))
Packit Service 97d2fb
	    continue;
Packit Service 97d2fb
	  dir = p;
Packit Service 97d2fb
	  if (mod->dw == NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      subdir = file_dirname;
Packit Service 97d2fb
	      /* We want to explore all sub-subdirs.  Chop off one slash
Packit Service 97d2fb
		 at a time.  */
Packit Service 97d2fb
	    explore_dir:
Packit Service 97d2fb
	      subdir = strchr (subdir, '/');
Packit Service 97d2fb
	      if (subdir != NULL)
Packit Service 97d2fb
		subdir = subdir + 1;
Packit Service 97d2fb
	      if (subdir && *subdir == 0)
Packit Service 97d2fb
		continue;
Packit Service 97d2fb
	      file = debuglink_file;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      subdir = NULL;
Packit Service 97d2fb
	      file = basename (debuglink_file);
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  try_file_basename = debuglink_null;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	default:
Packit Service 97d2fb
	  /* A relative path says to try a subdirectory of that name
Packit Service 97d2fb
	     in the main file's directory.  */
Packit Service 97d2fb
	  dir = file_dirname;
Packit Service 97d2fb
	  subdir = p;
Packit Service 97d2fb
	  file = debuglink_file;
Packit Service 97d2fb
	  try_file_basename = debuglink_null;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      char *fname = NULL;
Packit Service 97d2fb
      int fd = try_open (&main_stat, dir, subdir, file, &fname);
Packit Service 97d2fb
      if (fd < 0 && try_file_basename)
Packit Service 97d2fb
	fd = try_open (&main_stat, dir, subdir, file_basename, &fname);
Packit Service 97d2fb
      if (fd < 0)
Packit Service 97d2fb
	switch (errno)
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	  case ENOENT:
Packit Service 97d2fb
	  case ENOTDIR:
Packit Service 97d2fb
	    /* If we are looking for the alt file also try the .dwz subdir.
Packit Service 97d2fb
	       But only if this is the empty or absolute path.  */
Packit Service 97d2fb
	    if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
Packit Service 97d2fb
	      {
Packit Service 97d2fb
		fd = try_open (&main_stat, dir, ".dwz",
Packit Service 97d2fb
			       basename (file), &fname);
Packit Service 97d2fb
		if (fd < 0)
Packit Service 97d2fb
		  {
Packit Service 97d2fb
		    if (errno != ENOENT && errno != ENOTDIR)
Packit Service 97d2fb
		      goto fail_free;
Packit Service 97d2fb
		    else
Packit Service 97d2fb
		      continue;
Packit Service 97d2fb
		  }
Packit Service 97d2fb
		break;
Packit Service 97d2fb
	      }
Packit Service 97d2fb
	    /* If possible try again with a sub-subdir.  */
Packit Service 97d2fb
	    if (mod->dw == NULL && subdir)
Packit Service 97d2fb
	      goto explore_dir;
Packit Service 97d2fb
	    continue;
Packit Service 97d2fb
	  default:
Packit Service 97d2fb
	    goto fail_free;
Packit Service 97d2fb
	  }
Packit Service 97d2fb
      if (validate (mod, fd, check, debuglink_crc))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  free (localpath);
Packit Service 97d2fb
	  free (localname);
Packit Service 97d2fb
	  free (file_dirname);
Packit Service 97d2fb
	  *debuginfo_file_name = fname;
Packit Service 97d2fb
	  return fd;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      free (fname);
Packit Service 97d2fb
      close (fd);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* No dice.  */
Packit Service 97d2fb
  errno = 0;
Packit Service 97d2fb
fail_free:
Packit Service 97d2fb
  free (localpath);
Packit Service 97d2fb
  free (localname);
Packit Service 97d2fb
  free (file_dirname);
Packit Service 97d2fb
  return -1;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
dwfl_standard_find_debuginfo (Dwfl_Module *mod,
Packit Service 97d2fb
			      void **userdata __attribute__ ((unused)),
Packit Service 97d2fb
			      const char *modname __attribute__ ((unused)),
Packit Service 97d2fb
			      GElf_Addr base __attribute__ ((unused)),
Packit Service 97d2fb
			      const char *file_name,
Packit Service 97d2fb
			      const char *debuglink_file,
Packit Service 97d2fb
			      GElf_Word debuglink_crc,
Packit Service 97d2fb
			      char **debuginfo_file_name)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (mod == NULL)
Packit Service 97d2fb
    return -1;
Packit Service 97d2fb
Packit Service 97d2fb
  /* First try by build ID if we have one.  If that succeeds or fails
Packit Service 97d2fb
     other than just by finding nothing, that's all we do.  */
Packit Service 97d2fb
  const unsigned char *bits = NULL;
Packit Service 97d2fb
  GElf_Addr vaddr;
Packit Service 97d2fb
  int bits_len;
Packit Service 97d2fb
  if ((bits_len = INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr)) > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Dropping most arguments means we cannot rely on them in
Packit Service 97d2fb
	 dwfl_build_id_find_debuginfo.  But leave it that way since
Packit Service 97d2fb
	 some user code out there also does this, so we'll have to
Packit Service 97d2fb
	 handle it anyway.  */
Packit Service 97d2fb
      int fd = INTUSE(dwfl_build_id_find_debuginfo) (mod,
Packit Service 97d2fb
						     NULL, NULL, 0,
Packit Service 97d2fb
						     NULL, NULL, 0,
Packit Service 97d2fb
						     debuginfo_file_name);
Packit Service 97d2fb
Packit Service 97d2fb
      /* Did the build_id callback find something or report an error?
Packit Service 97d2fb
         Then we are done.  Otherwise fallback on path based search.  */
Packit Service 97d2fb
      if (fd >= 0
Packit Service 97d2fb
	  || (mod->dw == NULL && mod->debug.elf != NULL)
Packit Service 97d2fb
	  || (mod->dw != NULL && mod->alt_elf != NULL)
Packit Service 97d2fb
	  || errno != 0)
Packit Service 97d2fb
	return fd;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Failing that, search the path by name.  */
Packit Service 97d2fb
  int fd = find_debuginfo_in_path (mod, file_name,
Packit Service 97d2fb
				   debuglink_file, debuglink_crc,
Packit Service 97d2fb
				   debuginfo_file_name);
Packit Service 97d2fb
Packit Service 97d2fb
  if (fd < 0 && errno == 0 && file_name != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* If FILE_NAME is a symlink, the debug file might be associated
Packit Service 97d2fb
	 with the symlink target name instead.  */
Packit Service 97d2fb
Packit Service 97d2fb
      char *canon = realpath (file_name, NULL);
Packit Service 97d2fb
      if (canon != NULL && strcmp (file_name, canon))
Packit Service 97d2fb
	fd = find_debuginfo_in_path (mod, canon,
Packit Service 97d2fb
				     debuglink_file, debuglink_crc,
Packit Service 97d2fb
				     debuginfo_file_name);
Packit Service 97d2fb
      free (canon);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef ENABLE_LIBDEBUGINFOD
Packit Service 97d2fb
  /* Still nothing? Try if we can use the debuginfod client.
Packit Service 97d2fb
     But note that we might be looking for the alt file.
Packit Service 97d2fb
     We use the same trick as dwfl_build_id_find_debuginfo.
Packit Service 97d2fb
     If the debug file (dw) is already set, then we must be
Packit Service 97d2fb
     looking for the altfile. But we cannot use the actual
Packit Service 97d2fb
     file/path name given as hint. We'll have to lookup the
Packit Service 97d2fb
     alt file "build-id". Because the debuginfod client only
Packit Service 97d2fb
     handles build-ids.  */
Packit Service 97d2fb
  if (fd < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (mod->dw != NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  const char *altname;
Packit Service 97d2fb
	  bits_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, &altname,
Packit Service 97d2fb
							   (const void **)
Packit Service 97d2fb
							   &bits);
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      if (bits_len > 0)
Packit Service 97d2fb
	fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len);
Packit Service 97d2fb
    }
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
  return fd;
Packit Service 97d2fb
}
Packit Service 97d2fb
INTDEF (dwfl_standard_find_debuginfo)