1 /* Standard argp argument parsers for tools using libdwfl.
2 Copyright (C) 2005-2010 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
5 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.
9 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.
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,
16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
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.
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>. */
58 /* gettext helper macros. */
59 #define _(Str) dgettext ("elfutils", Str)
62 #define OPT_DEBUGINFO 0x100
63 #define OPT_COREFILE 0x101
65 static const struct argp_option options[] =
67 { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
68 { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
69 { "core", OPT_COREFILE, "COREFILE", 0,
70 N_("Find addresses from signatures found in COREFILE"), 0 },
71 { "pid", 'p', "PID", 0,
72 N_("Find addresses in files mapped into process PID"), 0 },
73 { "linux-process-map", 'M', "FILE", 0,
74 N_("Find addresses in files mapped as read from FILE"
75 " in Linux /proc/PID/maps format"), 0 },
76 { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
77 { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
78 N_("Kernel with all modules"), 0 },
79 { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
80 N_("Search path for separate debuginfo files"), 0 },
81 { NULL, 0, NULL, 0, NULL, 0 }
84 static char *debuginfo_path;
86 static const Dwfl_Callbacks offline_callbacks =
88 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
89 .debuginfo_path = &debuginfo_path,
91 .section_address = INTUSE(dwfl_offline_section_address),
93 /* We use this table for core files too. */
94 .find_elf = INTUSE(dwfl_build_id_find_elf),
97 static const Dwfl_Callbacks proc_callbacks =
99 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
100 .debuginfo_path = &debuginfo_path,
102 .find_elf = INTUSE(dwfl_linux_proc_find_elf),
105 static const Dwfl_Callbacks kernel_callbacks =
107 .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
108 .debuginfo_path = &debuginfo_path,
110 .find_elf = INTUSE(dwfl_linux_kernel_find_elf),
111 .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
115 parse_opt (int key, char *arg, struct argp_state *state)
117 inline void failure (Dwfl *dwfl, int errnum, const char *msg)
122 argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
123 msg, INTUSE(dwfl_errmsg) (-1));
125 argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
127 inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
129 failure (dwfl, errnum, msg);
130 return errnum == -1 ? EIO : errnum;
136 debuginfo_path = arg;
141 Dwfl *dwfl = state->hook;
144 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
146 return fail (dwfl, -1, arg);
149 /* Start at zero so if there is just one -e foo.so,
150 the DSO is shown without address bias. */
151 dwfl->offline_next_address = 0;
153 if (dwfl->callbacks == &offline_callbacks)
155 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
156 return fail (dwfl, -1, arg);
162 argp_error (state, "%s",
163 _("only one of -e, -p, -k, -K, or --core allowed"));
170 if (state->hook == NULL)
172 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
173 int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
175 return fail (dwfl, result, arg);
183 if (state->hook == NULL)
185 FILE *f = fopen (arg, "r");
190 argp_failure (state, EXIT_FAILURE, code,
191 "cannot open '%s'", arg);
194 Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
195 int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
198 return fail (dwfl, result, arg);
207 Dwfl *dwfl = state->hook;
209 state->hook = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
210 /* Permit -e and --core together. */
211 else if (dwfl->callbacks != &offline_callbacks)
214 int fd = open64 (arg, O_RDONLY);
219 Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
220 if (error != DWFL_E_NOERROR)
222 argp_failure (state, EXIT_FAILURE, 0,
223 _("cannot read ELF core file: %s"),
224 INTUSE(dwfl_errmsg) (error));
225 return error == DWFL_E_ERRNO ? errno : EIO;
228 int result = INTUSE(dwfl_core_file_report) (dwfl, core);
233 return fail (dwfl, result, arg);
236 /* From now we leak FD and CORE. */
240 argp_failure (state, EXIT_FAILURE, 0,
241 _("No modules recognized in core file"));
248 if (state->hook == NULL)
250 Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
251 int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
253 return fail (dwfl, result, _("cannot load kernel symbols"));
254 result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
256 /* Non-fatal to have no modules since we do have the kernel. */
257 failure (dwfl, result, _("cannot find kernel modules"));
265 if (state->hook == NULL)
267 Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
268 int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
271 return fail (dwfl, result, _("cannot find kernel or modules"));
278 case ARGP_KEY_SUCCESS:
280 Dwfl *dwfl = state->hook;
284 /* Default if no -e, -p, or -k, is "-e a.out". */
286 dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
287 if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
288 return fail (dwfl, -1, arg);
292 /* One of the three flavors has done dwfl_begin and some reporting
293 if we got here. Tie up the Dwfl and return it to the caller of
296 int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
297 assert (result == 0);
302 dwfl_end (state->hook);
307 return ARGP_ERR_UNKNOWN;
310 /* Update the input all along, so a parent parser can see it. */
311 *(Dwfl **) state->input = state->hook;
315 static const struct argp libdwfl_argp =
316 { .options = options, .parser = parse_opt };
319 dwfl_standard_argp (void)
321 return &libdwfl_argp;
325 /* In the absence of a mudflap wrapper for argp_parse, or a libc compiled
326 with -fmudflap, we'll see spurious errors for using the struct argp_state
327 on argp_parse's stack. */
329 void __attribute__ ((constructor))
330 __libdwfl_argp_mudflap_options (void)
332 __mf_set_options ("-heur-stack-bound");