Home | History | Annotate | Download | only in libdwfl
      1 /* Report modules by examining dynamic linker data structures.
      2    Copyright (C) 2008-2010 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat elfutils is distributed in the hope that it will be useful, but
     10    WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    In addition, as a special exception, Red Hat, Inc. gives You the
     19    additional right to link the code of Red Hat elfutils with code licensed
     20    under any Open Source Initiative certified open source license
     21    (http://www.opensource.org/licenses/index.php) which requires the
     22    distribution of source code with any binary distribution and to
     23    distribute linked combinations of the two.  Non-GPL Code permitted under
     24    this exception must only link to the code of Red Hat elfutils through
     25    those well defined interfaces identified in the file named EXCEPTION
     26    found in the source code files (the "Approved Interfaces").  The files
     27    of Non-GPL Code may instantiate templates or use macros or inline
     28    functions from the Approved Interfaces without causing the resulting
     29    work to be covered by the GNU General Public License.  Only Red Hat,
     30    Inc. may make changes or additions to the list of Approved Interfaces.
     31    Red Hat's grant of this exception is conditioned upon your not adding
     32    any new exceptions.  If you wish to add a new Approved Interface or
     33    exception, please contact Red Hat.  You must obey the GNU General Public
     34    License in all respects for all of the Red Hat elfutils code and other
     35    code used in conjunction with Red Hat elfutils except the Non-GPL Code
     36    covered by this exception.  If you modify this file, you may extend this
     37    exception to your version of the file, but you are not obligated to do
     38    so.  If you do not wish to provide this exception without modification,
     39    you must delete this exception statement from your version and license
     40    this file solely under the GPL without exception.
     41 
     42    Red Hat elfutils is an included package of the Open Invention Network.
     43    An included package of the Open Invention Network is a package for which
     44    Open Invention Network licensees cross-license their patents.  No patent
     45    license is granted, either expressly or impliedly, by designation as an
     46    included package.  Should you wish to participate in the Open Invention
     47    Network licensing program, please visit www.openinventionnetwork.com
     48    <http://www.openinventionnetwork.com>.  */
     49 
     50 #include <config.h>
     51 #include "libdwflP.h"
     52 
     53 #include <byteswap.h>
     54 #include <endian.h>
     55 
     56 /* This element is always provided and always has a constant value.
     57    This makes it an easy thing to scan for to discern the format.  */
     58 #define PROBE_TYPE	AT_PHENT
     59 #define PROBE_VAL32	sizeof (Elf32_Phdr)
     60 #define PROBE_VAL64	sizeof (Elf64_Phdr)
     61 
     62 #if BYTE_ORDER == BIG_ENDIAN
     63 # define BE32(x)	(x)
     64 # define BE64(x)	(x)
     65 # define LE32(x)	bswap_32 (x)
     66 # define LE64(x)	bswap_64 (x)
     67 #else
     68 # define LE32(x)	(x)
     69 # define LE64(x)	(x)
     70 # define BE32(x)	bswap_32 (x)
     71 # define BE64(x)	bswap_64 (x)
     72 #endif
     73 
     74 
     75 /* Examine an auxv data block and determine its format.
     76    Return true iff we figured it out.  */
     77 static bool
     78 auxv_format_probe (const void *auxv, size_t size,
     79 		   uint_fast8_t *elfclass, uint_fast8_t *elfdata)
     80 {
     81   const union
     82   {
     83     char buf[size];
     84     Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
     85     Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
     86   } *u = auxv;
     87 
     88   inline bool check64 (size_t i)
     89   {
     90     if (u->a64[i].a_type == BE64 (PROBE_TYPE)
     91 	&& u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
     92       {
     93 	*elfdata = ELFDATA2MSB;
     94 	return true;
     95       }
     96 
     97     if (u->a64[i].a_type == LE64 (PROBE_TYPE)
     98 	&& u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
     99       {
    100 	*elfdata = ELFDATA2LSB;
    101 	return true;
    102       }
    103 
    104     return false;
    105   }
    106 
    107   inline bool check32 (size_t i)
    108   {
    109     if (u->a32[i].a_type == BE32 (PROBE_TYPE)
    110 	&& u->a32[i].a_un.a_val == BE32 (PROBE_VAL32))
    111       {
    112 	*elfdata = ELFDATA2MSB;
    113 	return true;
    114       }
    115 
    116     if (u->a32[i].a_type == LE32 (PROBE_TYPE)
    117 	&& u->a32[i].a_un.a_val == LE32 (PROBE_VAL32))
    118       {
    119 	*elfdata = ELFDATA2LSB;
    120 	return true;
    121       }
    122 
    123     return false;
    124   }
    125 
    126   for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
    127     {
    128       if (check64 (i))
    129 	{
    130 	  *elfclass = ELFCLASS64;
    131 	  return true;
    132 	}
    133 
    134       if (check32 (i * 2) || check32 (i * 2 + 1))
    135 	{
    136 	  *elfclass = ELFCLASS32;
    137 	  return true;
    138 	}
    139     }
    140 
    141   return false;
    142 }
    143 
    144 /* This is a Dwfl_Memory_Callback that wraps another memory callback.
    146    If the underlying callback cannot fill the data, then this will
    147    fall back to fetching data from module files.  */
    148 
    149 struct integrated_memory_callback
    150 {
    151   Dwfl_Memory_Callback *memory_callback;
    152   void *memory_callback_arg;
    153   void *buffer;
    154 };
    155 
    156 static bool
    157 integrated_memory_callback (Dwfl *dwfl, int ndx,
    158 			       void **buffer, size_t *buffer_available,
    159 			       GElf_Addr vaddr,
    160 			       size_t minread,
    161 			       void *arg)
    162 {
    163   struct integrated_memory_callback *info = arg;
    164 
    165   if (ndx == -1)
    166     {
    167       /* Called for cleanup.  */
    168       if (info->buffer != NULL)
    169 	{
    170 	  /* The last probe buffer came from the underlying callback.
    171 	     Let it do its cleanup.  */
    172 	  assert (*buffer == info->buffer); /* XXX */
    173 	  *buffer = info->buffer;
    174 	  info->buffer = NULL;
    175 	  return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
    176 					   vaddr, minread,
    177 					   info->memory_callback_arg);
    178 	}
    179       *buffer = NULL;
    180       *buffer_available = 0;
    181       return false;
    182     }
    183 
    184   if (*buffer != NULL)
    185     /* For a final-read request, we only use the underlying callback.  */
    186     return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
    187 				     vaddr, minread, info->memory_callback_arg);
    188 
    189   /* Let the underlying callback try to fill this request.  */
    190   if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
    191 				vaddr, minread, info->memory_callback_arg))
    192     {
    193       *buffer = info->buffer;
    194       return true;
    195     }
    196 
    197   /* Now look for module text covering this address.  */
    198 
    199   Dwfl_Module *mod;
    200   (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
    201   if (mod == NULL)
    202     return false;
    203 
    204   Dwarf_Addr bias;
    205   Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
    206   if (unlikely (scn == NULL))
    207     {
    208 #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
    209       /* If we have no sections we can try to fill it from the module file
    210 	 based on its phdr mappings.  */
    211       if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
    212 	return INTUSE(dwfl_elf_phdr_memory_callback)
    213 	  (dwfl, 0, buffer, buffer_available,
    214 	   vaddr - mod->main.bias, minread, mod->main.elf);
    215 #endif
    216       return false;
    217     }
    218 
    219   Elf_Data *data = elf_rawdata (scn, NULL);
    220   if (unlikely (data == NULL))
    221     // XXX throw error?
    222     return false;
    223 
    224   if (unlikely (data->d_size < vaddr))
    225     return false;
    226 
    227   /* Provide as much data as we have.  */
    228   void *contents = data->d_buf + vaddr;
    229   size_t avail = data->d_size - vaddr;
    230   if (unlikely (avail < minread))
    231     return false;
    232 
    233   /* If probing for a string, make sure it's terminated.  */
    234   if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
    235     return false;
    236 
    237   /* We have it! */
    238   *buffer = contents;
    239   *buffer_available = avail;
    240   return true;
    241 }
    242 
    243 static size_t
    245 addrsize (uint_fast8_t elfclass)
    246 {
    247   return elfclass * 4;
    248 }
    249 
    250 /* Report a module for each struct link_map in the linked list at r_map
    251    in the struct r_debug at R_DEBUG_VADDR.
    252 
    253    For each link_map entry, if an existing module resides at its address,
    254    this just modifies that module's name and suggested file name.  If
    255    no such module exists, this calls dwfl_report_elf on the l_name string.
    256 
    257    Returns the number of modules found, or -1 for errors.  */
    258 
    259 static int
    260 report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
    261 		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
    262 		Dwfl_Memory_Callback *memory_callback,
    263 		void *memory_callback_arg)
    264 {
    265   /* Skip r_version, to aligned r_map field.  */
    266   GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
    267 
    268   void *buffer = NULL;
    269   size_t buffer_available = 0;
    270   inline int release_buffer (int result)
    271   {
    272     if (buffer != NULL)
    273       (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
    274 				 memory_callback_arg);
    275     return result;
    276   }
    277 
    278   GElf_Addr addrs[4];
    279   inline bool read_addrs (GElf_Addr vaddr, size_t n)
    280   {
    281     size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
    282 
    283     /* Read a new buffer if the old one doesn't cover these words.  */
    284     if (buffer == NULL
    285 	|| vaddr < read_vaddr
    286 	|| vaddr - read_vaddr + nb > buffer_available)
    287       {
    288 	release_buffer (0);
    289 
    290 	read_vaddr = vaddr;
    291 	int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
    292 	if (unlikely (segndx < 0)
    293 	    || unlikely (! (*memory_callback) (dwfl, segndx,
    294 					       &buffer, &buffer_available,
    295 					       vaddr, nb, memory_callback_arg)))
    296 	  return true;
    297       }
    298 
    299     const union
    300     {
    301       Elf32_Addr a32[n];
    302       Elf64_Addr a64[n];
    303     } *in = vaddr - read_vaddr + buffer;
    304 
    305     if (elfclass == ELFCLASS32)
    306       {
    307 	if (elfdata == ELFDATA2MSB)
    308 	  for (size_t i = 0; i < n; ++i)
    309 	    addrs[i] = BE32 (in->a32[i]);
    310 	else
    311 	  for (size_t i = 0; i < n; ++i)
    312 	    addrs[i] = LE32 (in->a32[i]);
    313       }
    314     else
    315       {
    316 	if (elfdata == ELFDATA2MSB)
    317 	  for (size_t i = 0; i < n; ++i)
    318 	    addrs[i] = BE64 (in->a64[i]);
    319 	else
    320 	  for (size_t i = 0; i < n; ++i)
    321 	    addrs[i] = LE64 (in->a64[i]);
    322       }
    323 
    324     return false;
    325   }
    326 
    327   if (unlikely (read_addrs (read_vaddr, 1)))
    328     return release_buffer (-1);
    329 
    330   GElf_Addr next = addrs[0];
    331 
    332   Dwfl_Module **lastmodp = &dwfl->modulelist;
    333   int result = 0;
    334 
    335   /* There can't be more elements in the link_map list than there are
    336      segments.  DWFL->lookup_elts is probably twice that number, so it
    337      is certainly above the upper bound.  If we iterate too many times,
    338      there must be a loop in the pointers due to link_map clobberation.  */
    339   size_t iterations = 0;
    340   while (next != 0 && ++iterations < dwfl->lookup_elts)
    341     {
    342       if (read_addrs (next, 4))
    343 	return release_buffer (-1);
    344 
    345       GElf_Addr l_addr = addrs[0];
    346       GElf_Addr l_name = addrs[1];
    347       GElf_Addr l_ld = addrs[2];
    348       next = addrs[3];
    349 
    350       /* If a clobbered or truncated memory image has no useful pointer,
    351 	 just skip this element.  */
    352       if (l_ld == 0)
    353 	continue;
    354 
    355       /* Fetch the string at the l_name address.  */
    356       const char *name = NULL;
    357       if (buffer != NULL
    358 	  && read_vaddr <= l_name
    359 	  && l_name + 1 - read_vaddr < buffer_available
    360 	  && memchr (l_name - read_vaddr + buffer, '\0',
    361 		     buffer_available - (l_name - read_vaddr)) != NULL)
    362 	name = l_name - read_vaddr + buffer;
    363       else
    364 	{
    365 	  release_buffer (0);
    366 	  read_vaddr = l_name;
    367 	  int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
    368 	  if (likely (segndx >= 0)
    369 	      && (*memory_callback) (dwfl, segndx,
    370 				     &buffer, &buffer_available,
    371 				     l_name, 0, memory_callback_arg))
    372 	    name = buffer;
    373 	}
    374 
    375       if (name != NULL && name[0] == '\0')
    376 	name = NULL;
    377 
    378       /* If content-sniffing already reported a module covering
    379 	 the same area, find that existing module to adjust.
    380 	 The l_ld address is the only one we know for sure
    381 	 to be within the module's own segments (its .dynamic).  */
    382       Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, l_ld);
    383       if (mod != NULL)
    384 	{
    385 	  /* We have a module.  We can give it a better name from l_name.  */
    386 	  if (name != NULL && mod->name[0] == '[')
    387 	    {
    388 	      char *newname = strdup (basename (name));
    389 	      if (newname != NULL)
    390 		{
    391 		  free (mod->name);
    392 		  mod->name = newname;
    393 		}
    394 	    }
    395 
    396 	  if (name == NULL && mod->name[0] == '/')
    397 	    name = mod->name;
    398 
    399 	  /* If we don't have a file for it already, we can pre-install
    400 	     the full file name from l_name.  Opening the file by this
    401 	     name will be the fallback when no build ID match is found.
    402 	     XXX hook for sysroot */
    403 	  if (name != NULL && mod->main.name == NULL)
    404 	    mod->main.name = strdup (name);
    405 	}
    406       else if (name != NULL)
    407 	{
    408 	  /* We have to find the file's phdrs to compute along with l_addr
    409 	     what its runtime address boundaries are.  */
    410 
    411 	  // XXX hook for sysroot
    412 	  mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
    413 					 name, -1, l_addr);
    414 	}
    415 
    416       if (mod != NULL)
    417 	{
    418 	  ++result;
    419 
    420 	  /* Move this module to the end of the list, so that we end
    421 	     up with a list in the same order as the link_map chain.  */
    422 	  if (mod->next != NULL)
    423 	    {
    424 	      if (*lastmodp != mod)
    425 		{
    426 		  lastmodp = &dwfl->modulelist;
    427 		  while (*lastmodp != mod)
    428 		    lastmodp = &(*lastmodp)->next;
    429 		}
    430 	      *lastmodp = mod->next;
    431 	      mod->next = NULL;
    432 	      while (*lastmodp != NULL)
    433 		lastmodp = &(*lastmodp)->next;
    434 	      *lastmodp = mod;
    435 	    }
    436 
    437 	  lastmodp = &mod->next;
    438 	}
    439     }
    440 
    441   return release_buffer (result);
    442 }
    443 
    444 static GElf_Addr
    446 consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
    447 		     uint_fast8_t *elfclass, uint_fast8_t *elfdata,
    448 		     Dwfl_Memory_Callback *memory_callback,
    449 		     void *memory_callback_arg)
    450 {
    451   GElf_Ehdr ehdr;
    452   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
    453     return 0;
    454 
    455   if (at_entry != 0)
    456     {
    457       /* If we have an AT_ENTRY value, reject this executable if
    458 	 its entry point address could not have supplied that.  */
    459 
    460       if (ehdr.e_entry == 0)
    461 	return 0;
    462 
    463       if (mod->e_type == ET_EXEC)
    464 	{
    465 	  if (ehdr.e_entry != at_entry)
    466 	    return 0;
    467 	}
    468       else
    469 	{
    470 	  /* It could be a PIE.  */
    471 	}
    472     }
    473 
    474   // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
    475   /* Find the vaddr of the DT_DEBUG's d_ptr.  This is the memory
    476      address where &r_debug was written at runtime.  */
    477   GElf_Xword align = mod->dwfl->segment_align;
    478   GElf_Addr d_val_vaddr = 0;
    479   for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
    480     {
    481       GElf_Phdr phdr_mem;
    482       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
    483       if (phdr == NULL)
    484 	break;
    485 
    486       if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
    487 	align = phdr->p_align;
    488 
    489       if (at_phdr != 0
    490 	  && phdr->p_type == PT_LOAD
    491 	  && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
    492 	{
    493 	  /* This is the segment that would map the phdrs.
    494 	     If we have an AT_PHDR value, reject this executable
    495 	     if its phdr mapping could not have supplied that.  */
    496 	  if (mod->e_type == ET_EXEC)
    497 	    {
    498 	      if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
    499 		return 0;
    500 	    }
    501 	  else
    502 	    {
    503 	      /* It could be a PIE.  If the AT_PHDR value and our
    504 		 phdr address don't match modulo ALIGN, then this
    505 		 could not have been the right PIE.  */
    506 	      if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
    507 		  != (at_phdr & -align))
    508 		return 0;
    509 
    510 	      /* Calculate the bias applied to the PIE's p_vaddr values.  */
    511 	      GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
    512 					   + phdr->p_vaddr));
    513 
    514 	      /* Final sanity check: if we have an AT_ENTRY value,
    515 		 reject this PIE unless its biased e_entry matches.  */
    516 	      if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
    517 		return 0;
    518 
    519 	      /* If we're changing the module's address range,
    520 		 we've just invalidated the module lookup table.  */
    521 	      GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
    522 	      if (bias != mod_bias)
    523 		{
    524 		  mod->low_addr -= mod_bias;
    525 		  mod->high_addr -= mod_bias;
    526 		  mod->low_addr += bias;
    527 		  mod->high_addr += bias;
    528 
    529 		  free (mod->dwfl->lookup_module);
    530 		  mod->dwfl->lookup_module = NULL;
    531 		}
    532 	    }
    533 	}
    534 
    535       if (phdr->p_type == PT_DYNAMIC)
    536 	{
    537 	  Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
    538 						 phdr->p_filesz, ELF_T_DYN);
    539 	  if (data == NULL)
    540 	    continue;
    541 	  const size_t entsize = gelf_fsize (mod->main.elf,
    542 					     ELF_T_DYN, 1, EV_CURRENT);
    543 	  const size_t n = data->d_size / entsize;
    544 	  for (size_t j = 0; j < n; ++j)
    545 	    {
    546 	      GElf_Dyn dyn_mem;
    547 	      GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
    548 	      if (dyn != NULL && dyn->d_tag == DT_DEBUG)
    549 		{
    550 		  d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
    551 		  break;
    552 		}
    553 	    }
    554 	}
    555     }
    556 
    557   if (d_val_vaddr != 0)
    558     {
    559       /* Now we have the final address from which to read &r_debug.  */
    560       d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
    561 
    562       void *buffer = NULL;
    563       size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
    564 
    565       int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
    566 
    567       if ((*memory_callback) (mod->dwfl, segndx,
    568 			      &buffer, &buffer_available,
    569 			      d_val_vaddr, buffer_available,
    570 			      memory_callback_arg))
    571 	{
    572 	  const union
    573 	  {
    574 	    Elf32_Addr a32;
    575 	    Elf64_Addr a64;
    576 	  } *u = buffer;
    577 
    578 	  GElf_Addr vaddr;
    579 	  if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
    580 	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
    581 		     ? BE32 (u->a32) : LE32 (u->a32));
    582 	  else
    583 	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
    584 		     ? BE64 (u->a64) : LE64 (u->a64));
    585 
    586 	  (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
    587 			      memory_callback_arg);
    588 
    589 	  if (*elfclass == ELFCLASSNONE)
    590 	    *elfclass = ehdr.e_ident[EI_CLASS];
    591 	  else if (*elfclass != ehdr.e_ident[EI_CLASS])
    592 	    return 0;
    593 
    594 	  if (*elfdata == ELFDATANONE)
    595 	    *elfdata = ehdr.e_ident[EI_DATA];
    596 	  else if (*elfdata != ehdr.e_ident[EI_DATA])
    597 	    return 0;
    598 
    599 	  return vaddr;
    600 	}
    601     }
    602 
    603   return 0;
    604 }
    605 
    606 /* Try to find an existing executable module with a DT_DEBUG.  */
    607 static GElf_Addr
    608 find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
    609 		 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
    610 		 Dwfl_Memory_Callback *memory_callback,
    611 		 void *memory_callback_arg)
    612 {
    613   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
    614     if (mod->main.elf != NULL)
    615       {
    616 	GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
    617 						       elfclass, elfdata,
    618 						       memory_callback,
    619 						       memory_callback_arg);
    620 	if (r_debug_vaddr != 0)
    621 	  return r_debug_vaddr;
    622       }
    623 
    624   return 0;
    625 }
    626 
    627 
    629 int
    630 dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
    631 		      Dwfl_Memory_Callback *memory_callback,
    632 		      void *memory_callback_arg)
    633 {
    634   GElf_Addr r_debug_vaddr = 0;
    635 
    636   uint_fast8_t elfclass = ELFCLASSNONE;
    637   uint_fast8_t elfdata = ELFDATANONE;
    638   if (likely (auxv != NULL)
    639       && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
    640     {
    641       GElf_Addr entry = 0;
    642       GElf_Addr phdr = 0;
    643       GElf_Xword phent = 0;
    644       GElf_Xword phnum = 0;
    645 
    646 #define AUXV_SCAN(NN, BL) do					\
    647 	{							\
    648 	  const Elf##NN##_auxv_t *av = auxv;			\
    649 	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)	\
    650 	    {							\
    651 	      Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val);	\
    652 	      if (av[i].a_type == BL##NN (AT_ENTRY))		\
    653 		entry = val;					\
    654 	      else if (av[i].a_type == BL##NN (AT_PHDR))	\
    655 		phdr = val;					\
    656 	      else if (av[i].a_type == BL##NN (AT_PHNUM))	\
    657 		phnum = val;					\
    658 	      else if (av[i].a_type == BL##NN (AT_PHENT))	\
    659 		phent = val;					\
    660 	      else if (av[i].a_type == BL##NN (AT_PAGESZ))	\
    661 		{						\
    662 		  if (val > 1					\
    663 		      && (dwfl->segment_align == 0		\
    664 			  || val < dwfl->segment_align))	\
    665 		    dwfl->segment_align = val;			\
    666 		}						\
    667 	    }							\
    668 	}							\
    669       while (0)
    670 
    671       if (elfclass == ELFCLASS32)
    672 	{
    673 	  if (elfdata == ELFDATA2MSB)
    674 	    AUXV_SCAN (32, BE);
    675 	  else
    676 	    AUXV_SCAN (32, LE);
    677 	}
    678       else
    679 	{
    680 	  if (elfdata == ELFDATA2MSB)
    681 	    AUXV_SCAN (64, BE);
    682 	  else
    683 	    AUXV_SCAN (64, LE);
    684 	}
    685 
    686       /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC.  */
    687       GElf_Addr dyn_vaddr = 0;
    688       GElf_Xword dyn_filesz = 0;
    689       GElf_Addr dyn_bias = (GElf_Addr) -1;
    690 
    691       inline bool consider_phdr (GElf_Word type,
    692 				 GElf_Addr vaddr, GElf_Xword filesz)
    693       {
    694 	switch (type)
    695 	  {
    696 	  case PT_PHDR:
    697 	    if (dyn_bias == (GElf_Addr) -1
    698 		/* Do a sanity check on the putative address.  */
    699 		&& ((vaddr & (dwfl->segment_align - 1))
    700 		    == (phdr & (dwfl->segment_align - 1))))
    701 	      {
    702 		dyn_bias = phdr - vaddr;
    703 		return dyn_vaddr != 0;
    704 	      }
    705 	    break;
    706 
    707 	  case PT_DYNAMIC:
    708 	    dyn_vaddr = vaddr;
    709 	    dyn_filesz = filesz;
    710 	    return dyn_bias != (GElf_Addr) -1;
    711 	  }
    712 
    713 	return false;
    714       }
    715 
    716       if (phdr != 0 && phnum != 0)
    717 	{
    718 	  Dwfl_Module *phdr_mod;
    719 	  int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
    720 	  Elf_Data in =
    721 	    {
    722 	      .d_type = ELF_T_PHDR,
    723 	      .d_version = EV_CURRENT,
    724 	      .d_size = phnum * phent,
    725 	      .d_buf = NULL
    726 	    };
    727 	  if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
    728 				  phdr, phnum * phent, memory_callback_arg))
    729 	    {
    730 	      union
    731 	      {
    732 		Elf32_Phdr p32;
    733 		Elf64_Phdr p64;
    734 		char data[phnum * phent];
    735 	      } buf;
    736 	      Elf_Data out =
    737 		{
    738 		  .d_type = ELF_T_PHDR,
    739 		  .d_version = EV_CURRENT,
    740 		  .d_size = phnum * phent,
    741 		  .d_buf = &buf
    742 		};
    743 	      in.d_size = out.d_size;
    744 	      if (likely ((elfclass == ELFCLASS32
    745 			   ? elf32_xlatetom : elf64_xlatetom)
    746 			  (&out, &in, elfdata) != NULL))
    747 		{
    748 		  /* We are looking for PT_DYNAMIC.  */
    749 		  const union
    750 		  {
    751 		    Elf32_Phdr p32[phnum];
    752 		    Elf64_Phdr p64[phnum];
    753 		  } *u = (void *) &buf;
    754 		  if (elfclass == ELFCLASS32)
    755 		    {
    756 		      for (size_t i = 0; i < phnum; ++i)
    757 			if (consider_phdr (u->p32[i].p_type,
    758 					   u->p32[i].p_vaddr,
    759 					   u->p32[i].p_filesz))
    760 			  break;
    761 		    }
    762 		  else
    763 		    {
    764 		      for (size_t i = 0; i < phnum; ++i)
    765 			if (consider_phdr (u->p64[i].p_type,
    766 					   u->p64[i].p_vaddr,
    767 					   u->p64[i].p_filesz))
    768 			  break;
    769 		    }
    770 		}
    771 
    772 	      (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    773 				  memory_callback_arg);
    774 	    }
    775 	  else
    776 	    /* We could not read the executable's phdrs from the
    777 	       memory image.  If we have a presupplied executable,
    778 	       we can still use the AT_PHDR and AT_ENTRY values to
    779 	       verify it, and to adjust its bias if it's a PIE.
    780 
    781 	       If there was an ET_EXEC module presupplied that contains
    782 	       the AT_PHDR address, then we only consider that one.
    783 	       We'll either accept it if its phdr location and e_entry
    784 	       make sense or reject it if they don't.  If there is no
    785 	       presupplied ET_EXEC, then look for a presupplied module,
    786 	       which might be a PIE (ET_DYN) that needs its bias adjusted.  */
    787 	    r_debug_vaddr = ((phdr_mod == NULL
    788 			      || phdr_mod->main.elf == NULL
    789 			      || phdr_mod->e_type != ET_EXEC)
    790 			     ? find_executable (dwfl, phdr, entry,
    791 						&elfclass, &elfdata,
    792 						memory_callback,
    793 						memory_callback_arg)
    794 			     : consider_executable (phdr_mod, phdr, entry,
    795 						    &elfclass, &elfdata,
    796 						    memory_callback,
    797 						    memory_callback_arg));
    798 	}
    799 
    800       /* If we found PT_DYNAMIC, search it for DT_DEBUG.  */
    801       if (dyn_filesz != 0)
    802 	{
    803 	  if (dyn_bias != (GElf_Addr) -1)
    804 	    dyn_vaddr += dyn_bias;
    805 
    806 	  Elf_Data in =
    807 	    {
    808 	      .d_type = ELF_T_DYN,
    809 	      .d_version = EV_CURRENT,
    810 	      .d_size = dyn_filesz,
    811 	      .d_buf = NULL
    812 	    };
    813 	  int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
    814 	  if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
    815 				  dyn_vaddr, dyn_filesz, memory_callback_arg))
    816 	    {
    817 	      union
    818 	      {
    819 		Elf32_Dyn d32;
    820 		Elf64_Dyn d64;
    821 		char data[dyn_filesz];
    822 	      } buf;
    823 	      Elf_Data out =
    824 		{
    825 		  .d_type = ELF_T_DYN,
    826 		  .d_version = EV_CURRENT,
    827 		  .d_size = dyn_filesz,
    828 		  .d_buf = &buf
    829 		};
    830 	      in.d_size = out.d_size;
    831 	      if (likely ((elfclass == ELFCLASS32
    832 			   ? elf32_xlatetom : elf64_xlatetom)
    833 			  (&out, &in, elfdata) != NULL))
    834 		{
    835 		  /* We are looking for DT_DEBUG.  */
    836 		  const union
    837 		  {
    838 		    Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
    839 		    Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
    840 		  } *u = (void *) &buf;
    841 		  if (elfclass == ELFCLASS32)
    842 		    {
    843 		      size_t n = dyn_filesz / sizeof (Elf32_Dyn);
    844 		      for (size_t i = 0; i < n; ++i)
    845 			if (u->d32[i].d_tag == DT_DEBUG)
    846 			  {
    847 			    r_debug_vaddr = u->d32[i].d_un.d_val;
    848 			    break;
    849 			  }
    850 		    }
    851 		  else
    852 		    {
    853 		      size_t n = dyn_filesz / sizeof (Elf64_Dyn);
    854 		      for (size_t i = 0; i < n; ++i)
    855 			if (u->d64[i].d_tag == DT_DEBUG)
    856 			  {
    857 			    r_debug_vaddr = u->d64[i].d_un.d_val;
    858 			    break;
    859 			  }
    860 		    }
    861 		}
    862 
    863 	      (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    864 				  memory_callback_arg);
    865 	    }
    866 	}
    867     }
    868   else
    869     /* We have to look for a presupplied executable file to determine
    870        the vaddr of its dynamic section and DT_DEBUG therein.  */
    871     r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
    872 				     memory_callback, memory_callback_arg);
    873 
    874   if (r_debug_vaddr == 0)
    875     return 0;
    876 
    877   /* For following pointers from struct link_map, we will use an
    878      integrated memory access callback that can consult module text
    879      elided from the core file.  This is necessary when the l_name
    880      pointer for the dynamic linker's own entry is a pointer into the
    881      executable's .interp section.  */
    882   struct integrated_memory_callback mcb =
    883     {
    884       .memory_callback = memory_callback,
    885       .memory_callback_arg = memory_callback_arg
    886     };
    887 
    888   /* Now we can follow the dynamic linker's library list.  */
    889   return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
    890 			 &integrated_memory_callback, &mcb);
    891 }
    892 INTDEF (dwfl_link_map_report)
    893