1 /* Standard argp argument parsers for tools using libdwfl.
2 Copyright (C) 2005-2010 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
37 /* gettext helper macros. */
38 #define _(Str) dgettext ("elfutils", Str)
41 #define OPT_DEBUGINFO 0x100
42 #define OPT_COREFILE 0x101
44 static const struct argp_option options[] =
46 { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
47 { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
48 { "core", OPT_COREFILE, "COREFILE", 0,
49 N_("Find addresses from signatures found in COREFILE"), 0 },
50 { "pid", 'p', "PID", 0,
51 N_("Find addresses in files mapped into process PID"), 0 },
52 { "linux-process-map", 'M', "FILE", 0,
53 N_("Find addresses in files mapped as read from FILE"
54 " in Linux /proc/PID/maps format"), 0 },
55 { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
56 { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
57 N_("Kernel with all modules"), 0 },
58 { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
59 N_("Search path for separate debuginfo files"), 0 },
60 { NULL, 0, NULL, 0, NULL, 0 }
63 static char *debuginfo_path;
65 static const Dwfl_Callbacks offline_callbacks =
67 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
68 .debuginfo_path = &debuginfo_path,
70 .section_address = INTUSE(dwfl_offline_section_address),
72 /* We use this table for core files too. */
73 .find_elf = INTUSE(dwfl_build_id_find_elf),
76 static const Dwfl_Callbacks proc_callbacks =
78 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
79 .debuginfo_path = &debuginfo_path,
81 .find_elf = INTUSE(dwfl_linux_proc_find_elf),
84 static const Dwfl_Callbacks kernel_callbacks =
86 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
87 .debuginfo_path = &debuginfo_path,
89 .find_elf = INTUSE(dwfl_linux_kernel_find_elf),
90 .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
94 parse_opt (int key, char *arg, struct argp_state *state)
96 inline void failure (Dwfl *dwfl, int errnum, const char *msg)
101 argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
102 msg, INTUSE(dwfl_errmsg) (-1));
104 argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
106 inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
108 failure (dwfl, errnum, msg);
109 return errnum == -1 ? EIO : errnum;
115 debuginfo_path = arg;
120 Dwfl *dwfl = state->hook;
123 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
125 return fail (dwfl, -1, arg);
128 /* Start at zero so if there is just one -e foo.so,
129 the DSO is shown without address bias. */
130 dwfl->offline_next_address = 0;
132 if (dwfl->callbacks == &offline_callbacks)
134 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
135 return fail (dwfl, -1, arg);
141 argp_error (state, "%s",
142 _("only one of -e, -p, -k, -K, or --core allowed"));
149 if (state->hook == NULL)
151 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
152 int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
154 return fail (dwfl, result, arg);
162 if (state->hook == NULL)
164 FILE *f = fopen (arg, "r");
169 argp_failure (state, EXIT_FAILURE, code,
170 "cannot open '%s'", arg);
173 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
174 int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
177 return fail (dwfl, result, arg);
186 Dwfl *dwfl = state->hook;
188 state->hook = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
189 /* Permit -e and --core together. */
190 else if (dwfl->callbacks != &offline_callbacks)
193 int fd = open64 (arg, O_RDONLY);
198 Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
199 if (error != DWFL_E_NOERROR)
201 argp_failure (state, EXIT_FAILURE, 0,
202 _("cannot read ELF core file: %s"),
203 INTUSE(dwfl_errmsg) (error));
204 return error == DWFL_E_ERRNO ? errno : EIO;
207 int result = INTUSE(dwfl_core_file_report) (dwfl, core);
212 return fail (dwfl, result, arg);
215 /* From now we leak FD and CORE. */
219 argp_failure (state, EXIT_FAILURE, 0,
220 _("No modules recognized in core file"));
227 if (state->hook == NULL)
229 Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
230 int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
232 return fail (dwfl, result, _("cannot load kernel symbols"));
233 result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
235 /* Non-fatal to have no modules since we do have the kernel. */
236 failure (dwfl, result, _("cannot find kernel modules"));
244 if (state->hook == NULL)
246 Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
247 int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
250 return fail (dwfl, result, _("cannot find kernel or modules"));
257 case ARGP_KEY_SUCCESS:
259 Dwfl *dwfl = state->hook;
263 /* Default if no -e, -p, or -k, is "-e a.out". */
265 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
266 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
267 return fail (dwfl, -1, arg);
271 /* One of the three flavors has done dwfl_begin and some reporting
272 if we got here. Tie up the Dwfl and return it to the caller of
275 int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
276 assert (result == 0);
281 dwfl_end (state->hook);
286 return ARGP_ERR_UNKNOWN;
289 /* Update the input all along, so a parent parser can see it. */
290 *(Dwfl **) state->input = state->hook;
294 static const struct argp libdwfl_argp =
295 { .options = options, .parser = parse_opt };
298 dwfl_standard_argp (void)
300 return &libdwfl_argp;
304 /* In the absence of a mudflap wrapper for argp_parse, or a libc compiled
305 with -fmudflap, we'll see spurious errors for using the struct argp_state
306 on argp_parse's stack. */
308 void __attribute__ ((constructor))
309 __libdwfl_argp_mudflap_options (void)
311 __mf_set_options ("-heur-stack-bound");