Hi Mark,
I just found that with
__libdwfl_attach_state_for_core hooked into dwfl_core_file_report
and
__libdwfl_attach_state_for_pid hooked into dwfl_linux_proc_report
we no longer need most of the code as dwfl_standard_argp handles it all.
Currently it was calling dwfl_linux_proc_report / dwfl_core_file_report twice.
That is not the case for tests/backtrace.c which intentionally does not use
dwfl_standard_argp so it has to do everything by hand (=to call
dwfl_core_file_report and dwfl_linux_proc_report, nothing more).
Jan
--- a/src/stack.c
+++ b/src/stack.c
@@ -30,36 +30,6 @@
/* libdwfl/argp-std.c */
#define OPT_COREFILE 0x101
-static void
-report_pid (Dwfl *dwfl, pid_t pid)
-{
- int result = dwfl_linux_proc_report (dwfl, pid);
- if (result < 0)
- error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
- else if (result > 0)
- error (2, result, "dwfl_linux_proc_report");
-
- if (dwfl_report_end (dwfl, NULL, NULL) != 0)
- error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
-}
-
-static Dwfl *
-report_corefile (Dwfl *dwfl, const char *corefile)
-{
- int fd = open64 (corefile, O_RDONLY);
- if (fd == -1)
- error (2, 0, "open64: %m");
- Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- error (2, 0, "elf_begin: %s", elf_errmsg (-1));
- if (dwfl_core_file_report (dwfl, elf) < 0)
- error (2, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
- if (dwfl_report_end (dwfl, NULL, NULL) != 0)
- error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
- /* ELF and CORE are leaked. */
- return dwfl;
-}
-
static int
frame_callback (Dwfl_Frame *state, void *arg)
{
@@ -104,54 +74,6 @@ thread_callback (Dwfl_Thread *thread, void *thread_arg
__attribute__ ((unused)))
return DWARF_CB_OK;
}
-static void
-dump (Dwfl *dwfl, pid_t pid, const char *corefile)
-{
- if (pid)
- report_pid (dwfl, pid);
- else if (corefile)
- report_corefile (dwfl, corefile);
- else
- abort ();
- switch (dwfl_getthreads (dwfl, thread_callback, NULL))
- {
- case 0:
- break;
- case -1:
- error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
- break;
- default:
- abort ();
- }
- dwfl_end (dwfl);
-}
-
-static argp_parser_t parse_opt_orig;
-static pid_t pid;
-static const char *corefile;
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'p':
- pid = atoi (arg);
- break;
- case OPT_COREFILE:
- corefile = arg;
- break;
- }
- return parse_opt_orig (key, arg, state);
-}
-
-static void
-usage (void)
-{
- error (2, 0, "eu-stack [--debuginfo-path=<path>] {-p <process id>|"
- "--core=<file> [--executable=<file>]|--help}");
-}
-
int
main (int argc, char **argv)
{
@@ -164,21 +86,30 @@ main (int argc, char **argv)
(void) setlocale (LC_ALL, "");
struct argp argp = *dwfl_standard_argp ();
- parse_opt_orig = argp.parser;
- argp.parser = parse_opt;
int remaining;
Dwfl *dwfl = NULL;
argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
assert (dwfl != NULL);
if (remaining != argc)
- usage ();
+ error (2, 0, "eu-stack [--debuginfo-path=<path>] {-p <process id>|"
+ "--core=<file> [--executable=<file>]|--help}");
- if (pid && !corefile)
- dump (dwfl, pid, NULL);
- else if (corefile && !pid)
- dump (dwfl, 0, corefile);
- else
- usage ();
+ /* dwfl_linux_proc_report has been already called from dwfl_standard_argp's
+ parse_opt function. */
+ if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+ error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+ {
+ case 0:
+ break;
+ case -1:
+ error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+ break;
+ default:
+ abort ();
+ }
+ dwfl_end (dwfl);
return 0;
}