summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2012-11-12 21:21:58 +0100
committerJan Kratochvil <jan.kratochvil@redhat.com>2012-11-12 21:21:58 +0100
commitf670f296d076c8dd6694efff94902a013ee1acd1 (patch)
tree6cdd0e791cdcc040557913900c0a9cc33ae9ec73
parent0ed122675b083c8e27e54fa84ffa39d748f5df3d (diff)
downloadelfutils-f670f296d076c8dd6694efff94902a013ee1acd1.tar.gz
+dwfl_core_filename_report
-rw-r--r--libdwfl/argp-std.c20
-rw-r--r--libdwfl/core-file.c37
-rw-r--r--libdwfl/libdwfl.h8
3 files changed, 48 insertions, 17 deletions
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index f0c530f2..8aeb80a1 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -205,7 +205,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
{
FILE *f = fopen (arg, "r");
if (f == NULL)
- nofile:
{
int code = errno;
argp_failure (state, EXIT_FAILURE, code,
@@ -291,31 +290,18 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (opt->core)
{
- int fd = open64 (opt->core, O_RDONLY);
- if (fd < 0)
- goto nofile;
-
- Elf *core;
- Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
- if (error != DWFL_E_NOERROR)
+ if (dwfl_core_filename_report (dwfl, NULL, opt->core) == NULL)
{
+ Dwfl_Error error = dwfl_errno ();
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, opt->core);
- }
-
/* From now we leak FD and CORE. */
- if (result == 0)
+ if (dwfl->modulelist == NULL)
{
argp_failure (state, EXIT_FAILURE, 0,
_("No modules recognized in core file"));
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 1545ca86..f2178472 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -37,6 +37,7 @@
#include <endian.h>
#include <byteswap.h>
#include "system.h"
+#include <fcntl.h>
/* This is a prototype of what a new libelf interface might be.
@@ -461,3 +462,39 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
return sniffed == 0 || listed > sniffed ? listed : sniffed;
}
INTDEF (dwfl_core_file_report)
+
+Elf *
+dwfl_core_filename_report (Dwfl *dwfl, int *fdp, const char *filename)
+{
+ int fd_storage = -1;
+ if (fdp == NULL)
+ fdp = &fd_storage;
+
+ if (*fdp < 0)
+ {
+ *fdp = open64 (filename, O_RDONLY);
+ if (*fdp < 0)
+ {
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return NULL;
+ }
+ }
+
+ Elf *core;
+ Dwfl_Error error = __libdw_open_file (fdp, &core, true, false);
+ if (error != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (error);
+ return NULL;
+ }
+
+ int result = INTUSE(dwfl_core_file_report) (dwfl, core);
+ if (result < 0)
+ {
+ elf_end (core);
+ close (*fdp);
+ return NULL;
+ }
+ return core;
+}
+INTDEF (dwfl_core_filename_report)
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index a2ab8246..c2b85f4b 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -355,6 +355,14 @@ extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
Returns the number of modules reported, or -1 for errors. */
extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+/* Call dwfl_core_file_report but providing FILENAME instead. Function returns
+ opened core file Elf * and its *FDP file descriptor which must be held valid
+ until dwfl_end is called for DWFL. FDP can be passed as NULL (but the
+ caller cannot close the file descriptor then). Function returns NULL for
+ errors, check dwfl_errmsg in such case. */
+extern Elf *dwfl_core_filename_report (Dwfl *dwfl, int *fdp,
+ const char *filename);
+
/* Call dwfl_report_module for each file mapped into the address space of PID.
Returns zero on success, -1 if dwfl_report_module failed,
or an errno code if opening the kernel binary failed. */