On Thu, 2012-10-18 at 00:22 +0200, Jan Kratochvil wrote:
Shared libraries are located by Dwfl_Callbacks->find_elf which
will put them
proper displacement. But the main executable is only specified via
--executable and one cannot easily associate it to the proper core segment.
(It may get associated via build-id but build-id does not have to be available
etc.)
With --core=X --executable=Y order one gets:
0x7ff2cfe9b000 0x7ff2d009c000 [pie]
0x200000 0x400ac0
where the second entry is not relocated.
Similarly it looks for the order --executable=Y --core=X:
0x200000 0x400ac0
0x7ff2cfe9b000 0x7ff2d009c000 [pie]
So before when --core came first dwfl_core_file_report () was called and
then --executable would call dwfl_report_offline () or the other way
around. I am not completely clear on why that results in the bad
mapping, but I assume that is because dwfl_report_segment () and
dwfl_report_offline () don't mix well.
With this patch when both --core and --executable are given in whatever
order dwfl_core_file_report () is called first and the new
offline_find_elf () callback will replace the Dwfl_Module main.name with
the recorded --executable file when the modname is [exe] or [pie] (which
then triggers opening and reporting of the executable). It took me a
while to realize this is what the patch seems to do since the
documentation for the find_elf callback doesn't say that will happen
when you do that (actually, there sadly is no documentation at all for
this callback...). It is a cute trick, but please add a comment in
offline_find_elf that this is what is happening when you return -1.
+/* Wrapper to provide proper FILE_NAME for -e|--executable. */
+static int
+offline_find_elf (Dwfl_Module *mod, void **userdata, const char *modname,
+ Dwarf_Addr base, char **file_name, Elf **elfp)
+{
+ if (modname != NULL && (strcmp (modname, "[exe]") == 0
+ || strcmp (modname, "[pie]") == 0)
+ && *userdata)
+ {
+ char *e_dup = strdup (*userdata);
+ if (e_dup)
+ {
So, please do add a comment here why/how this works.
+ free (*file_name);
+ *file_name = e_dup;
+ return -1;
+ }
+ }
+ return INTUSE(dwfl_build_id_find_elf) (mod, userdata, modname, base,
+ file_name, elfp);
+}
+
+ if (opt->e)
+ for (Dwfl_Module *mod = dwfl->modulelist; mod; mod = mod->next)
+ {
+ if (mod->name == NULL
+ || (strcmp (mod->name, "[exe]") != 0
+ && strcmp (mod->name, "[pie]") != 0))
+ continue;
+ mod->userdata = (void *) opt->e;
+ }
Why is this done?
The following documentation in dwflp.h doesn't really make that clear.
Also it doesn't mention this is only done when --core is given.
-/* Standard argument parsing for using a standard callback set. */
+/* Standard argument parsing for using a standard callback set.
+ Field Dwfl_Module->USERDATA is reserved for "[exe]" or "[pie]"
modules. */
struct argp;
extern const struct argp *dwfl_standard_argp (void) __attribute__ ((const));
Of course in general this documentation could be improved a bit. It was
already a little sparse.
Thanks,
Mark