Blame libdwfl/dwfl_module_build_id.c

Packit 032894
/* Return build ID information for a module.
Packit 032894
   Copyright (C) 2007-2010, 2014 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include "libdwflP.h"
Packit 032894
Packit 032894
static int
Packit 032894
found_build_id (Dwfl_Module *mod, bool set,
Packit 032894
		const void *bits, int len, GElf_Addr vaddr)
Packit 032894
{
Packit 032894
  if (!set)
Packit 032894
    /* When checking bits, we do not compare VADDR because the
Packit 032894
       address found in a debuginfo file may not match the main
Packit 032894
       file as modified by prelink.  */
Packit 032894
    return 1 + (mod->build_id_len == len
Packit 032894
		&& !memcmp (bits, mod->build_id_bits, len));
Packit 032894
Packit 032894
  void *copy = malloc (len);
Packit 032894
  if (unlikely (copy == NULL))
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_NOMEM);
Packit 032894
      return -1;
Packit 032894
    }
Packit 032894
Packit 032894
  mod->build_id_bits = memcpy (copy, bits, len);
Packit 032894
  mod->build_id_vaddr = vaddr;
Packit 032894
  mod->build_id_len = len;
Packit 032894
  return len;
Packit 032894
}
Packit 032894
Packit 032894
int
Packit 032894
internal_function
Packit 032894
__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
Packit 032894
{
Packit 032894
  const void *build_id_bits;
Packit 032894
  GElf_Addr build_id_elfaddr;
Packit 032894
  int build_id_len;
Packit 032894
Packit 032894
  /* For mod == NULL use dwelf_elf_gnu_build_id directly.  */
Packit 032894
  assert (mod != NULL);
Packit 032894
Packit 032894
  int result = __libdwfl_find_elf_build_id (mod, elf, &build_id_bits,
Packit 032894
					    &build_id_elfaddr, &build_id_len);
Packit 032894
  if (result <= 0)
Packit 032894
    return result;
Packit 032894
Packit 032894
  GElf_Addr build_id_vaddr = build_id_elfaddr + (build_id_elfaddr != 0
Packit 032894
						 ? mod->main_bias : 0);
Packit 032894
  return found_build_id (mod, set, build_id_bits, build_id_len, build_id_vaddr);
Packit 032894
}
Packit 032894
Packit 032894
int
Packit 032894
dwfl_module_build_id (Dwfl_Module *mod,
Packit 032894
		      const unsigned char **bits, GElf_Addr *vaddr)
Packit 032894
{
Packit 032894
  if (mod == NULL)
Packit 032894
    return -1;
Packit 032894
Packit 032894
  if (mod->build_id_len == 0 && mod->main.elf != NULL)
Packit 032894
    {
Packit 032894
      /* We have the file, but have not examined it yet.  */
Packit 032894
      int result = __libdwfl_find_build_id (mod, true, mod->main.elf);
Packit 032894
      if (result <= 0)
Packit 032894
	{
Packit 032894
	  mod->build_id_len = -1;	/* Cache negative result.  */
Packit 032894
	  return result;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  if (mod->build_id_len <= 0)
Packit 032894
    return 0;
Packit 032894
Packit 032894
  *bits = mod->build_id_bits;
Packit 032894
  *vaddr = mod->build_id_vaddr;
Packit 032894
  return mod->build_id_len;
Packit 032894
}
Packit 032894
INTDEF (dwfl_module_build_id)
Packit 032894
NEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138)
Packit 032894
Packit 032894
#ifdef SYMBOL_VERSIONING
Packit 032894
COMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end)
Packit 032894
Packit 032894
int
Packit 032894
_compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod,
Packit 032894
					   const unsigned char **bits,
Packit 032894
					   GElf_Addr *vaddr)
Packit 032894
{
Packit 032894
  int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr);
Packit 032894
  if (result > 0)
Packit 032894
    *vaddr += (result + 3) & -4;
Packit 032894
  return result;
Packit 032894
}
Packit 032894
#endif