0.159-4 Add elfutils-0.159-argp-attach.patch (#1107654)

This commit is contained in:
Mark Wielaard 2014-06-10 15:28:11 +02:00
parent 2e16caff89
commit 1648a11415
2 changed files with 365 additions and 1 deletions

View File

@ -0,0 +1,359 @@
commit 68b1afa36d2389c4f2fb526d0b134e5a3c68dedb
Author: Mark Wielaard <mjw@redhat.com>
Date: Tue Jun 10 15:09:23 2014 +0200
libdwfl: dwfl_standard_argp should not fail when not able to attach Dwfl.
As pointed out in https://bugzilla.redhat.com/show_bug.cgi?id=1107654
commit 191080 introduced a thinko that caused dwfl_standard_argp
to fail if the Dwfl couldn't be attached. Instead of generating a warning
as the comment intended, the failure would be fatal. But even warning
about dwfl_core_file_attach () or dwfl_linux_proc_attach () failing
would be a mistake. The caller/user might not be interested in such
a non-fatal issue. So just ignore if the call failed for whatever reason.
If the caller is interested in warning up front about this issue, then
dwfl_pid () should be called to check the Dwfl is attached. Things should
work just fine for anything that doesn't call any of the dwfl_state related
functions.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 8d2bc6a..42b7e78 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -171,10 +171,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (result != 0)
return fail (dwfl, result, arg);
- result = INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
- if (result != 0)
- /* Non-fatal to not be able to attach to process. */
- failure (dwfl, result, _("cannot attach to process"));
+ /* 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
@@ -301,10 +300,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
return fail (dwfl, result, opt->core);
}
- result = INTUSE(dwfl_core_file_attach) (dwfl, core);
- if (result < 0)
- /* Non-fatal to not be able to attach to core. */
- failure (dwfl, result, _("cannot attach to 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. */
commit 14beac3b6f22b8d7a054980f74c4f8d33b969fc4
Author: Mark Wielaard <mjw@redhat.com>
Date: Wed Jun 11 15:14:23 2014 +0200
libdwfl: Record dwfl_attach_state error and return it on failure.
When dwfl_attach_state fails functions that need the process state should
return the error that caused the attach to fail. Use this in the backtrace
test to signal any attach failure. This makes sure that architectures that
don't provide unwinder support get properly detected (and the tests SKIPs)
Also don't assert when trying to attach a non-core ELF file, but return an
error to indicate failure.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
index fd0b9ae..f6f86c0 100644
--- a/libdwfl/dwfl_frame.c
+++ b/libdwfl/dwfl_frame.c
@@ -117,6 +117,7 @@ __libdwfl_process_free (Dwfl_Process *process)
if (process->ebl_close)
ebl_closebackend (process->ebl);
free (process);
+ dwfl->attacherr = DWFL_E_NOERROR;
}
/* Allocate new Dwfl_Process for DWFL. */
@@ -134,17 +135,24 @@ bool
dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
const Dwfl_Thread_Callbacks *thread_callbacks, void *arg)
{
- if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL
- || thread_callbacks->set_initial_registers == NULL)
+ if (dwfl->process != NULL)
{
- __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+ __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
return false;
}
- if (dwfl->process != NULL)
+
+ /* Reset any previous error, we are just going to try again. */
+ dwfl->attacherr = DWFL_E_NOERROR;
+ if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL
+ || thread_callbacks->set_initial_registers == NULL)
{
- __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
+ dwfl->attacherr = DWFL_E_INVALID_ARGUMENT;
+ fail:
+ dwfl->attacherr = __libdwfl_canon_error (dwfl->attacherr);
+ __libdwfl_seterrno (dwfl->attacherr);
return false;
}
+
Ebl *ebl;
bool ebl_close;
if (elf != NULL)
@@ -180,8 +188,8 @@ dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
if (ebl == NULL)
{
/* Not identified EBL from any of the modules. */
- __libdwfl_seterrno (DWFL_E_PROCESS_NO_ARCH);
- return false;
+ dwfl->attacherr = DWFL_E_PROCESS_NO_ARCH;
+ goto fail;
}
process_alloc (dwfl);
Dwfl_Process *process = dwfl->process;
@@ -189,8 +197,8 @@ dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
{
if (ebl_close)
ebl_closebackend (ebl);
- __libdwfl_seterrno (DWFL_E_NOMEM);
- return false;
+ dwfl->attacherr = DWFL_E_NOMEM;
+ goto fail;
}
process->ebl = ebl;
process->ebl_close = ebl_close;
@@ -204,6 +212,12 @@ INTDEF(dwfl_attach_state)
pid_t
dwfl_pid (Dwfl *dwfl)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
if (dwfl->process == NULL)
{
__libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
@@ -238,6 +252,12 @@ int
dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
void *arg)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
@@ -309,6 +329,12 @@ getthread (Dwfl *dwfl, pid_t tid,
int (*callback) (Dwfl_Thread *thread, void *arg),
void *arg)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 9b03d8a..30c0f8a 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -91,7 +91,8 @@ typedef struct Dwfl_Process Dwfl_Process;
DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state")) \
DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \
DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
- DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))
+ DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument")) \
+ DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file"))
#define DWFL_ERROR(name, text) DWFL_E_##name,
typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -110,6 +111,7 @@ struct Dwfl
Dwfl_Module *modulelist; /* List in order used by full traversals. */
Dwfl_Process *process;
+ Dwfl_Error attacherr; /* Previous error attaching process. */
GElf_Addr offline_next_address;
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
index 1002788..7ef3f25 100644
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -309,33 +309,41 @@ static const Dwfl_Thread_Callbacks core_thread_callbacks =
int
dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
{
+ Dwfl_Error err = DWFL_E_NOERROR;
Ebl *ebl = ebl_openbackend (core);
if (ebl == NULL)
{
- __libdwfl_seterrno (DWFL_E_LIBEBL);
+ err = DWFL_E_LIBEBL;
+ fail_err:
+ if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+ dwfl->attacherr = __libdwfl_canon_error (err);
+ __libdwfl_seterrno (err);
return -1;
}
size_t nregs = ebl_frame_nregs (ebl);
if (nregs == 0)
{
- __libdwfl_seterrno (DWFL_E_NO_UNWIND);
+ err = DWFL_E_NO_UNWIND;
+ fail:
ebl_closebackend (ebl);
- return -1;
+ goto fail_err;
}
GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
if (ehdr == NULL)
{
- __libdwfl_seterrno (DWFL_E_LIBELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_LIBELF;
+ goto fail;
+ }
+ if (ehdr->e_type != ET_CORE)
+ {
+ err = DWFL_E_NO_CORE_FILE;
+ goto fail;
}
- assert (ehdr->e_type == ET_CORE);
size_t phnum;
if (elf_getphdrnum (core, &phnum) < 0)
{
- __libdwfl_seterrno (DWFL_E_LIBELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_LIBELF;
+ goto fail;
}
pid_t pid = -1;
Elf_Data *note_data = NULL;
@@ -351,8 +359,8 @@ dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
}
if (note_data == NULL)
{
- ebl_closebackend (ebl);
- return DWFL_E_LIBELF;
+ err = DWFL_E_LIBELF;
+ goto fail;
}
size_t offset = 0;
GElf_Nhdr nhdr;
@@ -394,16 +402,14 @@ dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
if (pid == -1)
{
/* No valid NT_PRPSINFO recognized in this CORE. */
- __libdwfl_seterrno (DWFL_E_BADELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_BADELF;
+ goto fail;
}
struct core_arg *core_arg = malloc (sizeof *core_arg);
if (core_arg == NULL)
{
- __libdwfl_seterrno (DWFL_E_NOMEM);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_NOMEM;
+ goto fail;
}
core_arg->core = core;
core_arg->note_data = note_data;
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 8aee721..d60955e 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -290,13 +290,23 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
{
char buffer[36];
FILE *procfile;
+ int err = 0; /* The errno to return and set for dwfl->attcherr. */
/* Make sure to report the actual PID (thread group leader) to
dwfl_attach_state. */
snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
procfile = fopen (buffer, "r");
if (procfile == NULL)
- return errno;
+ {
+ err = errno;
+ fail:
+ if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+ {
+ errno = err;
+ dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
+ }
+ return err;
+ }
char *line = NULL;
size_t linelen = 0;
@@ -317,19 +327,26 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
fclose (procfile);
if (pid == 0)
- return ESRCH;
+ {
+ err = ESRCH;
+ goto fail;
+ }
char dirname[64];
int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
DIR *dir = opendir (dirname);
if (dir == NULL)
- return errno;
+ {
+ err = errno;
+ goto fail;
+ }
struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
if (pid_arg == NULL)
{
closedir (dir);
- return ENOMEM;
+ err = ENOMEM;
+ goto fail;
}
pid_arg->dir = dir;
pid_arg->tid_attached = 0;
diff --git a/tests/backtrace.c b/tests/backtrace.c
index 1a4709b..ce0bd17 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -1,5 +1,5 @@
/* Test program for unwinding of frames.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -459,6 +459,9 @@ main (int argc __attribute__ ((unused)), char **argv)
};
(void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
assert (dwfl != NULL);
+ /* We want to make sure the dwfl was properly attached. */
+ if (dwfl_pid (dwfl) < 0)
+ error (2, 0, "dwfl_pid: %s", dwfl_errmsg (-1));
dump (dwfl);
dwfl_end (dwfl);
return 0;

View File

@ -1,7 +1,7 @@
Name: elfutils Name: elfutils
Summary: A collection of utilities and DSOs to handle compiled objects Summary: A collection of utilities and DSOs to handle compiled objects
Version: 0.159 Version: 0.159
%global baserelease 3 %global baserelease 4
URL: https://fedorahosted.org/elfutils/ URL: https://fedorahosted.org/elfutils/
%global source_url http://fedorahosted.org/releases/e/l/elfutils/%{version}/ %global source_url http://fedorahosted.org/releases/e/l/elfutils/%{version}/
License: GPLv3+ and (GPLv2+ or LGPLv3+) License: GPLv3+ and (GPLv2+ or LGPLv3+)
@ -46,6 +46,7 @@ Source: %{?source_url}%{name}-%{version}.tar.bz2
Patch1: %{?source_url}elfutils-portability.patch Patch1: %{?source_url}elfutils-portability.patch
Patch2: elfutils-aarch64-user_regs_struct.patch Patch2: elfutils-aarch64-user_regs_struct.patch
Patch3: elfutils-0.159-argp-attach.patch
%if !%{compat} %if !%{compat}
Release: %{baserelease}%{?dist} Release: %{baserelease}%{?dist}
@ -209,6 +210,7 @@ sed -i.scanf-m -e 's/%m/%a/g' src/addr2line.c tests/line2addr.c
%endif %endif
%patch2 -p1 -b .aa64~1 %patch2 -p1 -b .aa64~1
%patch3 -p1 -b .argp-attach
find . -name \*.sh ! -perm -0100 -print | xargs chmod +x find . -name \*.sh ! -perm -0100 -print | xargs chmod +x
@ -331,6 +333,9 @@ rm -rf ${RPM_BUILD_ROOT}
%{_libdir}/libelf.a %{_libdir}/libelf.a
%changelog %changelog
* Tue Jun 10 2014 Mark Wielaard <mjw@redhat.com> - 0.159-4
- Add elfutils-0.159-argp-attach.patch (#1107654)
* Mon Jun 09 2014 Kyle McMartin <kyle@fedoraproject.org> - 0.159-3 * Mon Jun 09 2014 Kyle McMartin <kyle@fedoraproject.org> - 0.159-3
- AArch64: handle new glibc-headers which provides proper GETREGSET structs. - AArch64: handle new glibc-headers which provides proper GETREGSET structs.