[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