xref: /aosp_15_r20/external/elfutils/libdwfl/find-debuginfo.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Standard find_debuginfo callback for libdwfl.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2010, 2014, 2015, 2019 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
34*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
35*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
36*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
37*7304104dSAndroid Build Coastguard Worker #include "system.h"
38*7304104dSAndroid Build Coastguard Worker 
39*7304104dSAndroid Build Coastguard Worker 
40*7304104dSAndroid Build Coastguard Worker /* Try to open [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1.
41*7304104dSAndroid Build Coastguard Worker    On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file.  */
42*7304104dSAndroid Build Coastguard Worker static int
try_open(const struct stat * main_stat,const char * dir,const char * subdir,const char * debuglink,char ** debuginfo_file_name)43*7304104dSAndroid Build Coastguard Worker try_open (const struct stat *main_stat,
44*7304104dSAndroid Build Coastguard Worker 	  const char *dir, const char *subdir, const char *debuglink,
45*7304104dSAndroid Build Coastguard Worker 	  char **debuginfo_file_name)
46*7304104dSAndroid Build Coastguard Worker {
47*7304104dSAndroid Build Coastguard Worker   char *fname;
48*7304104dSAndroid Build Coastguard Worker   if (dir == NULL && subdir == NULL)
49*7304104dSAndroid Build Coastguard Worker     {
50*7304104dSAndroid Build Coastguard Worker       fname = strdup (debuglink);
51*7304104dSAndroid Build Coastguard Worker       if (unlikely (fname == NULL))
52*7304104dSAndroid Build Coastguard Worker 	return -1;
53*7304104dSAndroid Build Coastguard Worker     }
54*7304104dSAndroid Build Coastguard Worker   else if ((subdir == NULL ? asprintf (&fname, "%s/%s", dir, debuglink)
55*7304104dSAndroid Build Coastguard Worker 	    : dir == NULL ? asprintf (&fname, "%s/%s", subdir, debuglink)
56*7304104dSAndroid Build Coastguard Worker 	    : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0)
57*7304104dSAndroid Build Coastguard Worker     return -1;
58*7304104dSAndroid Build Coastguard Worker 
59*7304104dSAndroid Build Coastguard Worker   struct stat st;
60*7304104dSAndroid Build Coastguard Worker   int fd = TEMP_FAILURE_RETRY (open (fname, O_RDONLY));
61*7304104dSAndroid Build Coastguard Worker   if (fd < 0)
62*7304104dSAndroid Build Coastguard Worker     free (fname);
63*7304104dSAndroid Build Coastguard Worker   else if (fstat (fd, &st) == 0
64*7304104dSAndroid Build Coastguard Worker 	   && st.st_ino == main_stat->st_ino
65*7304104dSAndroid Build Coastguard Worker 	   && st.st_dev == main_stat->st_dev)
66*7304104dSAndroid Build Coastguard Worker     {
67*7304104dSAndroid Build Coastguard Worker       /* This is the main file by another name.  Don't look at it again.  */
68*7304104dSAndroid Build Coastguard Worker       free (fname);
69*7304104dSAndroid Build Coastguard Worker       close (fd);
70*7304104dSAndroid Build Coastguard Worker       errno = ENOENT;
71*7304104dSAndroid Build Coastguard Worker       fd = -1;
72*7304104dSAndroid Build Coastguard Worker     }
73*7304104dSAndroid Build Coastguard Worker   else
74*7304104dSAndroid Build Coastguard Worker     *debuginfo_file_name = fname;
75*7304104dSAndroid Build Coastguard Worker 
76*7304104dSAndroid Build Coastguard Worker   return fd;
77*7304104dSAndroid Build Coastguard Worker }
78*7304104dSAndroid Build Coastguard Worker 
79*7304104dSAndroid Build Coastguard Worker /* Return true iff the FD's contents CRC matches DEBUGLINK_CRC.  */
80*7304104dSAndroid Build Coastguard Worker static inline bool
check_crc(int fd,GElf_Word debuglink_crc)81*7304104dSAndroid Build Coastguard Worker check_crc (int fd, GElf_Word debuglink_crc)
82*7304104dSAndroid Build Coastguard Worker {
83*7304104dSAndroid Build Coastguard Worker   uint32_t file_crc;
84*7304104dSAndroid Build Coastguard Worker   return (__libdwfl_crc32_file (fd, &file_crc) == 0
85*7304104dSAndroid Build Coastguard Worker 	  && file_crc == debuglink_crc);
86*7304104dSAndroid Build Coastguard Worker }
87*7304104dSAndroid Build Coastguard Worker 
88*7304104dSAndroid Build Coastguard Worker static bool
validate(Dwfl_Module * mod,int fd,bool check,GElf_Word debuglink_crc)89*7304104dSAndroid Build Coastguard Worker validate (Dwfl_Module *mod, int fd, bool check, GElf_Word debuglink_crc)
90*7304104dSAndroid Build Coastguard Worker {
91*7304104dSAndroid Build Coastguard Worker   /* For alt debug files always check the build-id from the Dwarf and alt.  */
92*7304104dSAndroid Build Coastguard Worker   if (mod->dw != NULL)
93*7304104dSAndroid Build Coastguard Worker     {
94*7304104dSAndroid Build Coastguard Worker       bool valid = false;
95*7304104dSAndroid Build Coastguard Worker       const void *build_id;
96*7304104dSAndroid Build Coastguard Worker       const char *altname;
97*7304104dSAndroid Build Coastguard Worker       ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
98*7304104dSAndroid Build Coastguard Worker 								   &altname,
99*7304104dSAndroid Build Coastguard Worker 								   &build_id);
100*7304104dSAndroid Build Coastguard Worker       if (build_id_len > 0)
101*7304104dSAndroid Build Coastguard Worker 	{
102*7304104dSAndroid Build Coastguard Worker 	  /* We need to open an Elf handle on the file so we can check its
103*7304104dSAndroid Build Coastguard Worker 	     build ID note for validation.  Backdoor the handle into the
104*7304104dSAndroid Build Coastguard Worker 	     module data structure since we had to open it early anyway.  */
105*7304104dSAndroid Build Coastguard Worker 	  Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
106*7304104dSAndroid Build Coastguard Worker 						false, false);
107*7304104dSAndroid Build Coastguard Worker 	  if (error != DWFL_E_NOERROR)
108*7304104dSAndroid Build Coastguard Worker 	    __libdwfl_seterrno (error);
109*7304104dSAndroid Build Coastguard Worker 	  else
110*7304104dSAndroid Build Coastguard Worker 	    {
111*7304104dSAndroid Build Coastguard Worker 	      const void *alt_build_id;
112*7304104dSAndroid Build Coastguard Worker 	      ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
113*7304104dSAndroid Build Coastguard Worker 								&alt_build_id);
114*7304104dSAndroid Build Coastguard Worker 	      if (alt_len > 0 && alt_len == build_id_len
115*7304104dSAndroid Build Coastguard Worker 		  && memcmp (build_id, alt_build_id, alt_len) == 0)
116*7304104dSAndroid Build Coastguard Worker 		valid = true;
117*7304104dSAndroid Build Coastguard Worker 	      else
118*7304104dSAndroid Build Coastguard Worker 		{
119*7304104dSAndroid Build Coastguard Worker 		  /* A mismatch!  */
120*7304104dSAndroid Build Coastguard Worker 		  elf_end (mod->alt_elf);
121*7304104dSAndroid Build Coastguard Worker 		  mod->alt_elf = NULL;
122*7304104dSAndroid Build Coastguard Worker 		  close (fd);
123*7304104dSAndroid Build Coastguard Worker 		  fd = -1;
124*7304104dSAndroid Build Coastguard Worker 		}
125*7304104dSAndroid Build Coastguard Worker 	    }
126*7304104dSAndroid Build Coastguard Worker 	}
127*7304104dSAndroid Build Coastguard Worker       return valid;
128*7304104dSAndroid Build Coastguard Worker     }
129*7304104dSAndroid Build Coastguard Worker 
130*7304104dSAndroid Build Coastguard Worker   /* If we have a build ID, check only that.  */
131*7304104dSAndroid Build Coastguard Worker   if (mod->build_id_len > 0)
132*7304104dSAndroid Build Coastguard Worker     {
133*7304104dSAndroid Build Coastguard Worker       /* We need to open an Elf handle on the file so we can check its
134*7304104dSAndroid Build Coastguard Worker 	 build ID note for validation.  Backdoor the handle into the
135*7304104dSAndroid Build Coastguard Worker 	 module data structure since we had to open it early anyway.  */
136*7304104dSAndroid Build Coastguard Worker 
137*7304104dSAndroid Build Coastguard Worker       mod->debug.valid = false;
138*7304104dSAndroid Build Coastguard Worker       Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, false, false);
139*7304104dSAndroid Build Coastguard Worker       if (error != DWFL_E_NOERROR)
140*7304104dSAndroid Build Coastguard Worker 	__libdwfl_seterrno (error);
141*7304104dSAndroid Build Coastguard Worker       else if (likely (__libdwfl_find_build_id (mod, false,
142*7304104dSAndroid Build Coastguard Worker 						mod->debug.elf) == 2))
143*7304104dSAndroid Build Coastguard Worker 	/* Also backdoor the gratuitous flag.  */
144*7304104dSAndroid Build Coastguard Worker 	mod->debug.valid = true;
145*7304104dSAndroid Build Coastguard Worker       else
146*7304104dSAndroid Build Coastguard Worker 	{
147*7304104dSAndroid Build Coastguard Worker 	  /* A mismatch!  */
148*7304104dSAndroid Build Coastguard Worker 	  elf_end (mod->debug.elf);
149*7304104dSAndroid Build Coastguard Worker 	  mod->debug.elf = NULL;
150*7304104dSAndroid Build Coastguard Worker 	  close (fd);
151*7304104dSAndroid Build Coastguard Worker 	  fd = -1;
152*7304104dSAndroid Build Coastguard Worker 	}
153*7304104dSAndroid Build Coastguard Worker 
154*7304104dSAndroid Build Coastguard Worker       return mod->debug.valid;
155*7304104dSAndroid Build Coastguard Worker     }
156*7304104dSAndroid Build Coastguard Worker 
157*7304104dSAndroid Build Coastguard Worker   return !check || check_crc (fd, debuglink_crc);
158*7304104dSAndroid Build Coastguard Worker }
159*7304104dSAndroid Build Coastguard Worker 
160*7304104dSAndroid Build Coastguard Worker static int
find_debuginfo_in_path(Dwfl_Module * mod,const char * file_name,const char * debuglink_file,GElf_Word debuglink_crc,char ** debuginfo_file_name)161*7304104dSAndroid Build Coastguard Worker find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
162*7304104dSAndroid Build Coastguard Worker 			const char *debuglink_file, GElf_Word debuglink_crc,
163*7304104dSAndroid Build Coastguard Worker 			char **debuginfo_file_name)
164*7304104dSAndroid Build Coastguard Worker {
165*7304104dSAndroid Build Coastguard Worker   bool cancheck = debuglink_crc != (GElf_Word) 0;
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker   const char *file_basename = file_name == NULL ? NULL : xbasename (file_name);
168*7304104dSAndroid Build Coastguard Worker   char *localname = NULL;
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker   /* We invent a debuglink .debug name if NULL, but then want to try the
171*7304104dSAndroid Build Coastguard Worker      basename too.  */
172*7304104dSAndroid Build Coastguard Worker   bool debuglink_null = debuglink_file == NULL;
173*7304104dSAndroid Build Coastguard Worker   if (debuglink_null)
174*7304104dSAndroid Build Coastguard Worker     {
175*7304104dSAndroid Build Coastguard Worker       /* For a alt debug multi file we need a name, for a separate debug
176*7304104dSAndroid Build Coastguard Worker 	 name we may be able to fall back on file_basename.debug.  */
177*7304104dSAndroid Build Coastguard Worker       if (file_basename == NULL || mod->dw != NULL)
178*7304104dSAndroid Build Coastguard Worker 	{
179*7304104dSAndroid Build Coastguard Worker 	  errno = 0;
180*7304104dSAndroid Build Coastguard Worker 	  return -1;
181*7304104dSAndroid Build Coastguard Worker 	}
182*7304104dSAndroid Build Coastguard Worker 
183*7304104dSAndroid Build Coastguard Worker       size_t len = strlen (file_basename);
184*7304104dSAndroid Build Coastguard Worker       localname = malloc (len + sizeof ".debug");
185*7304104dSAndroid Build Coastguard Worker       if (unlikely (localname == NULL))
186*7304104dSAndroid Build Coastguard Worker 	return -1;
187*7304104dSAndroid Build Coastguard Worker       memcpy (localname, file_basename, len);
188*7304104dSAndroid Build Coastguard Worker       memcpy (&localname[len], ".debug", sizeof ".debug");
189*7304104dSAndroid Build Coastguard Worker       debuglink_file = localname;
190*7304104dSAndroid Build Coastguard Worker       cancheck = false;
191*7304104dSAndroid Build Coastguard Worker     }
192*7304104dSAndroid Build Coastguard Worker 
193*7304104dSAndroid Build Coastguard Worker   /* Look for a file named DEBUGLINK_FILE in the directories
194*7304104dSAndroid Build Coastguard Worker      indicated by the debug directory path setting.  */
195*7304104dSAndroid Build Coastguard Worker 
196*7304104dSAndroid Build Coastguard Worker   const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
197*7304104dSAndroid Build Coastguard Worker   char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
198*7304104dSAndroid Build Coastguard Worker 			    ?: DEFAULT_DEBUGINFO_PATH);
199*7304104dSAndroid Build Coastguard Worker   if (unlikely (localpath == NULL))
200*7304104dSAndroid Build Coastguard Worker     {
201*7304104dSAndroid Build Coastguard Worker       free (localname);
202*7304104dSAndroid Build Coastguard Worker       return -1;
203*7304104dSAndroid Build Coastguard Worker     }
204*7304104dSAndroid Build Coastguard Worker 
205*7304104dSAndroid Build Coastguard Worker   /* A leading - or + in the whole path sets whether to check file CRCs.  */
206*7304104dSAndroid Build Coastguard Worker   bool defcheck = true;
207*7304104dSAndroid Build Coastguard Worker   char *path = localpath;
208*7304104dSAndroid Build Coastguard Worker   if (path[0] == '-' || path[0] == '+')
209*7304104dSAndroid Build Coastguard Worker     {
210*7304104dSAndroid Build Coastguard Worker       defcheck = path[0] == '+';
211*7304104dSAndroid Build Coastguard Worker       ++path;
212*7304104dSAndroid Build Coastguard Worker     }
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker   /* XXX dev/ino should be cached in struct dwfl_file.  */
215*7304104dSAndroid Build Coastguard Worker   struct stat main_stat;
216*7304104dSAndroid Build Coastguard Worker   if (unlikely ((mod->main.fd != -1 ? fstat (mod->main.fd, &main_stat)
217*7304104dSAndroid Build Coastguard Worker 		 : file_name != NULL ? stat (file_name, &main_stat)
218*7304104dSAndroid Build Coastguard Worker 		 : -1) < 0))
219*7304104dSAndroid Build Coastguard Worker     {
220*7304104dSAndroid Build Coastguard Worker       main_stat.st_dev = 0;
221*7304104dSAndroid Build Coastguard Worker       main_stat.st_ino = 0;
222*7304104dSAndroid Build Coastguard Worker     }
223*7304104dSAndroid Build Coastguard Worker 
224*7304104dSAndroid Build Coastguard Worker   char *file_dirname = (file_basename == file_name ? NULL
225*7304104dSAndroid Build Coastguard Worker 			: strndup (file_name, file_basename - 1 - file_name));
226*7304104dSAndroid Build Coastguard Worker   if (file_basename != file_name && file_dirname == NULL)
227*7304104dSAndroid Build Coastguard Worker     {
228*7304104dSAndroid Build Coastguard Worker       free (localpath);
229*7304104dSAndroid Build Coastguard Worker       free (localname);
230*7304104dSAndroid Build Coastguard Worker       return -1;
231*7304104dSAndroid Build Coastguard Worker     }
232*7304104dSAndroid Build Coastguard Worker   char *p;
233*7304104dSAndroid Build Coastguard Worker   while ((p = strsep (&path, ":")) != NULL)
234*7304104dSAndroid Build Coastguard Worker     {
235*7304104dSAndroid Build Coastguard Worker       /* A leading - or + says whether to check file CRCs for this element.  */
236*7304104dSAndroid Build Coastguard Worker       bool check = defcheck;
237*7304104dSAndroid Build Coastguard Worker       if (*p == '+' || *p == '-')
238*7304104dSAndroid Build Coastguard Worker 	check = *p++ == '+';
239*7304104dSAndroid Build Coastguard Worker       check = check && cancheck;
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker       /* Try the basename too, if we made up the debuglink name and this
242*7304104dSAndroid Build Coastguard Worker 	 is not the main directory.  */
243*7304104dSAndroid Build Coastguard Worker       bool try_file_basename;
244*7304104dSAndroid Build Coastguard Worker 
245*7304104dSAndroid Build Coastguard Worker       const char *dir, *subdir, *file;
246*7304104dSAndroid Build Coastguard Worker       switch (p[0])
247*7304104dSAndroid Build Coastguard Worker 	{
248*7304104dSAndroid Build Coastguard Worker 	case '\0':
249*7304104dSAndroid Build Coastguard Worker 	  /* An empty entry says to try the main file's directory.  */
250*7304104dSAndroid Build Coastguard Worker 	  dir = file_dirname;
251*7304104dSAndroid Build Coastguard Worker 	  subdir = NULL;
252*7304104dSAndroid Build Coastguard Worker 	  file = debuglink_file;
253*7304104dSAndroid Build Coastguard Worker 	  try_file_basename = false;
254*7304104dSAndroid Build Coastguard Worker 	  break;
255*7304104dSAndroid Build Coastguard Worker 	case '/':
256*7304104dSAndroid Build Coastguard Worker 	  /* An absolute path says to look there for a subdirectory
257*7304104dSAndroid Build Coastguard Worker 	     named by the main file's absolute directory.  This cannot
258*7304104dSAndroid Build Coastguard Worker 	     be applied to a relative file name.  For alt debug files
259*7304104dSAndroid Build Coastguard Worker 	     it means to look for the basename file in that dir or the
260*7304104dSAndroid Build Coastguard Worker 	     .dwz subdir (see below).  */
261*7304104dSAndroid Build Coastguard Worker 	  if (mod->dw == NULL
262*7304104dSAndroid Build Coastguard Worker 	      && (file_dirname == NULL || file_dirname[0] != '/'))
263*7304104dSAndroid Build Coastguard Worker 	    continue;
264*7304104dSAndroid Build Coastguard Worker 	  dir = p;
265*7304104dSAndroid Build Coastguard Worker 	  if (mod->dw == NULL)
266*7304104dSAndroid Build Coastguard Worker 	    {
267*7304104dSAndroid Build Coastguard Worker 	      subdir = file_dirname;
268*7304104dSAndroid Build Coastguard Worker 	      /* We want to explore all sub-subdirs.  Chop off one slash
269*7304104dSAndroid Build Coastguard Worker 		 at a time.  */
270*7304104dSAndroid Build Coastguard Worker 	    explore_dir:
271*7304104dSAndroid Build Coastguard Worker 	      subdir = strchr (subdir, '/');
272*7304104dSAndroid Build Coastguard Worker 	      if (subdir != NULL)
273*7304104dSAndroid Build Coastguard Worker 		subdir = subdir + 1;
274*7304104dSAndroid Build Coastguard Worker 	      if (subdir && *subdir == 0)
275*7304104dSAndroid Build Coastguard Worker 		continue;
276*7304104dSAndroid Build Coastguard Worker 	      file = debuglink_file;
277*7304104dSAndroid Build Coastguard Worker 	    }
278*7304104dSAndroid Build Coastguard Worker 	  else
279*7304104dSAndroid Build Coastguard Worker 	    {
280*7304104dSAndroid Build Coastguard Worker 	      subdir = NULL;
281*7304104dSAndroid Build Coastguard Worker 	      file = xbasename (debuglink_file);
282*7304104dSAndroid Build Coastguard Worker 	    }
283*7304104dSAndroid Build Coastguard Worker 	  try_file_basename = debuglink_null;
284*7304104dSAndroid Build Coastguard Worker 	  break;
285*7304104dSAndroid Build Coastguard Worker 	default:
286*7304104dSAndroid Build Coastguard Worker 	  /* A relative path says to try a subdirectory of that name
287*7304104dSAndroid Build Coastguard Worker 	     in the main file's directory.  */
288*7304104dSAndroid Build Coastguard Worker 	  dir = file_dirname;
289*7304104dSAndroid Build Coastguard Worker 	  subdir = p;
290*7304104dSAndroid Build Coastguard Worker 	  file = debuglink_file;
291*7304104dSAndroid Build Coastguard Worker 	  try_file_basename = debuglink_null;
292*7304104dSAndroid Build Coastguard Worker 	  break;
293*7304104dSAndroid Build Coastguard Worker 	}
294*7304104dSAndroid Build Coastguard Worker 
295*7304104dSAndroid Build Coastguard Worker       char *fname = NULL;
296*7304104dSAndroid Build Coastguard Worker       int fd = try_open (&main_stat, dir, subdir, file, &fname);
297*7304104dSAndroid Build Coastguard Worker       if (fd < 0 && try_file_basename)
298*7304104dSAndroid Build Coastguard Worker 	fd = try_open (&main_stat, dir, subdir, file_basename, &fname);
299*7304104dSAndroid Build Coastguard Worker       if (fd < 0)
300*7304104dSAndroid Build Coastguard Worker 	switch (errno)
301*7304104dSAndroid Build Coastguard Worker 	  {
302*7304104dSAndroid Build Coastguard Worker 	  case ENOENT:
303*7304104dSAndroid Build Coastguard Worker 	  case ENOTDIR:
304*7304104dSAndroid Build Coastguard Worker 	    /* If we are looking for the alt file also try the .dwz subdir.
305*7304104dSAndroid Build Coastguard Worker 	       But only if this is the empty or absolute path.  */
306*7304104dSAndroid Build Coastguard Worker 	    if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
307*7304104dSAndroid Build Coastguard Worker 	      {
308*7304104dSAndroid Build Coastguard Worker 		fd = try_open (&main_stat, dir, ".dwz",
309*7304104dSAndroid Build Coastguard Worker 			       xbasename (file), &fname);
310*7304104dSAndroid Build Coastguard Worker 		if (fd < 0)
311*7304104dSAndroid Build Coastguard Worker 		  {
312*7304104dSAndroid Build Coastguard Worker 		    if (errno != ENOENT && errno != ENOTDIR)
313*7304104dSAndroid Build Coastguard Worker 		      goto fail_free;
314*7304104dSAndroid Build Coastguard Worker 		    else
315*7304104dSAndroid Build Coastguard Worker 		      continue;
316*7304104dSAndroid Build Coastguard Worker 		  }
317*7304104dSAndroid Build Coastguard Worker 		break;
318*7304104dSAndroid Build Coastguard Worker 	      }
319*7304104dSAndroid Build Coastguard Worker 	    /* If possible try again with a sub-subdir.  */
320*7304104dSAndroid Build Coastguard Worker 	    if (mod->dw == NULL && subdir)
321*7304104dSAndroid Build Coastguard Worker 	      goto explore_dir;
322*7304104dSAndroid Build Coastguard Worker 	    continue;
323*7304104dSAndroid Build Coastguard Worker 	  default:
324*7304104dSAndroid Build Coastguard Worker 	    goto fail_free;
325*7304104dSAndroid Build Coastguard Worker 	  }
326*7304104dSAndroid Build Coastguard Worker       if (validate (mod, fd, check, debuglink_crc))
327*7304104dSAndroid Build Coastguard Worker 	{
328*7304104dSAndroid Build Coastguard Worker 	  free (localpath);
329*7304104dSAndroid Build Coastguard Worker 	  free (localname);
330*7304104dSAndroid Build Coastguard Worker 	  free (file_dirname);
331*7304104dSAndroid Build Coastguard Worker 	  *debuginfo_file_name = fname;
332*7304104dSAndroid Build Coastguard Worker 	  return fd;
333*7304104dSAndroid Build Coastguard Worker 	}
334*7304104dSAndroid Build Coastguard Worker       free (fname);
335*7304104dSAndroid Build Coastguard Worker       close (fd);
336*7304104dSAndroid Build Coastguard Worker     }
337*7304104dSAndroid Build Coastguard Worker 
338*7304104dSAndroid Build Coastguard Worker   /* No dice.  */
339*7304104dSAndroid Build Coastguard Worker   errno = 0;
340*7304104dSAndroid Build Coastguard Worker fail_free:
341*7304104dSAndroid Build Coastguard Worker   free (localpath);
342*7304104dSAndroid Build Coastguard Worker   free (localname);
343*7304104dSAndroid Build Coastguard Worker   free (file_dirname);
344*7304104dSAndroid Build Coastguard Worker   return -1;
345*7304104dSAndroid Build Coastguard Worker }
346*7304104dSAndroid Build Coastguard Worker 
347*7304104dSAndroid Build Coastguard Worker int
dwfl_standard_find_debuginfo(Dwfl_Module * mod,void ** userdata,const char * modname,GElf_Addr base,const char * file_name,const char * debuglink_file,GElf_Word debuglink_crc,char ** debuginfo_file_name)348*7304104dSAndroid Build Coastguard Worker dwfl_standard_find_debuginfo (Dwfl_Module *mod,
349*7304104dSAndroid Build Coastguard Worker 			      void **userdata __attribute__ ((unused)),
350*7304104dSAndroid Build Coastguard Worker 			      const char *modname __attribute__ ((unused)),
351*7304104dSAndroid Build Coastguard Worker 			      GElf_Addr base __attribute__ ((unused)),
352*7304104dSAndroid Build Coastguard Worker 			      const char *file_name,
353*7304104dSAndroid Build Coastguard Worker 			      const char *debuglink_file,
354*7304104dSAndroid Build Coastguard Worker 			      GElf_Word debuglink_crc,
355*7304104dSAndroid Build Coastguard Worker 			      char **debuginfo_file_name)
356*7304104dSAndroid Build Coastguard Worker {
357*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
358*7304104dSAndroid Build Coastguard Worker     return -1;
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker   /* First try by build ID if we have one.  If that succeeds or fails
361*7304104dSAndroid Build Coastguard Worker      other than just by finding nothing, that's all we do.  */
362*7304104dSAndroid Build Coastguard Worker   const unsigned char *bits = NULL;
363*7304104dSAndroid Build Coastguard Worker   GElf_Addr vaddr;
364*7304104dSAndroid Build Coastguard Worker   int bits_len;
365*7304104dSAndroid Build Coastguard Worker   if ((bits_len = INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr)) > 0)
366*7304104dSAndroid Build Coastguard Worker     {
367*7304104dSAndroid Build Coastguard Worker       /* Dropping most arguments means we cannot rely on them in
368*7304104dSAndroid Build Coastguard Worker 	 dwfl_build_id_find_debuginfo.  But leave it that way since
369*7304104dSAndroid Build Coastguard Worker 	 some user code out there also does this, so we'll have to
370*7304104dSAndroid Build Coastguard Worker 	 handle it anyway.  */
371*7304104dSAndroid Build Coastguard Worker       int fd = INTUSE(dwfl_build_id_find_debuginfo) (mod,
372*7304104dSAndroid Build Coastguard Worker 						     NULL, NULL, 0,
373*7304104dSAndroid Build Coastguard Worker 						     NULL, NULL, 0,
374*7304104dSAndroid Build Coastguard Worker 						     debuginfo_file_name);
375*7304104dSAndroid Build Coastguard Worker 
376*7304104dSAndroid Build Coastguard Worker       /* Did the build_id callback find something or report an error?
377*7304104dSAndroid Build Coastguard Worker          Then we are done.  Otherwise fallback on path based search.  */
378*7304104dSAndroid Build Coastguard Worker       if (fd >= 0
379*7304104dSAndroid Build Coastguard Worker 	  || (mod->dw == NULL && mod->debug.elf != NULL)
380*7304104dSAndroid Build Coastguard Worker 	  || (mod->dw != NULL && mod->alt_elf != NULL)
381*7304104dSAndroid Build Coastguard Worker 	  || errno != 0)
382*7304104dSAndroid Build Coastguard Worker 	return fd;
383*7304104dSAndroid Build Coastguard Worker     }
384*7304104dSAndroid Build Coastguard Worker 
385*7304104dSAndroid Build Coastguard Worker   /* Failing that, search the path by name.  */
386*7304104dSAndroid Build Coastguard Worker   int fd = find_debuginfo_in_path (mod, file_name,
387*7304104dSAndroid Build Coastguard Worker 				   debuglink_file, debuglink_crc,
388*7304104dSAndroid Build Coastguard Worker 				   debuginfo_file_name);
389*7304104dSAndroid Build Coastguard Worker 
390*7304104dSAndroid Build Coastguard Worker   if (fd < 0 && errno == 0 && file_name != NULL)
391*7304104dSAndroid Build Coastguard Worker     {
392*7304104dSAndroid Build Coastguard Worker       /* If FILE_NAME is a symlink, the debug file might be associated
393*7304104dSAndroid Build Coastguard Worker 	 with the symlink target name instead.  */
394*7304104dSAndroid Build Coastguard Worker 
395*7304104dSAndroid Build Coastguard Worker       char *canon = realpath (file_name, NULL);
396*7304104dSAndroid Build Coastguard Worker       if (canon != NULL && strcmp (file_name, canon))
397*7304104dSAndroid Build Coastguard Worker 	fd = find_debuginfo_in_path (mod, canon,
398*7304104dSAndroid Build Coastguard Worker 				     debuglink_file, debuglink_crc,
399*7304104dSAndroid Build Coastguard Worker 				     debuginfo_file_name);
400*7304104dSAndroid Build Coastguard Worker       free (canon);
401*7304104dSAndroid Build Coastguard Worker     }
402*7304104dSAndroid Build Coastguard Worker 
403*7304104dSAndroid Build Coastguard Worker #ifdef ENABLE_LIBDEBUGINFOD
404*7304104dSAndroid Build Coastguard Worker   /* Still nothing? Try if we can use the debuginfod client.
405*7304104dSAndroid Build Coastguard Worker      But note that we might be looking for the alt file.
406*7304104dSAndroid Build Coastguard Worker      We use the same trick as dwfl_build_id_find_debuginfo.
407*7304104dSAndroid Build Coastguard Worker      If the debug file (dw) is already set, then we must be
408*7304104dSAndroid Build Coastguard Worker      looking for the altfile. But we cannot use the actual
409*7304104dSAndroid Build Coastguard Worker      file/path name given as hint. We'll have to lookup the
410*7304104dSAndroid Build Coastguard Worker      alt file "build-id". Because the debuginfod client only
411*7304104dSAndroid Build Coastguard Worker      handles build-ids.  */
412*7304104dSAndroid Build Coastguard Worker   if (fd < 0)
413*7304104dSAndroid Build Coastguard Worker     {
414*7304104dSAndroid Build Coastguard Worker       if (mod->dw != NULL)
415*7304104dSAndroid Build Coastguard Worker 	{
416*7304104dSAndroid Build Coastguard Worker 	  const char *altname;
417*7304104dSAndroid Build Coastguard Worker 	  bits_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, &altname,
418*7304104dSAndroid Build Coastguard Worker 							   (const void **)
419*7304104dSAndroid Build Coastguard Worker 							   &bits);
420*7304104dSAndroid Build Coastguard Worker 	}
421*7304104dSAndroid Build Coastguard Worker 
422*7304104dSAndroid Build Coastguard Worker       if (bits_len > 0)
423*7304104dSAndroid Build Coastguard Worker 	fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len);
424*7304104dSAndroid Build Coastguard Worker     }
425*7304104dSAndroid Build Coastguard Worker #endif
426*7304104dSAndroid Build Coastguard Worker 
427*7304104dSAndroid Build Coastguard Worker   return fd;
428*7304104dSAndroid Build Coastguard Worker }
429*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_standard_find_debuginfo)
430