1 /* debuginfod utilities for GDB. 2 Copyright (C) 2020 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #include "defs.h" 20 #include <errno.h> 21 #include "cli/cli-style.h" 22 #include "gdbsupport/scoped_fd.h" 23 #include "debuginfod-support.h" 24 25 #ifndef HAVE_LIBDEBUGINFOD 26 scoped_fd 27 debuginfod_source_query (const unsigned char *build_id, 28 int build_id_len, 29 const char *srcpath, 30 gdb::unique_xmalloc_ptr<char> *destname) 31 { 32 return scoped_fd (-ENOSYS); 33 } 34 35 scoped_fd 36 debuginfod_debuginfo_query (const unsigned char *build_id, 37 int build_id_len, 38 const char *filename, 39 gdb::unique_xmalloc_ptr<char> *destname) 40 { 41 return scoped_fd (-ENOSYS); 42 } 43 #else 44 #include <elfutils/debuginfod.h> 45 46 struct user_data 47 { 48 user_data (const char *desc, const char *fname) 49 : desc (desc), fname (fname), has_printed (false) 50 { } 51 52 const char * const desc; 53 const char * const fname; 54 bool has_printed; 55 }; 56 57 static int 58 progressfn (debuginfod_client *c, long cur, long total) 59 { 60 user_data *data = static_cast<user_data *> (debuginfod_get_user_data (c)); 61 62 if (check_quit_flag ()) 63 { 64 printf_filtered ("Cancelling download of %s %ps...\n", 65 data->desc, 66 styled_string (file_name_style.style (), data->fname)); 67 return 1; 68 } 69 70 if (!data->has_printed && total != 0) 71 { 72 /* Print this message only once. */ 73 data->has_printed = true; 74 printf_filtered ("Downloading %s %ps...\n", 75 data->desc, 76 styled_string (file_name_style.style (), data->fname)); 77 } 78 79 return 0; 80 } 81 82 static debuginfod_client * 83 debuginfod_init () 84 { 85 debuginfod_client *c = debuginfod_begin (); 86 87 if (c != nullptr) 88 debuginfod_set_progressfn (c, progressfn); 89 90 return c; 91 } 92 93 /* See debuginfod-support.h */ 94 95 scoped_fd 96 debuginfod_source_query (const unsigned char *build_id, 97 int build_id_len, 98 const char *srcpath, 99 gdb::unique_xmalloc_ptr<char> *destname) 100 { 101 if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL) 102 return scoped_fd (-ENOSYS); 103 104 debuginfod_client *c = debuginfod_init (); 105 106 if (c == nullptr) 107 return scoped_fd (-ENOMEM); 108 109 user_data data ("source file", srcpath); 110 111 debuginfod_set_user_data (c, &data); 112 scoped_fd fd (debuginfod_find_source (c, 113 build_id, 114 build_id_len, 115 srcpath, 116 nullptr)); 117 118 /* TODO: Add 'set debug debuginfod' command to control when error messages are shown. */ 119 if (fd.get () < 0 && fd.get () != -ENOENT) 120 printf_filtered (_("Download failed: %s. Continuing without source file %ps.\n"), 121 safe_strerror (-fd.get ()), 122 styled_string (file_name_style.style (), srcpath)); 123 else 124 destname->reset (xstrdup (srcpath)); 125 126 debuginfod_end (c); 127 return fd; 128 } 129 130 /* See debuginfod-support.h */ 131 132 scoped_fd 133 debuginfod_debuginfo_query (const unsigned char *build_id, 134 int build_id_len, 135 const char *filename, 136 gdb::unique_xmalloc_ptr<char> *destname) 137 { 138 if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL) 139 return scoped_fd (-ENOSYS); 140 141 debuginfod_client *c = debuginfod_init (); 142 143 if (c == nullptr) 144 return scoped_fd (-ENOMEM); 145 146 char *dname = nullptr; 147 user_data data ("separate debug info for", filename); 148 149 debuginfod_set_user_data (c, &data); 150 scoped_fd fd (debuginfod_find_debuginfo (c, build_id, build_id_len, &dname)); 151 152 if (fd.get () < 0 && fd.get () != -ENOENT) 153 printf_filtered (_("Download failed: %s. Continuing without debug info for %ps.\n"), 154 safe_strerror (-fd.get ()), 155 styled_string (file_name_style.style (), filename)); 156 157 destname->reset (dname); 158 debuginfod_end (c); 159 return fd; 160 } 161 #endif 162