• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Command-line frontend for retrieving ELF / DWARF / source files
2    from the debuginfod.
3    Copyright (C) 2019 Red Hat, Inc.
4    This file is part of elfutils.
5 
6    This file 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    elfutils is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should have received copies of the GNU General Public License and
17    the GNU Lesser General Public License along with this program.  If
18    not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "printversion.h"
22 #include "debuginfod.h"
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <argp.h>
28 
29 
30 /* Name and version of program.  */
31 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
32 
33 /* Bug report address.  */
34 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
35 
36 /* Short description of program.  */
37 static const char doc[] = N_("Request debuginfo-related content "
38                              "from debuginfods listed in $" DEBUGINFOD_URLS_ENV_VAR ".");
39 
40 /* Strings for arguments in help texts.  */
41 static const char args_doc[] = N_("debuginfo BUILDID\n"
42                                   "executable BUILDID\n"
43                                   "source BUILDID /FILENAME");
44 
45 /* Definitions of arguments for argp functions.  */
46 static const struct argp_option options[] =
47   {
48    { "verbose", 'v', NULL, 0, "Increase verbosity.", 0 },
49    { NULL, 0, NULL, 0, NULL, 0 }
50   };
51 
52 /* debuginfod connection handle.  */
53 static debuginfod_client *client;
54 
progressfn(debuginfod_client * c,long a,long b)55 int progressfn(debuginfod_client *c __attribute__((__unused__)),
56 	       long a, long b)
57 {
58   fprintf (stderr, "Progress %ld / %ld\n", a, b);
59   return 0;
60 }
61 
62 
parse_opt(int key,char * arg,struct argp_state * state)63 static error_t parse_opt (int key, char *arg, struct argp_state *state)
64 {
65   (void) arg;
66   (void) state;
67   switch (key)
68     {
69     case 'v': debuginfod_set_progressfn (client, & progressfn); break;
70     default: return ARGP_ERR_UNKNOWN;
71     }
72   return 0;
73 }
74 
75 
76 /* Data structure to communicate with argp functions.  */
77 static struct argp argp =
78   {
79    options, parse_opt, args_doc, doc, NULL, NULL, NULL
80   };
81 
82 
83 
84 int
main(int argc,char ** argv)85 main(int argc, char** argv)
86 {
87   client = debuginfod_begin ();
88   if (client == NULL)
89     {
90       fprintf(stderr, "Couldn't create debuginfod client context\n");
91       return 1;
92     }
93 
94   int remaining;
95   (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
96 
97   if (argc < 2 || remaining+1 == argc) /* no arguments or at least two non-option words */
98     {
99       argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
100       return 1;
101     }
102 
103   int rc;
104   char *cache_name;
105 
106   /* Check whether FILETYPE is valid and call the appropriate
107      debuginfod_find_* function. If FILETYPE is "source"
108      then ensure a FILENAME was also supplied as an argument.  */
109   if (strcmp(argv[remaining], "debuginfo") == 0)
110     rc = debuginfod_find_debuginfo(client,
111 				   (unsigned char *)argv[remaining+1], 0,
112 				   &cache_name);
113   else if (strcmp(argv[remaining], "executable") == 0)
114     rc = debuginfod_find_executable(client,
115 				    (unsigned char *)argv[remaining+1], 0,
116 				    &cache_name);
117   else if (strcmp(argv[remaining], "source") == 0)
118     {
119       if (remaining+2 == argc || argv[3][0] != '/')
120         {
121           fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
122           return 1;
123         }
124       rc = debuginfod_find_source(client, (unsigned char *)argv[remaining+1],
125 				  0, argv[remaining+2], &cache_name);
126     }
127   else
128     {
129       argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
130       return 1;
131     }
132 
133   if (rc < 0)
134     {
135       fprintf(stderr, "Server query failed: %s\n", strerror(-rc));
136       return 1;
137     }
138 
139   printf("%s\n", cache_name);
140 
141   free (cache_name);
142   debuginfod_end (client);
143 
144   return 0;
145 }
146