1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Standard argp argument parsers for tools using libdwfl.
2355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard   Copyright (C) 2005-2010, 2012, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
7b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libdwflP.h"
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
34b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath#include <fcntl.h>
35b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath#include <unistd.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* gettext helper macros.  */
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define _(Str) dgettext ("elfutils", Str)
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
41b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath#define OPT_DEBUGINFO	0x100
42b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath#define OPT_COREFILE	0x101
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
464be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
48b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath  { "core", OPT_COREFILE, "COREFILE", 0,
49b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    N_("Find addresses from signatures found in COREFILE"), 0 },
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "pid", 'p', "PID", 0,
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Find addresses in files mapped into process PID"), 0 },
521656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath  { "linux-process-map", 'M', "FILE", 0,
531656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath    N_("Find addresses in files mapped as read from FILE"
541656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath       " in Linux /proc/PID/maps format"), 0 },
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
56d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
57d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    N_("Kernel with all modules"), 0 },
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Search path for separate debuginfo files"), 0 },
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic char *debuginfo_path;
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
65d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathstatic const Dwfl_Callbacks offline_callbacks =
66d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  {
67d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
68d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    .debuginfo_path = &debuginfo_path,
69d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
70d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    .section_address = INTUSE(dwfl_offline_section_address),
71b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath
72b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    /* We use this table for core files too.  */
73c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil    .find_elf = INTUSE(dwfl_build_id_find_elf),
74d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  };
75d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const Dwfl_Callbacks proc_callbacks =
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .debuginfo_path = &debuginfo_path,
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .find_elf = INTUSE(dwfl_linux_proc_find_elf),
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  };
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const Dwfl_Callbacks kernel_callbacks =
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .debuginfo_path = &debuginfo_path,
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .find_elf = INTUSE(dwfl_linux_kernel_find_elf),
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  };
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil/* Structure held at state->HOOK.  */
94d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvilstruct parse_opt
95d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil{
96d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  Dwfl *dwfl;
97d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  /* The -e|--executable parameter.  */
98d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  const char *e;
99d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  /* The --core parameter.  */
100d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  const char *core;
101d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil};
102d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg, struct argp_state *state)
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1061656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath  inline void failure (Dwfl *dwfl, int errnum, const char *msg)
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
108d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath      if (dwfl != NULL)
109d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath	dwfl_end (dwfl);
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (errnum == -1)
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      msg, INTUSE(dwfl_errmsg) (-1));
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1161656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath  inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1181656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath      failure (dwfl, errnum, msg);
119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return errnum == -1 ? EIO : errnum;
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
124d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil    case ARGP_KEY_INIT:
125d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
126d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	assert (state->hook == NULL);
127d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = calloc (1, sizeof (*opt));
128d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt == NULL)
129d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  failure (NULL, DWFL_E_ERRNO, "calloc");
130d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	state->hook = opt;
131d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
132d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      break;
133d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_DEBUGINFO:
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuginfo_path = arg;
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'e':
139d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      {
140d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
141d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	Dwfl *dwfl = opt->dwfl;
142d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	if (dwfl == NULL)
143d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  {
144d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
145d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	    if (dwfl == NULL)
1461656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath	      return fail (dwfl, -1, arg);
147d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
148aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper
149aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    /* Start at zero so if there is just one -e foo.so,
150aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	       the DSO is shown without address bias.  */
151aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    dwfl->offline_next_address = 0;
152d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  }
153d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (dwfl->callbacks != &offline_callbacks)
154d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  {
155d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  toomany:
156b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath	    argp_error (state, "%s",
157b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath			_("only one of -e, -p, -k, -K, or --core allowed"));
158d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	    return EINVAL;
159d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  }
160d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	opt->e = arg;
161d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      }
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'p':
165d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
166d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
167d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt->dwfl == NULL)
168d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
169d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
170d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
171d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result != 0)
172d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      return fail (dwfl, result, arg);
17319108019192ab273c53ae324be448d29dac806caMark Wielaard
174824f393411acc4596ab557b6e7bff9e48c61f951Mark Wielaard	    /* Non-fatal to not be able to attach to process, ignore error.  */
175824f393411acc4596ab557b6e7bff9e48c61f951Mark Wielaard	    INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
176824f393411acc4596ab557b6e7bff9e48c61f951Mark Wielaard
177d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
178d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
179d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	else
180d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  goto toomany;
181d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
1821656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath      break;
1831656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath
1841656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath    case 'M':
185d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
186d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
187d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt->dwfl == NULL)
188d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
189d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    FILE *f = fopen (arg, "r");
190d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (f == NULL)
191d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      {
192d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		int code = errno;
193d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		argp_failure (state, EXIT_FAILURE, code,
194d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil			      "cannot open '%s'", arg);
195d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		return code;
196d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      }
197d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
198d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
199d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    fclose (f);
200d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result != 0)
201d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      return fail (dwfl, result, arg);
202d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
203d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
204d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	else
205d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  goto toomany;
206d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
209b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    case OPT_COREFILE:
210b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      {
211d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
212d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	Dwfl *dwfl = opt->dwfl;
213b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath	if (dwfl == NULL)
214d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  opt->dwfl = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
215b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath	/* Permit -e and --core together.  */
216b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath	else if (dwfl->callbacks != &offline_callbacks)
217b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath	  goto toomany;
218d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	opt->core = arg;
219b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      }
220b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath      break;
221b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'k':
223d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
224d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
225d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt->dwfl == NULL)
226d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
227d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
228d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
229d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result != 0)
230d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      return fail (dwfl, result, _("cannot load kernel symbols"));
231d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
232d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result != 0)
233d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      /* Non-fatal to have no modules since we do have the kernel.  */
234d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      failure (dwfl, result, _("cannot find kernel modules"));
235d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
236d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
237d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	else
238d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  goto toomany;
239d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
242d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    case 'K':
243d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
244d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
245d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt->dwfl == NULL)
246d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
247d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
248d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
249d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil								   NULL);
250d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result != 0)
251d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      return fail (dwfl, result, _("cannot find kernel or modules"));
252d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
253d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
254d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	else
255d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  goto toomany;
256d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
257d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      break;
258d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_KEY_SUCCESS:
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
261d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
262d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	Dwfl *dwfl = opt->dwfl;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (dwfl == NULL)
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Default if no -e, -p, or -k, is "-e a.out".  */
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    arg = "a.out";
268d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
269d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	    if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
2701656bc00ae97fa16a941a8cefacc4e01488d0e8aRoland McGrath	      return fail (dwfl, -1, arg);
271d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    opt->dwfl = dwfl;
272d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
273d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
274d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	if (opt->core)
275d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
2763425454a10d307fae891fb667cf7969e945cde79Josh Stone	    int fd = open (opt->core, O_RDONLY);
277d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (fd < 0)
27840025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard	      {
27940025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard		int code = errno;
28040025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard		argp_failure (state, EXIT_FAILURE, code,
28140025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard			      "cannot open '%s'", opt->core);
28240025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard		return code;
28340025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard	      }
284d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
285d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Elf *core;
286d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
287d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (error != DWFL_E_NOERROR)
288d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      {
289d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		argp_failure (state, EXIT_FAILURE, 0,
290d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil			      _("cannot read ELF core file: %s"),
291d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil			      INTUSE(dwfl_errmsg) (error));
292d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		return error == DWFL_E_ERRNO ? errno : EIO;
293d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      }
294d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
2953cf491ee10f10855a49e6a35cc9b8365a3197553Jan Kratochvil	    int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e);
296d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result < 0)
297d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      {
298d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		elf_end (core);
299d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		close (fd);
300d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		return fail (dwfl, result, opt->core);
301d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      }
302d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
303824f393411acc4596ab557b6e7bff9e48c61f951Mark Wielaard	    /* Non-fatal to not be able to attach to core, ignore error.  */
304824f393411acc4596ab557b6e7bff9e48c61f951Mark Wielaard	    INTUSE(dwfl_core_file_attach) (dwfl, core);
30519108019192ab273c53ae324be448d29dac806caMark Wielaard
306355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	    /* Store core Elf and fd in Dwfl to expose with dwfl_end.  */
307355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	    if (dwfl->user_core == NULL)
308355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	      {
309355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
310355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		if (dwfl->user_core == NULL)
311355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		  {
312355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		    argp_failure (state, EXIT_FAILURE, 0,
313355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard				  _("Not enough memory"));
314355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		    return ENOMEM;
315355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard		  }
316355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	      }
317355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	    dwfl->user_core->core = core;
318355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard	    dwfl->user_core->fd = fd;
319d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
320d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (result == 0)
321d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      {
322d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		argp_failure (state, EXIT_FAILURE, 0,
323d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil			      _("No modules recognized in core file"));
324d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil		return ENOENT;
325d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	      }
326d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  }
327d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	else if (opt->e)
328d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	  {
329d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	    if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL)
33040025813dc9e5f2524c3c1851a99efd43cb59894Mark Wielaard	      return fail (dwfl, -1, opt->e);
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* One of the three flavors has done dwfl_begin and some reporting
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   if we got here.  Tie up the Dwfl and return it to the caller of
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   argp_parse.  */
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	assert (result == 0);
339d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
340d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	/* Update the input all along, so a parent parser can see it.
341d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	   As we free OPT the update below will be no longer active.  */
342d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	*(Dwfl **) state->input = dwfl;
343d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	free (opt);
344d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	state->hook = NULL;
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3484be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case ARGP_KEY_ERROR:
349d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      {
350d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	struct parse_opt *opt = state->hook;
351d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	dwfl_end (opt->dwfl);
352d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	free (opt);
353d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil	state->hook = NULL;
354d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil      }
3554be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
3564be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3604be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
3614be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  /* Update the input all along, so a parent parser can see it.  */
362d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  struct parse_opt *opt = state->hook;
363d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil  if (opt)
364d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil    *(Dwfl **) state->input = opt->dwfl;
365d5784afaf49cd59b9286e766cd9b1cf00cb43553Jan Kratochvil
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp libdwfl_argp =
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { .options = options, .parser = parse_opt };
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperconst struct argp *
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperdwfl_standard_argp (void)
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return &libdwfl_argp;
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
377