1da0c48c4Sopenharmony_ci/* Try to get an ELF or debug file through the debuginfod.
2da0c48c4Sopenharmony_ci   Copyright (C) 2019 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4da0c48c4Sopenharmony_ci   This file is part of elfutils.
5da0c48c4Sopenharmony_ci
6da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
7da0c48c4Sopenharmony_ci   it under the terms of either
8da0c48c4Sopenharmony_ci
9da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
10da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
11da0c48c4Sopenharmony_ci       your option) any later version
12da0c48c4Sopenharmony_ci
13da0c48c4Sopenharmony_ci   or
14da0c48c4Sopenharmony_ci
15da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
16da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
17da0c48c4Sopenharmony_ci       your option) any later version
18da0c48c4Sopenharmony_ci
19da0c48c4Sopenharmony_ci   or both in parallel, as here.
20da0c48c4Sopenharmony_ci
21da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
22da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
23da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24da0c48c4Sopenharmony_ci   General Public License for more details.
25da0c48c4Sopenharmony_ci
26da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
27da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
28da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
29da0c48c4Sopenharmony_ci
30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
31da0c48c4Sopenharmony_ci# include <config.h>
32da0c48c4Sopenharmony_ci#endif
33da0c48c4Sopenharmony_ci
34da0c48c4Sopenharmony_ci#include "libdwflP.h"
35da0c48c4Sopenharmony_ci
36da0c48c4Sopenharmony_ci#ifdef ENABLE_LIBDEBUGINFOD
37da0c48c4Sopenharmony_ci
38da0c48c4Sopenharmony_ci#include <pthread.h>
39da0c48c4Sopenharmony_ci#include <dlfcn.h>
40da0c48c4Sopenharmony_ci
41da0c48c4Sopenharmony_cistatic __typeof__ (debuginfod_begin) *fp_debuginfod_begin;
42da0c48c4Sopenharmony_cistatic __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable;
43da0c48c4Sopenharmony_cistatic __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo;
44da0c48c4Sopenharmony_cistatic __typeof__ (debuginfod_end) *fp_debuginfod_end;
45da0c48c4Sopenharmony_ci
46da0c48c4Sopenharmony_cistatic void __libdwfl_debuginfod_init (void);
47da0c48c4Sopenharmony_ci
48da0c48c4Sopenharmony_cistatic pthread_once_t init_control = PTHREAD_ONCE_INIT;
49da0c48c4Sopenharmony_ci
50da0c48c4Sopenharmony_ci/* NB: this is slightly thread-unsafe */
51da0c48c4Sopenharmony_ci
52da0c48c4Sopenharmony_cidebuginfod_client *
53da0c48c4Sopenharmony_cidwfl_get_debuginfod_client (Dwfl *dwfl)
54da0c48c4Sopenharmony_ci{
55da0c48c4Sopenharmony_ci  if (dwfl->debuginfod != NULL)
56da0c48c4Sopenharmony_ci    return dwfl->debuginfod;
57da0c48c4Sopenharmony_ci
58da0c48c4Sopenharmony_ci  pthread_once (&init_control, __libdwfl_debuginfod_init);
59da0c48c4Sopenharmony_ci
60da0c48c4Sopenharmony_ci  if (fp_debuginfod_begin != NULL)
61da0c48c4Sopenharmony_ci    {
62da0c48c4Sopenharmony_ci      dwfl->debuginfod = (*fp_debuginfod_begin) ();
63da0c48c4Sopenharmony_ci      return dwfl->debuginfod;
64da0c48c4Sopenharmony_ci    }
65da0c48c4Sopenharmony_ci
66da0c48c4Sopenharmony_ci  return NULL;
67da0c48c4Sopenharmony_ci}
68da0c48c4Sopenharmony_ciINTDEF(dwfl_get_debuginfod_client)
69da0c48c4Sopenharmony_ci
70da0c48c4Sopenharmony_ciint
71da0c48c4Sopenharmony_ci__libdwfl_debuginfod_find_executable (Dwfl *dwfl,
72da0c48c4Sopenharmony_ci				      const unsigned char *build_id_bits,
73da0c48c4Sopenharmony_ci				      size_t build_id_len)
74da0c48c4Sopenharmony_ci{
75da0c48c4Sopenharmony_ci  int fd = -1;
76da0c48c4Sopenharmony_ci  if (build_id_len > 0)
77da0c48c4Sopenharmony_ci    {
78da0c48c4Sopenharmony_ci      debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
79da0c48c4Sopenharmony_ci      if (c != NULL)
80da0c48c4Sopenharmony_ci	fd = (*fp_debuginfod_find_executable) (c, build_id_bits,
81da0c48c4Sopenharmony_ci					       build_id_len, NULL);
82da0c48c4Sopenharmony_ci    }
83da0c48c4Sopenharmony_ci
84da0c48c4Sopenharmony_ci  return fd;
85da0c48c4Sopenharmony_ci}
86da0c48c4Sopenharmony_ci
87da0c48c4Sopenharmony_ciint
88da0c48c4Sopenharmony_ci__libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
89da0c48c4Sopenharmony_ci				     const unsigned char *build_id_bits,
90da0c48c4Sopenharmony_ci				     size_t build_id_len)
91da0c48c4Sopenharmony_ci{
92da0c48c4Sopenharmony_ci  int fd = -1;
93da0c48c4Sopenharmony_ci  if (build_id_len > 0)
94da0c48c4Sopenharmony_ci    {
95da0c48c4Sopenharmony_ci      debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
96da0c48c4Sopenharmony_ci      if (c != NULL)
97da0c48c4Sopenharmony_ci	fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits,
98da0c48c4Sopenharmony_ci					      build_id_len, NULL);
99da0c48c4Sopenharmony_ci    }
100da0c48c4Sopenharmony_ci
101da0c48c4Sopenharmony_ci  return fd;
102da0c48c4Sopenharmony_ci}
103da0c48c4Sopenharmony_ci
104da0c48c4Sopenharmony_civoid
105da0c48c4Sopenharmony_ci__libdwfl_debuginfod_end (debuginfod_client *c)
106da0c48c4Sopenharmony_ci{
107da0c48c4Sopenharmony_ci  if (c != NULL)
108da0c48c4Sopenharmony_ci    (*fp_debuginfod_end) (c);
109da0c48c4Sopenharmony_ci}
110da0c48c4Sopenharmony_ci
111da0c48c4Sopenharmony_ci/* Try to get the libdebuginfod library functions.
112da0c48c4Sopenharmony_ci   Only needs to be called once from dwfl_get_debuginfod_client.  */
113da0c48c4Sopenharmony_cistatic void
114da0c48c4Sopenharmony_ci__libdwfl_debuginfod_init (void)
115da0c48c4Sopenharmony_ci{
116da0c48c4Sopenharmony_ci  void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY);
117da0c48c4Sopenharmony_ci
118da0c48c4Sopenharmony_ci  if (debuginfod_so != NULL)
119da0c48c4Sopenharmony_ci    {
120da0c48c4Sopenharmony_ci      fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin");
121da0c48c4Sopenharmony_ci      fp_debuginfod_find_executable = dlsym (debuginfod_so,
122da0c48c4Sopenharmony_ci					     "debuginfod_find_executable");
123da0c48c4Sopenharmony_ci      fp_debuginfod_find_debuginfo = dlsym (debuginfod_so,
124da0c48c4Sopenharmony_ci					    "debuginfod_find_debuginfo");
125da0c48c4Sopenharmony_ci      fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end");
126da0c48c4Sopenharmony_ci
127da0c48c4Sopenharmony_ci      /* We either get them all, or we get none.  */
128da0c48c4Sopenharmony_ci      if (fp_debuginfod_begin == NULL
129da0c48c4Sopenharmony_ci	  || fp_debuginfod_find_executable == NULL
130da0c48c4Sopenharmony_ci	  || fp_debuginfod_find_debuginfo == NULL
131da0c48c4Sopenharmony_ci	  || fp_debuginfod_end == NULL)
132da0c48c4Sopenharmony_ci	{
133da0c48c4Sopenharmony_ci	  fp_debuginfod_begin = NULL;
134da0c48c4Sopenharmony_ci	  fp_debuginfod_find_executable = NULL;
135da0c48c4Sopenharmony_ci	  fp_debuginfod_find_debuginfo = NULL;
136da0c48c4Sopenharmony_ci	  fp_debuginfod_end = NULL;
137da0c48c4Sopenharmony_ci	  dlclose (debuginfod_so);
138da0c48c4Sopenharmony_ci	}
139da0c48c4Sopenharmony_ci    }
140da0c48c4Sopenharmony_ci}
141da0c48c4Sopenharmony_ci
142da0c48c4Sopenharmony_ci#else // ENABLE_LIBDEBUGINFOD
143da0c48c4Sopenharmony_ci
144da0c48c4Sopenharmony_cidebuginfod_client *
145da0c48c4Sopenharmony_cidwfl_get_debuginfod_client (Dwfl *dummy __attribute__ ((unused)))
146da0c48c4Sopenharmony_ci{
147da0c48c4Sopenharmony_ci  return NULL;
148da0c48c4Sopenharmony_ci}
149da0c48c4Sopenharmony_ci
150da0c48c4Sopenharmony_ci#endif // ENABLE_LIBDEBUGINFOD
151