1da0c48c4Sopenharmony_ci/* Return build ID information for a module.
2da0c48c4Sopenharmony_ci   Copyright (C) 2007-2010, 2014 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of either
7da0c48c4Sopenharmony_ci
8da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
9da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
10da0c48c4Sopenharmony_ci       your option) any later version
11da0c48c4Sopenharmony_ci
12da0c48c4Sopenharmony_ci   or
13da0c48c4Sopenharmony_ci
14da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
15da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
16da0c48c4Sopenharmony_ci       your option) any later version
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci   or both in parallel, as here.
19da0c48c4Sopenharmony_ci
20da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
21da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23da0c48c4Sopenharmony_ci   General Public License for more details.
24da0c48c4Sopenharmony_ci
25da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
26da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
27da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
30da0c48c4Sopenharmony_ci# include <config.h>
31da0c48c4Sopenharmony_ci#endif
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci#include "libdwflP.h"
34da0c48c4Sopenharmony_ci
35da0c48c4Sopenharmony_cistatic int
36da0c48c4Sopenharmony_cifound_build_id (Dwfl_Module *mod, bool set,
37da0c48c4Sopenharmony_ci		const void *bits, int len, GElf_Addr vaddr)
38da0c48c4Sopenharmony_ci{
39da0c48c4Sopenharmony_ci  if (!set)
40da0c48c4Sopenharmony_ci    /* When checking bits, we do not compare VADDR because the
41da0c48c4Sopenharmony_ci       address found in a debuginfo file may not match the main
42da0c48c4Sopenharmony_ci       file as modified by prelink.  */
43da0c48c4Sopenharmony_ci    return 1 + (mod->build_id_len == len
44da0c48c4Sopenharmony_ci		&& !memcmp (bits, mod->build_id_bits, len));
45da0c48c4Sopenharmony_ci
46da0c48c4Sopenharmony_ci  void *copy = malloc (len);
47da0c48c4Sopenharmony_ci  if (unlikely (copy == NULL))
48da0c48c4Sopenharmony_ci    {
49da0c48c4Sopenharmony_ci      __libdwfl_seterrno (DWFL_E_NOMEM);
50da0c48c4Sopenharmony_ci      return -1;
51da0c48c4Sopenharmony_ci    }
52da0c48c4Sopenharmony_ci
53da0c48c4Sopenharmony_ci  mod->build_id_bits = memcpy (copy, bits, len);
54da0c48c4Sopenharmony_ci  mod->build_id_vaddr = vaddr;
55da0c48c4Sopenharmony_ci  mod->build_id_len = len;
56da0c48c4Sopenharmony_ci  return len;
57da0c48c4Sopenharmony_ci}
58da0c48c4Sopenharmony_ci
59da0c48c4Sopenharmony_ciint
60da0c48c4Sopenharmony_ciinternal_function
61da0c48c4Sopenharmony_ci__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
62da0c48c4Sopenharmony_ci{
63da0c48c4Sopenharmony_ci  const void *build_id_bits;
64da0c48c4Sopenharmony_ci  GElf_Addr build_id_elfaddr;
65da0c48c4Sopenharmony_ci  int build_id_len;
66da0c48c4Sopenharmony_ci
67da0c48c4Sopenharmony_ci  /* For mod == NULL use dwelf_elf_gnu_build_id directly.  */
68da0c48c4Sopenharmony_ci  assert (mod != NULL);
69da0c48c4Sopenharmony_ci
70da0c48c4Sopenharmony_ci  int result = __libdwfl_find_elf_build_id (mod, elf, &build_id_bits,
71da0c48c4Sopenharmony_ci					    &build_id_elfaddr, &build_id_len);
72da0c48c4Sopenharmony_ci  if (result <= 0)
73da0c48c4Sopenharmony_ci    return result;
74da0c48c4Sopenharmony_ci
75da0c48c4Sopenharmony_ci  GElf_Addr build_id_vaddr = build_id_elfaddr + (build_id_elfaddr != 0
76da0c48c4Sopenharmony_ci						 ? mod->main_bias : 0);
77da0c48c4Sopenharmony_ci  return found_build_id (mod, set, build_id_bits, build_id_len, build_id_vaddr);
78da0c48c4Sopenharmony_ci}
79da0c48c4Sopenharmony_ci
80da0c48c4Sopenharmony_ciNEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138)
81da0c48c4Sopenharmony_ciint
82da0c48c4Sopenharmony_cidwfl_module_build_id (Dwfl_Module *mod,
83da0c48c4Sopenharmony_ci		      const unsigned char **bits, GElf_Addr *vaddr)
84da0c48c4Sopenharmony_ci{
85da0c48c4Sopenharmony_ci  if (mod == NULL)
86da0c48c4Sopenharmony_ci    return -1;
87da0c48c4Sopenharmony_ci
88da0c48c4Sopenharmony_ci  if (mod->build_id_len == 0 && mod->main.elf != NULL)
89da0c48c4Sopenharmony_ci    {
90da0c48c4Sopenharmony_ci      /* We have the file, but have not examined it yet.  */
91da0c48c4Sopenharmony_ci      int result = __libdwfl_find_build_id (mod, true, mod->main.elf);
92da0c48c4Sopenharmony_ci      if (result <= 0)
93da0c48c4Sopenharmony_ci	{
94da0c48c4Sopenharmony_ci	  mod->build_id_len = -1;	/* Cache negative result.  */
95da0c48c4Sopenharmony_ci	  return result;
96da0c48c4Sopenharmony_ci	}
97da0c48c4Sopenharmony_ci    }
98da0c48c4Sopenharmony_ci
99da0c48c4Sopenharmony_ci  if (mod->build_id_len <= 0)
100da0c48c4Sopenharmony_ci    return 0;
101da0c48c4Sopenharmony_ci
102da0c48c4Sopenharmony_ci  *bits = mod->build_id_bits;
103da0c48c4Sopenharmony_ci  *vaddr = mod->build_id_vaddr;
104da0c48c4Sopenharmony_ci  return mod->build_id_len;
105da0c48c4Sopenharmony_ci}
106da0c48c4Sopenharmony_ciNEW_INTDEF (dwfl_module_build_id)
107da0c48c4Sopenharmony_ci
108da0c48c4Sopenharmony_ci#ifdef SYMBOL_VERSIONING
109da0c48c4Sopenharmony_ciCOMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end)
110da0c48c4Sopenharmony_ci
111da0c48c4Sopenharmony_ciint
112da0c48c4Sopenharmony_ci_compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod,
113da0c48c4Sopenharmony_ci					   const unsigned char **bits,
114da0c48c4Sopenharmony_ci					   GElf_Addr *vaddr)
115da0c48c4Sopenharmony_ci{
116da0c48c4Sopenharmony_ci  int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr);
117da0c48c4Sopenharmony_ci  if (result > 0)
118da0c48c4Sopenharmony_ci    *vaddr += (result + 3) & -4;
119da0c48c4Sopenharmony_ci  return result;
120da0c48c4Sopenharmony_ci}
121da0c48c4Sopenharmony_ci#endif
122