Upgrade to elfutils 0.161.

Change-Id: Iee07e1329d9750f092afc6c2fbd6af8db32862b0
diff --git a/src/libdwfl/argp-std.c b/src/libdwfl/argp-std.c
index e598c6e..42b7e78 100644
--- a/src/libdwfl/argp-std.c
+++ b/src/libdwfl/argp-std.c
@@ -1,51 +1,30 @@
 /* Standard argp argument parsers for tools using libdwfl.
-   Copyright (C) 2005-2010 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
+   Copyright (C) 2005-2010, 2012 Red Hat, Inc.
+   This file is part of elfutils.
 
-   Red Hat elfutils is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by the
-   Free Software Foundation; version 2 of the License.
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
 
-   Red Hat elfutils is distributed in the hope that it will be useful, but
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with Red Hat elfutils; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
-   In addition, as a special exception, Red Hat, Inc. gives You the
-   additional right to link the code of Red Hat elfutils with code licensed
-   under any Open Source Initiative certified open source license
-   (http://www.opensource.org/licenses/index.php) which requires the
-   distribution of source code with any binary distribution and to
-   distribute linked combinations of the two.  Non-GPL Code permitted under
-   this exception must only link to the code of Red Hat elfutils through
-   those well defined interfaces identified in the file named EXCEPTION
-   found in the source code files (the "Approved Interfaces").  The files
-   of Non-GPL Code may instantiate templates or use macros or inline
-   functions from the Approved Interfaces without causing the resulting
-   work to be covered by the GNU General Public License.  Only Red Hat,
-   Inc. may make changes or additions to the list of Approved Interfaces.
-   Red Hat's grant of this exception is conditioned upon your not adding
-   any new exceptions.  If you wish to add a new Approved Interface or
-   exception, please contact Red Hat.  You must obey the GNU General Public
-   License in all respects for all of the Red Hat elfutils code and other
-   code used in conjunction with Red Hat elfutils except the Non-GPL Code
-   covered by this exception.  If you modify this file, you may extend this
-   exception to your version of the file, but you are not obligated to do
-   so.  If you do not wish to provide this exception without modification,
-   you must delete this exception statement from your version and license
-   this file solely under the GPL without exception.
-
-   Red Hat elfutils is an included package of the Open Invention Network.
-   An included package of the Open Invention Network is a package for which
-   Open Invention Network licensees cross-license their patents.  No patent
-   license is granted, either expressly or impliedly, by designation as an
-   included package.  Should you wish to participate in the Open Invention
-   Network licensing program, please visit www.openinventionnetwork.com
-   <http://www.openinventionnetwork.com>.  */
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
 
 #include "libdwflP.h"
 #include <argp.h>
@@ -111,6 +90,16 @@
     .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
   };
 
