[patch] Fix for PIE with both -e and --core in use
Mark Wielaard
mjw at redhat.com
Tue Nov 27 13:29:46 UTC 2012
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
More information about the elfutils-devel
mailing list