blob: bec370a3ecebbf6716dfe1aae027f73e1bcab774 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Standard argp argument parsers for tools using libdwfl.
2 Copyright (C) 2005 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00003 This file is part of Red Hat elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004
Ulrich Drepper361df7d2006-04-04 21:38:57 +00005 Red Hat elfutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by the
7 Free Software Foundation; version 2 of the License.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Ulrich Drepper361df7d2006-04-04 21:38:57 +00009 Red Hat elfutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Red Hat elfutils; if not, write to the Free Software Foundation,
Ulrich Drepper1e9ef502006-04-04 22:29:06 +000016 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000017
18 In addition, as a special exception, Red Hat, Inc. gives You the
19 additional right to link the code of Red Hat elfutils with code licensed
20 under any Open Source Initiative certified open source license
21 (http://www.opensource.org/licenses/index.php) which requires the
22 distribution of source code with any binary distribution and to
23 distribute linked combinations of the two. Non-GPL Code permitted under
24 this exception must only link to the code of Red Hat elfutils through
25 those well defined interfaces identified in the file named EXCEPTION
26 found in the source code files (the "Approved Interfaces"). The files
27 of Non-GPL Code may instantiate templates or use macros or inline
28 functions from the Approved Interfaces without causing the resulting
29 work to be covered by the GNU General Public License. Only Red Hat,
30 Inc. may make changes or additions to the list of Approved Interfaces.
31 Red Hat's grant of this exception is conditioned upon your not adding
32 any new exceptions. If you wish to add a new Approved Interface or
33 exception, please contact Red Hat. You must obey the GNU General Public
34 License in all respects for all of the Red Hat elfutils code and other
35 code used in conjunction with Red Hat elfutils except the Non-GPL Code
36 covered by this exception. If you modify this file, you may extend this
37 exception to your version of the file, but you are not obligated to do
38 so. If you do not wish to provide this exception without modification,
39 you must delete this exception statement from your version and license
40 this file solely under the GPL without exception.
41
42 Red Hat elfutils is an included package of the Open Invention Network.
43 An included package of the Open Invention Network is a package for which
44 Open Invention Network licensees cross-license their patents. No patent
45 license is granted, either expressly or impliedly, by designation as an
46 included package. Should you wish to participate in the Open Invention
47 Network licensing program, please visit www.openinventionnetwork.com
48 <http://www.openinventionnetwork.com>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000049
50#include "libdwflP.h"
51#include <argp.h>
52#include <stdlib.h>
53#include <assert.h>
54#include <libintl.h>
55
56/* gettext helper macros. */
57#define _(Str) dgettext ("elfutils", Str)
58
59
60#define OPT_DEBUGINFO 0x100
61
62static const struct argp_option options[] =
63{
64 { NULL, 0, NULL, 0, N_("Input Selection:"), 0 },
65 { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
66 { "pid", 'p', "PID", 0,
67 N_("Find addresses in files mapped into process PID"), 0 },
Roland McGrath1656bc02005-12-23 01:49:50 +000068 { "linux-process-map", 'M', "FILE", 0,
69 N_("Find addresses in files mapped as read from FILE"
70 " in Linux /proc/PID/maps format"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000071 { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
Roland McGrathd17fac72005-08-23 08:20:21 +000072 { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
73 N_("Kernel with all modules"), 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000074 { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
75 N_("Search path for separate debuginfo files"), 0 },
76 { NULL, 0, NULL, 0, NULL, 0 }
77};
78
79static char *debuginfo_path;
80
Roland McGrathd17fac72005-08-23 08:20:21 +000081static const Dwfl_Callbacks offline_callbacks =
82 {
83 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
84 .debuginfo_path = &debuginfo_path,
85
86 .section_address = INTUSE(dwfl_offline_section_address),
87 };
88
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000089static const Dwfl_Callbacks proc_callbacks =
90 {
91 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
92 .debuginfo_path = &debuginfo_path,
93
94 .find_elf = INTUSE(dwfl_linux_proc_find_elf),
95 };
96
97static const Dwfl_Callbacks kernel_callbacks =
98 {
99 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
100 .debuginfo_path = &debuginfo_path,
101
102 .find_elf = INTUSE(dwfl_linux_kernel_find_elf),
103 .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
104 };
105
106static error_t
107parse_opt (int key, char *arg, struct argp_state *state)
108{
Roland McGrath1656bc02005-12-23 01:49:50 +0000109 inline void failure (Dwfl *dwfl, int errnum, const char *msg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000110 {
111 if (errnum == -1)
112 argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
113 msg, INTUSE(dwfl_errmsg) (-1));
114 else
115 argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
Roland McGrath1656bc02005-12-23 01:49:50 +0000116 if (dwfl != NULL)
117 dwfl_end (dwfl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000118 }
Roland McGrath1656bc02005-12-23 01:49:50 +0000119 inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000120 {
Roland McGrath1656bc02005-12-23 01:49:50 +0000121 failure (dwfl, errnum, msg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000122 return errnum == -1 ? EIO : errnum;
123 }
124
125 switch (key)
126 {
127 case OPT_DEBUGINFO:
128 debuginfo_path = arg;
129 break;
130
131 case 'e':
Roland McGrathd17fac72005-08-23 08:20:21 +0000132 {
133 Dwfl *dwfl = state->hook;
134 if (dwfl == NULL)
135 {
136 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
137 if (dwfl == NULL)
Roland McGrath1656bc02005-12-23 01:49:50 +0000138 return fail (dwfl, -1, arg);
Roland McGrathd17fac72005-08-23 08:20:21 +0000139 state->hook = dwfl;
140 }
141 if (dwfl->callbacks == &offline_callbacks)
142 {
143 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
Roland McGrath1656bc02005-12-23 01:49:50 +0000144 return fail (dwfl, -1, arg);
Roland McGrathd17fac72005-08-23 08:20:21 +0000145 state->hook = dwfl;
146 }
147 else
148 {
149 toomany:
150 argp_error (state,
151 "%s", _("only one of -e, -p, -k, or -K allowed"));
152 return EINVAL;
153 }
154 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000155 break;
156
157 case 'p':
158 if (state->hook == NULL)
159 {
160 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
161 int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
162 if (result != 0)
Roland McGrath1656bc02005-12-23 01:49:50 +0000163 return fail (dwfl, result, arg);
164 state->hook = dwfl;
165 }
166 else
167 goto toomany;
168 break;
169
170 case 'M':
171 if (state->hook == NULL)
172 {
173 FILE *f = fopen (arg, "r");
174 if (f == NULL)
175 {
176 int code = errno;
177 argp_failure (state, EXIT_FAILURE, code,
178 "cannot open '%s'", arg);
179 return code;
180 }
181 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
182 int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
183 fclose (f);
184 if (result != 0)
185 return fail (dwfl, result, arg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000186 state->hook = dwfl;
187 }
188 else
189 goto toomany;
190 break;
191
192 case 'k':
193 if (state->hook == NULL)
194 {
195 Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
196 int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
197 if (result != 0)
Roland McGrath1656bc02005-12-23 01:49:50 +0000198 return fail (dwfl, result, _("cannot load kernel symbols"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000199 result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
200 if (result != 0)
201 /* Non-fatal to have no modules since we do have the kernel. */
Roland McGrath1656bc02005-12-23 01:49:50 +0000202 failure (dwfl, result, _("cannot find kernel modules"));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000203 state->hook = dwfl;
204 }
205 else
206 goto toomany;
207 break;
208
Roland McGrathd17fac72005-08-23 08:20:21 +0000209 case 'K':
210 if (state->hook == NULL)
211 {
212 Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
213 int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
214 NULL);
215 if (result != 0)
Roland McGrath1656bc02005-12-23 01:49:50 +0000216 return fail (dwfl, result, _("cannot find kernel or modules"));
Roland McGrathd17fac72005-08-23 08:20:21 +0000217 state->hook = dwfl;
218 }
219 else
220 goto toomany;
221 break;
222
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000223 case ARGP_KEY_SUCCESS:
224 {
225 Dwfl *dwfl = state->hook;
226
227 if (dwfl == NULL)
228 {
229 /* Default if no -e, -p, or -k, is "-e a.out". */
230 arg = "a.out";
Roland McGrathd17fac72005-08-23 08:20:21 +0000231 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
232 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
Roland McGrath1656bc02005-12-23 01:49:50 +0000233 return fail (dwfl, -1, arg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000234 state->hook = dwfl;
235 }
236
237 /* One of the three flavors has done dwfl_begin and some reporting
238 if we got here. Tie up the Dwfl and return it to the caller of
239 argp_parse. */
240
241 int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
242 assert (result == 0);
243
244 *(Dwfl **) state->input = dwfl;
245 }
246 break;
247
248 default:
249 return ARGP_ERR_UNKNOWN;
250 }
251 return 0;
252}
253
254static const struct argp libdwfl_argp =
255 { .options = options, .parser = parse_opt };
256
257const struct argp *
258dwfl_standard_argp (void)
259{
260 return &libdwfl_argp;
261}
Roland McGrath80e43a72005-08-24 21:12:15 +0000262
263#ifdef _MUDFLAP
264/* In the absence of a mudflap wrapper for argp_parse, or a libc compiled
265 with -fmudflap, we'll see spurious errors for using the struct argp_state
266 on argp_parse's stack. */
267
268void __attribute__ ((constructor))
269__libdwfl_argp_mudflap_options (void)
270{
271 __mf_set_options ("-heur-stack-bound");
272}
273#endif