+/* Structure held at state->HOOK.  */
+struct parse_opt
+{
+  Dwfl *dwfl;
+  /* The -e|--executable parameter.  */
+  const char *e;
+  /* The --core parameter.  */
+  const char *core;
+};
+
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
@@ -132,152 +121,145 @@
 
   switch (key)
     {
+    case ARGP_KEY_INIT:
+      {
+	assert (state->hook == NULL);
+	struct parse_opt *opt = calloc (1, sizeof (*opt));
+	if (opt == NULL)
+	  failure (NULL, DWFL_E_ERRNO, "calloc");
+	state->hook = opt;
+      }
+      break;
+
     case OPT_DEBUGINFO:
       debuginfo_path = arg;
       break;
 
     case 'e':
       {
-	Dwfl *dwfl = state->hook;
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
 	if (dwfl == NULL)
 	  {
 	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
 	    if (dwfl == NULL)
 	      return fail (dwfl, -1, arg);
-	    state->hook = dwfl;
+	    opt->dwfl = dwfl;
 
 	    /* Start at zero so if there is just one -e foo.so,
 	       the DSO is shown without address bias.  */
 	    dwfl->offline_next_address = 0;
 	  }
-	if (dwfl->callbacks == &offline_callbacks)
-	  {
-	    if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
-	      return fail (dwfl, -1, arg);
-	    state->hook = dwfl;
-	  }
-	else
+	if (dwfl->callbacks != &offline_callbacks)
 	  {
 	  toomany:
 	    argp_error (state, "%s",
 			_("only one of -e, -p, -k, -K, or --core allowed"));
 	    return EINVAL;
 	  }
+	opt->e = arg;
       }
       break;
 
     case 'p':
-      if (state->hook == NULL)
-	{
-	  Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
-	  int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
-	  if (result != 0)
-	    return fail (dwfl, result, arg);
-	  state->hook = dwfl;
-	}
-      else
-	goto toomany;
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
+	    int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
+	    if (result != 0)
+	      return fail (dwfl, result, arg);
+
+	    /* Non-fatal to not be able to attach to process, ignore error.  */
+	    INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
+
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
       break;
 
     case 'M':
-      if (state->hook == NULL)
-	{
-	  FILE *f = fopen (arg, "r");
-	  if (f == NULL)
-	  nofile:
-	    {
-	      int code = errno;
-	      argp_failure (state, EXIT_FAILURE, code,
-			    "cannot open '%s'", arg);
-	      return code;
-	    }
-	  Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
-	  int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
-	  fclose (f);
-	  if (result != 0)
-	    return fail (dwfl, result, arg);
-	  state->hook = dwfl;
-	}
-      else
-	goto toomany;
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    FILE *f = fopen (arg, "r");
+	    if (f == NULL)
+	      {
+		int code = errno;
+		argp_failure (state, EXIT_FAILURE, code,
+			      "cannot open '%s'", arg);
+		return code;
+	      }
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
+	    int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
+	    fclose (f);
+	    if (result != 0)
+	      return fail (dwfl, result, arg);
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
       break;
 
     case OPT_COREFILE:
       {
-	Dwfl *dwfl = state->hook;
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
 	if (dwfl == NULL)
-	  state->hook = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	  opt->dwfl = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
 	/* Permit -e and --core together.  */
 	else if (dwfl->callbacks != &offline_callbacks)
 	  goto toomany;
-
-	int fd = open64 (arg, O_RDONLY);
-	if (fd < 0)
-	  goto nofile;
-
-	Elf *core;
-	Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
-	if (error != DWFL_E_NOERROR)
-	  {
-	    argp_failure (state, EXIT_FAILURE, 0,
-			  _("cannot read ELF core file: %s"),
-			  INTUSE(dwfl_errmsg) (error));
-	    return error == DWFL_E_ERRNO ? errno : EIO;
-	  }
-
-	int result = INTUSE(dwfl_core_file_report) (dwfl, core);
-	if (result < 0)
-	  {
-	    elf_end (core);
-	    close (fd);
-	    return fail (dwfl, result, arg);
-	  }
-
-	/* From now we leak FD and CORE.  */
-
-	if (result == 0)
-	  {
-	    argp_failure (state, EXIT_FAILURE, 0,
-			  _("No modules recognized in core file"));
-	    return ENOENT;
-	  }
+	opt->core = arg;
       }
       break;
 
     case 'k':
-      if (state->hook == NULL)
-	{
-	  Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
-	  int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
-	  if (result != 0)
-	    return fail (dwfl, result, _("cannot load kernel symbols"));
-	  result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
-	  if (result != 0)
-	    /* Non-fatal to have no modules since we do have the kernel.  */
-	    failure (dwfl, result, _("cannot find kernel modules"));
-	  state->hook = dwfl;
-	}
-      else
-	goto toomany;
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
+	    int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
+	    if (result != 0)
+	      return fail (dwfl, result, _("cannot load kernel symbols"));
+	    result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
+	    if (result != 0)
+	      /* Non-fatal to have no modules since we do have the kernel.  */
+	      failure (dwfl, result, _("cannot find kernel modules"));
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
       break;
 
     case 'K':
-      if (state->hook == NULL)
-	{
-	  Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
-	  int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
-								 NULL);
-	  if (result != 0)
-	    return fail (dwfl, result, _("cannot find kernel or modules"));
-	  state->hook = dwfl;
-	}
-      else
-	goto toomany;
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	    int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
+								   NULL);
+	    if (result != 0)
+	      return fail (dwfl, result, _("cannot find kernel or modules"));
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
       break;
 
     case ARGP_KEY_SUCCESS:
       {
-	Dwfl *dwfl = state->hook;
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
 
 	if (dwfl == NULL)
 	  {
@@ -286,7 +268,54 @@
 	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
 	    if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
 	      return fail (dwfl, -1, arg);
-	    state->hook = dwfl;
+	    opt->dwfl = dwfl;
+	  }
+
+	if (opt->core)
+	  {
+	    int fd = open64 (opt->core, O_RDONLY);
+	    if (fd < 0)
+	      {
+		int code = errno;
+		argp_failure (state, EXIT_FAILURE, code,
+			      "cannot open '%s'", opt->core);
+		return code;
+	      }
+
+	    Elf *core;
+	    Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
+	    if (error != DWFL_E_NOERROR)
+	      {
+		argp_failure (state, EXIT_FAILURE, 0,
+			      _("cannot read ELF core file: %s"),
+			      INTUSE(dwfl_errmsg) (error));
+		return error == DWFL_E_ERRNO ? errno : EIO;
+	      }
+
+	    int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e);
+	    if (result < 0)
+	      {
+		elf_end (core);
+		close (fd);
+		return fail (dwfl, result, opt->core);
+	      }
+
+	    /* Non-fatal to not be able to attach to core, ignore error.  */
+	    INTUSE(dwfl_core_file_attach) (dwfl, core);
+
+	    /* From now we leak FD and CORE.  */
+
+	    if (result == 0)
+	      {
+		argp_failure (state, EXIT_FAILURE, 0,
+			      _("No modules recognized in core file"));
+		return ENOENT;
+	      }
+	  }
+	else if (opt->e)
+	  {
+	    if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL)
+	      return fail (dwfl, -1, opt->e);
 	  }
 
 	/* One of the three flavors has done dwfl_begin and some reporting
@@ -295,12 +324,22 @@
 
 	int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
 	assert (result == 0);
+
+	/* Update the input all along, so a parent parser can see it.
+	   As we free OPT the update below will be no longer active.  */
+	*(Dwfl **) state->input = dwfl;
+	free (opt);
+	state->hook = NULL;
       }
       break;
 
     case ARGP_KEY_ERROR:
-      dwfl_end (state->hook);
-      state->hook = NULL;
+      {
+	struct parse_opt *opt = state->hook;
+	dwfl_end (opt->dwfl);
+	free (opt);
+	state->hook = NULL;
+      }
       break;
 
     default:
@@ -308,7 +347,10 @@
     }
 
   /* Update the input all along, so a parent parser can see it.  */
-  *(Dwfl **) state->input = state->hook;
+  struct parse_opt *opt = state->hook;
+  if (opt)
+    *(Dwfl **) state->input = opt->dwfl;
+
   return 0;
 }
 
@@ -320,15 +362,3 @@
 {
   return &libdwfl_argp;
 }
-
-#ifdef _MUDFLAP
-/* In the absence of a mudflap wrapper for argp_parse, or a libc compiled
-   with -fmudflap, we'll see spurious errors for using the struct argp_state
-   on argp_parse's stack.  */
-
-void __attribute__ ((constructor))
-__libdwfl_argp_mudflap_options (void)
-{
-  __mf_set_options ("-heur-stack-bound");
-}
-#endif