summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdw/ChangeLog5
-rw-r--r--libdw/libdw.map3
-rw-r--r--libdwfl/ChangeLog32
-rw-r--r--libdwfl/argp-std.c10
-rw-r--r--libdwfl/core-file.c7
-rw-r--r--libdwfl/dwfl_begin.c1
-rw-r--r--libdwfl/dwfl_frame.c6
-rw-r--r--libdwfl/libdwfl.h26
-rw-r--r--libdwfl/libdwflP.h11
-rw-r--r--libdwfl/linux-core-attach.c51
-rw-r--r--libdwfl/linux-pid-attach.c44
-rw-r--r--libdwfl/linux-proc-maps.c7
-rw-r--r--src/ChangeLog5
-rw-r--r--src/stack.c16
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/backtrace-dwarf.c6
-rw-r--r--tests/backtrace.c6
17 files changed, 157 insertions, 85 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 2b677595..6e779c8e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_core_file_attach and
+ dwfl_linux_proc_attach.
+
2013-12-20 Mark Wielaard <[email protected]>
* libdw.map (ELFUTILS_0.158): Add dwfl_getthread_frames.
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 08c4ddcc..d0e47317 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -288,4 +288,7 @@ ELFUTILS_0.158 {
dwfl_module_getsymtab_first_global;
dwfl_module_addrinfo;
dwfl_module_getsym_info;
+
+ dwfl_core_file_attach;
+ dwfl_linux_proc_attach;
} ELFUTILS_0.157;
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 6c983b2b..2190899e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,35 @@
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * argp-std.c (parse_opt): Call dwfl_linux_proc_attach and
+ dwfl_core_file_attach explicitly.
+ * core-file.c (dwfl_core_file_report): Don't call
+ __libdwfl_attach_state_for_core implicitly.
+ * dwfl_begin.c (dwfl_begin): Remove setting of process_attach_error.
+ * dwfl_frame.c (dwfl_pid): Set errno to DWFL_E_NO_ATTACH_STATE, not
+ process_attach_error.
+ (dwfl_getthreads): Likewise.
+ (getthread): Likewise.
+ * libdwfl.h (dwfl_core_file_report): Update documentation.
+ (dwfl_linux_proc_report): Likewise.
+ (dwfl_core_file_attach): New function declaration.
+ (dwfl_linux_proc_attach): Likewise.
+ * libdwflP.h (struct Dwfl): Remove process_attach_error.
+ (__libdwfl_attach_state_for_pid): Removed declaration.
+ (__libdwfl_attach_state_for_core): Likewise.
+ (dwfl_core_file_attach): New internal declaration.
+ (dwfl_linux_proc_attach): Likewise.
+ (attach_state_for_core): Renamed to...
+ (dwfl_core_file_attach): ...this. Change return type.
+ (__libdwfl_attach_state_for_core): Removed.
+ * linux-pid-attach.c (struct pid_arg): Add assume_ptrace_stopped.
+ (pid_set_initial_registers): Check assume_ptrace_stopped before
+ calling ptrace.
+ (pid_thread_detach): Likewise.
+ (__libdwfl_attach_state_for_pid): Renamed to...
+ (dwfl_linux_proc_attach): ...this. Adjust return type.
+ * linux-proc-maps.c (dwfl_linux_proc_report): Don't call
+ __libdwfl_attach_state_for_pid implicitly.
+
2013-12-28 Mark Wielaard <[email protected]>
* linux-proc-maps.c (dwfl_linux_proc_find_elf): Don't return special
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index cf178eee..3a2d2a59 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -170,6 +170,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
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"));
opt->dwfl = dwfl;
}
else
@@ -296,6 +301,11 @@ 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"));
+
/* From now we leak FD and CORE. */
if (result == 0)
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 92745bd6..4ce63c4e 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -559,13 +559,6 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
clear_r_debug_info (&r_debug_info);
- if (listed > 0)
- {
- /* Possible error is ignored, DWFL still may be useful for non-unwinding
- operations. */
- __libdwfl_attach_state_for_core (dwfl, elf);
- }
-
/* We return the number of modules we found if we found any.
If we found none, we return -1 instead of 0 if there was an
error rather than just nothing found. */
diff --git a/libdwfl/dwfl_begin.c b/libdwfl/dwfl_begin.c
index 490da905..44c16a92 100644
--- a/libdwfl/dwfl_begin.c
+++ b/libdwfl/dwfl_begin.c
@@ -44,7 +44,6 @@ dwfl_begin (const Dwfl_Callbacks *callbacks)
{
dwfl->callbacks = callbacks;
dwfl->offline_next_address = OFFLINE_REDZONE;
- dwfl->process_attach_error = DWFL_E_NO_ATTACH_STATE;
}
return dwfl;
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
index 28008e90..e45cf14c 100644
--- a/libdwfl/dwfl_frame.c
+++ b/libdwfl/dwfl_frame.c
@@ -200,7 +200,7 @@ dwfl_pid (Dwfl *dwfl)
{
if (dwfl->process == NULL)
{
- __libdwfl_seterrno (dwfl->process_attach_error);
+ __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
return -1;
}
return dwfl->process->pid;
@@ -235,7 +235,7 @@ dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
- __libdwfl_seterrno (dwfl->process_attach_error);
+ __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
return -1;
}
@@ -306,7 +306,7 @@ getthread (Dwfl *dwfl, pid_t tid,
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
- __libdwfl_seterrno (dwfl->process_attach_error);
+ __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
return -1;
}
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 67785ea3..2bb4f455 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -361,16 +361,13 @@ extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
supply non-NULL EXECUTABLE, otherwise dynamic libraries will not be loaded
into the DWFL map. This might call dwfl_report_elf on file names found in
the dump if reading some link_map files is the only way to ascertain those
- modules' addresses. dwfl_attach_state is also called for DWFL,
- dwfl_core_file_report does not fail if the dwfl_attach_state call has failed.
- Returns the number of modules reported, or -1 for errors. */
+ modules' addresses. Returns the number of modules reported, or -1 for
+ errors. */
extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable);
/* Call dwfl_report_module for each file mapped into the address space of PID.
- dwfl_attach_state is also called for DWFL, dwfl_linux_proc_report does
- not fail if the dwfl_attach_state call has failed.
Returns zero on success, -1 if dwfl_report_module failed,
- or an errno code if opening the kernel binary failed. */
+ or an errno code if opening the proc files failed. */
extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid);
/* Similar, but reads an input stream in the format of Linux /proc/PID/maps
@@ -717,6 +714,23 @@ bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
void *dwfl_arg)
__nonnull_attribute__ (1, 4);
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+ thread state from the ELF core file. Returns the pid number extracted
+ from the core file, or -1 for errors. */
+extern int dwfl_core_file_attach (Dwfl *dwfl, Elf *elf);
+
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+ thread state from the proc file system. Uses ptrace to attach and stop
+ the thread under inspection and detaches when thread_detach is called
+ and unwinding for the thread is done, unless ASSUME_PTRACE_STOPPED is
+ true. If ASSUME_PTRACE_STOPPED is true the caller should make sure that
+ the thread is ptrace attached and stopped before unwinding by calling
+ either dwfl_thread_getframes or dwfl_getthread_frames. Returns zero on
+ success, -1 if dwfl_attach_state failed, or an errno code if opening the
+ proc files failed. */
+extern int dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid,
+ bool assume_ptrace_stopped);
+
/* Return PID for the process associated with DWFL. Function returns -1 if
dwfl_attach_state was not called for DWFL. */
pid_t dwfl_pid (Dwfl *dwfl)
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 63615a8a..710e6992 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -108,7 +108,6 @@ struct Dwfl
Dwfl_Module *modulelist; /* List in order used by full traversals. */
Dwfl_Process *process;
- Dwfl_Error process_attach_error;
GElf_Addr offline_next_address;
@@ -531,14 +530,6 @@ extern void __libdwfl_process_free (Dwfl_Process *process)
extern void __libdwfl_frame_unwind (Dwfl_Frame *state)
internal_function;
-/* Call dwfl_attach_state for PID, return true if successful. */
-extern bool __libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
- internal_function;
-
-/* Call dwfl_attach_state for CORE, return true if successful. */
-extern bool __libdwfl_attach_state_for_core (Dwfl *dwfl, Elf *core)
- internal_function;
-
/* Align segment START downwards or END upwards addresses according to DWFL. */
extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
internal_function;
@@ -657,6 +648,7 @@ INTDECL (dwfl_addrmodule)
INTDECL (dwfl_addrsegment)
INTDECL (dwfl_addrdwarf)
INTDECL (dwfl_addrdie)
+INTDECL (dwfl_core_file_attach)
INTDECL (dwfl_core_file_report)
INTDECL (dwfl_getmodules)
INTDECL (dwfl_module_addrdie)
@@ -685,6 +677,7 @@ INTDECL (dwfl_standard_find_debuginfo)
INTDECL (dwfl_link_map_report)
INTDECL (dwfl_linux_kernel_find_elf)
INTDECL (dwfl_linux_kernel_module_section_address)
+INTDECL (dwfl_linux_proc_attach)
INTDECL (dwfl_linux_proc_report)
INTDECL (dwfl_linux_proc_maps_report)
INTDECL (dwfl_linux_proc_find_elf)
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
index cc11467b..1002788e 100644
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -306,30 +306,36 @@ static const Dwfl_Thread_Callbacks core_thread_callbacks =
NULL, /* core_thread_detach */
};
-static Dwfl_Error
-attach_state_for_core (Dwfl *dwfl, Elf *core)
+int
+dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
{
Ebl *ebl = ebl_openbackend (core);
if (ebl == NULL)
- return DWFL_E_LIBEBL;
+ {
+ __libdwfl_seterrno (DWFL_E_LIBEBL);
+ return -1;
+ }
size_t nregs = ebl_frame_nregs (ebl);
if (nregs == 0)
{
+ __libdwfl_seterrno (DWFL_E_NO_UNWIND);
ebl_closebackend (ebl);
- return DWFL_E_NO_UNWIND;
+ return -1;
}
GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
if (ehdr == NULL)
{
+ __libdwfl_seterrno (DWFL_E_LIBELF);
ebl_closebackend (ebl);
- return DWFL_E_LIBELF;
+ return -1;
}
assert (ehdr->e_type == ET_CORE);
size_t phnum;
if (elf_getphdrnum (core, &phnum) < 0)
{
+ __libdwfl_seterrno (DWFL_E_LIBELF);
ebl_closebackend (ebl);
- return DWFL_E_LIBELF;
+ return -1;
}
pid_t pid = -1;
Elf_Data *note_data = NULL;
@@ -388,14 +394,16 @@ attach_state_for_core (Dwfl *dwfl, Elf *core)
if (pid == -1)
{
/* No valid NT_PRPSINFO recognized in this CORE. */
+ __libdwfl_seterrno (DWFL_E_BADELF);
ebl_closebackend (ebl);
- return DWFL_E_BADELF;
+ return -1;
}
struct core_arg *core_arg = malloc (sizeof *core_arg);
if (core_arg == NULL)
{
+ __libdwfl_seterrno (DWFL_E_NOMEM);
ebl_closebackend (ebl);
- return DWFL_E_NOMEM;
+ return -1;
}
core_arg->core = core;
core_arg->note_data = note_data;
@@ -404,31 +412,10 @@ attach_state_for_core (Dwfl *dwfl, Elf *core)
if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks,
core_arg))
{
- Dwfl_Error error = dwfl_errno ();
- assert (error != DWFL_E_NOERROR);
free (core_arg);
ebl_closebackend (ebl);
- return error;
- }
- return DWFL_E_NOERROR;
-}
-
-bool
-internal_function
-__libdwfl_attach_state_for_core (Dwfl *dwfl, Elf *core)
-{
- if (dwfl->process != NULL)
- {
- __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
- return false;
+ return -1;
}
- Dwfl_Error error = attach_state_for_core (dwfl, core);
- assert ((dwfl->process != NULL) == (error == DWFL_E_NOERROR));
- dwfl->process_attach_error = error;
- if (error != DWFL_E_NOERROR)
- {
- __libdwfl_seterrno (error);
- return false;
- }
- return true;
+ return pid;
}
+INTDEF (dwfl_core_file_attach)
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 70bd666a..21ff4b99 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -44,6 +44,8 @@ struct pid_arg
pid_t tid_attached;
/* Valid only if TID_ATTACHED is not zero. */
bool tid_was_stopped;
+ /* True if threads are ptrace stopped by caller. */
+ bool assume_ptrace_stopped;
};
static bool
@@ -239,7 +241,8 @@ pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
struct pid_arg *pid_arg = thread_arg;
assert (pid_arg->tid_attached == 0);
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
- if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
+ if (! pid_arg->assume_ptrace_stopped
+ && ! ptrace_attach (tid, &pid_arg->tid_was_stopped))
return false;
pid_arg->tid_attached = tid;
Dwfl_Process *process = thread->process;
@@ -263,12 +266,16 @@ pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
assert (pid_arg->tid_attached == tid);
pid_arg->tid_attached = 0;
- /* This handling is needed only on older Linux kernels such as
- 2.6.32-358.23.2.el6.ppc64. Later kernels such as 3.11.7-200.fc19.x86_64
- remember the T (stopped) state themselves and no longer need to pass
- SIGSTOP during PTRACE_DETACH. */
- ptrace (PTRACE_DETACH, tid, NULL,
- (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
+ if (! pid_arg->assume_ptrace_stopped)
+ {
+ /* This handling is needed only on older Linux kernels such as
+ 2.6.32-358.23.2.el6.ppc64. Later kernels such as
+ 3.11.7-200.fc19.x86_64 remember the T (stopped) state
+ themselves and no longer need to pass SIGSTOP during
+ PTRACE_DETACH. */
+ ptrace (PTRACE_DETACH, tid, NULL,
+ (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
+ }
}
static const Dwfl_Thread_Callbacks pid_thread_callbacks =
@@ -281,9 +288,8 @@ static const Dwfl_Thread_Callbacks pid_thread_callbacks =
pid_thread_detach,
};
-bool
-internal_function
-__libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
+int
+dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
{
char buffer[36];
FILE *procfile;
@@ -293,7 +299,7 @@ __libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
procfile = fopen (buffer, "r");
if (procfile == NULL)
- return false;
+ return errno;
char *line = NULL;
size_t linelen = 0;
@@ -307,32 +313,30 @@ __libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
fclose (procfile);
if (pid == 0)
- return false;
+ return ESRCH;
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)
- {
- __libdwfl_seterrno (DWFL_E_ERRNO);
- return false;
- }
+ return errno;
struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
if (pid_arg == NULL)
{
closedir (dir);
- __libdwfl_seterrno (DWFL_E_NOMEM);
- return false;
+ return ENOMEM;
}
pid_arg->dir = dir;
pid_arg->tid_attached = 0;
+ pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
pid_arg))
{
closedir (dir);
free (pid_arg);
- return false;
+ return -1;
}
- return true;
+ return 0;
}
+INTDEF (dwfl_linux_proc_attach)
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index b1f8b331..cdb6959d 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -301,13 +301,6 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
fclose (f);
- if (result == 0)
- {
- /* Possible error is ignored, DWFL still may be useful for non-unwinding
- operations. */
- __libdwfl_attach_state_for_pid (dwfl, pid);
- }
-
return result;
}
INTDEF (dwfl_linux_proc_report)
diff --git a/src/ChangeLog b/src/ChangeLog
index cb9c8151..811004d3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * stack.c (parse_opt): Explicitly call dwfl_linux_proc_attach
+ or dwfl_core_file_attach and check for errors.
+
2013-12-28 Mark Wielaard <[email protected]>
* stack.c (print_frames): Remove address width code and use...
diff --git a/src/stack.c b/src/stack.c
index 156455c0..2c1d8ff7 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -443,6 +443,22 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+ if (pid != 0)
+ {
+ int err = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (err < 0)
+ error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
+ dwfl_errmsg (-1));
+ else if (err > 0)
+ error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid);
+ }
+
+ if (core != NULL)
+ {
+ if (dwfl_core_file_attach (dwfl, core) < 0)
+ error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
+ }
+
/* Makes sure we are properly attached. */
if (dwfl_pid (dwfl) < 0)
error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1));
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 23c5051d..5c80e9bf 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * backtrace-dwarf.c (report_pid): Explicitly call
+ dwfl_linux_proc_attach and check for errors.
+ * backtrace.c (report_pid): Likewise.
+
2013-12-21 Mark Wielaard <[email protected]>
* backtrace.c (callback_verify): Only assert that case 5 is the last
diff --git a/tests/backtrace-dwarf.c b/tests/backtrace-dwarf.c
index aa12315a..3a3e7632 100644
--- a/tests/backtrace-dwarf.c
+++ b/tests/backtrace-dwarf.c
@@ -41,6 +41,12 @@ report_pid (Dwfl *dwfl, pid_t pid)
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ result = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_attach");
}
static Dwfl *
diff --git a/tests/backtrace.c b/tests/backtrace.c
index 8a7d6dfc..64f90c43 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -279,6 +279,12 @@ report_pid (Dwfl *dwfl, pid_t pid)
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ result = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_attach");
}
static Dwfl *