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