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 <[email protected]> * NEWS (Version 0.158): New. libdw/ 2013-10-29 Jan Kratochvil <[email protected]> * libdw.map (ELFUTILS_0.158): New. libdwfl/ 2013-10-29 Jan Kratochvil <[email protected]> * 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,
