Hi Mark,
currently dwfl->executable_for_core is private. It is set from
libdwfl/argp-std.c but it is used also from libdwfl/link_map.c.
Applications not using dwfl_standard_argp () cannot use executable_for_core.
This has effect for running jankratochvil/unwindx86 on RHEL-5. RHEL-5 does
not have build-ids, therefore its core files do not contain the first page of
each ELF file. I such case one needs dwfl->executable_for_core to find the
missing program headers (to find DYNAMIC segment). src/stack.c was working
there (thanks to dwfl_standard_argp ()) but tests/backtrace.c was not, as it
calls dwfl_core_file_report () on its own.
Unfortunately jankratochvil/unwindx86 does not work yet on RHEL-5 but that is
unrelated (there is some race with SIGSTOPs, that will be a different patch).
No testcase here. It should be reproducible with jankratochvil/unwindx86 on
RHEL-5 hosts. I could provide a core file generated without the first ELF
page dumping with matching executable but I have not.
Thanks,
Jan
./
2013-10-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* NEWS (Version 0.158): New.
libdw/
2013-10-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* libdw.map (ELFUTILS_0.158): New.
libdwfl/
2013-10-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* argp-std.c (parse_opt): Use executable parameter of
dwfl_core_file_report.
* core-file.c (dwfl_core_file_report): Add parameter executable. Set
it to DWFL. Add NEW_VERSION for it.
(_compat_without_executable_dwfl_core_file_report): New. Twice.
* libdwfl.h (dwfl_core_file_report): Add parameter executable, update
the function comment.
diff --git a/NEWS b/NEWS
index 7236f66..9d73f09 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Version 0.158
+
+libdwfl: dwfl_core_file_report has new parameter executable.
+
Version 0.157
libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 09eae6a..5fb6660 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -267,3 +267,9 @@ ELFUTILS_0.157 {
dwarf_getlocation_die;
dwarf_getlocation_attr;
} ELFUTILS_0.156;
+
+ELFUTILS_0.158 {
+ global:
+ # Replaced ELFUTILS_0.146 version, which has a wrapper without executable.
+ dwfl_core_file_report;
+} ELFUTILS_0.157;
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index c884390..322cdf4 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -295,9 +295,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (opt->core)
{
- if (opt->e)
- dwfl->executable_for_core = strdup (opt->e);
-
int fd = open64 (opt->core, O_RDONLY);
if (fd < 0)
{
@@ -317,7 +314,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
return error == DWFL_E_ERRNO ? errno : EIO;
}
- int result = INTUSE(dwfl_core_file_report) (dwfl, core);
+ int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e);
if (result < 0)
{
elf_end (core);
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 7207591..37613b8 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -398,7 +398,7 @@ clear_r_debug_info (struct r_debug_info *r_debug_info)
}
int
-dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
+dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
{
size_t phnum;
if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
@@ -407,6 +407,19 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
return -1;
}
+ free (dwfl->executable_for_core);
+ if (executable == NULL)
+ dwfl->executable_for_core = NULL;
+ else
+ {
+ dwfl->executable_for_core = strdup (executable);
+ if (dwfl->executable_for_core == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return -1;
+ }
+ }
+
/* First report each PT_LOAD segment. */
GElf_Phdr notes_phdr;
int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr);
@@ -524,3 +537,16 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
return sniffed || listed >= 0 ? listed + sniffed : listed;
}
INTDEF (dwfl_core_file_report)
+NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
+
+#ifdef SHARED
+int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
+ without_executable)
+
+int
+_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
+{
+ return dwfl_core_file_report (dwfl, elf, NULL);
+}
+#endif
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 2b70e28..2ba8234 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -349,11 +349,13 @@ extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char
*release,
This can follow a dwfl_report_offline call to bootstrap the
DT_DEBUG method of following the dynamic linker link_map chain, in
case the core file does not contain enough of the executable's text
- segment to locate its PT_DYNAMIC in the dump. 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.
+ segment to locate its PT_DYNAMIC in the dump. In such case you need to
+ 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.
Returns the number of modules reported, or -1 for errors. */
-extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+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.
Returns zero on success, -1 if dwfl_report_module failed,