Home | History | Annotate | Download | only in libdwfl
      1 /* Report modules by examining dynamic linker data structures.
      2    Copyright (C) 2008 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   size_t i;
    127   for (i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
    128     {
    129       if (check64 (i))
    130 	{
    131 	  *elfclass = ELFCLASS64;
    132 	  return true;
    133 	}
    134 
    135       if (check32 (i))
    136 	{
    137 	  *elfclass = ELFCLASS32;
    138 	  return true;
    139 	}
    140     }
    141   for (; i < size / sizeof (Elf64_auxv_t); ++i)
    142     if (check32 (i))
    143       {
    144 	*elfclass = ELFCLASS32;
    145 	return true;
    146       }
    147 
    148   return false;
    149 }
    150 
    151 /* This is a Dwfl_Memory_Callback that wraps another memory callback.
    153    If the underlying callback cannot fill the data, then this will
    154    fall back to fetching data from module files.  */
    155 
    156 struct integrated_memory_callback
    157 {
    158   Dwfl_Memory_Callback *memory_callback;
    159   void *memory_callback_arg;
    160   void *buffer;
    161 };
    162 
    163 static bool
    164 integrated_memory_callback (Dwfl *dwfl, int ndx,
    165 			       void **buffer, size_t *buffer_available,
    166 			       GElf_Addr vaddr,
    167 			       size_t minread,
    168 			       void *arg)
    169 {
    170   struct integrated_memory_callback *info = arg;
    171 
    172   if (ndx == -1)
    173     {
    174       /* Called for cleanup.  */
    175       if (info->buffer != NULL)
    176 	{
    177 	  /* The last probe buffer came from the underlying callback.
    178 	     Let it do its cleanup.  */
    179 	  assert (*buffer == info->buffer); /* XXX */
    180 	  *buffer = info->buffer;
    181 	  info->buffer = NULL;
    182 	  return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
    183 					   vaddr, minread,
    184 					   info->memory_callback_arg);
    185 	}
    186       *buffer = NULL;
    187       *buffer_available = 0;
    188       return false;
    189     }
    190 
    191   if (*buffer != NULL)
    192     /* For a final-read request, we only use the underlying callback.  */
    193     return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
    194 				     vaddr, minread, info->memory_callback_arg);
    195 
    196   /* Let the underlying callback try to fill this request.  */
    197   if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
    198 				vaddr, minread, info->memory_callback_arg))
    199     {
    200       *buffer = info->buffer;
    201       return true;
    202     }
    203 
    204   /* Now look for module text covering this address.  */
    205 
    206   Dwfl_Module *mod;
    207   (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
    208   if (mod == NULL)
    209     return false;
    210 
    211   Dwarf_Addr bias;
    212   Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
    213   if (unlikely (scn == NULL))
    214     {
    215 #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
    216       /* If we have no sections we can try to fill it from the module file
    217 	 based on its phdr mappings.  */
    218       if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
    219 	return INTUSE(dwfl_elf_phdr_memory_callback)
    220 	  (dwfl, 0, buffer, buffer_available,
    221 	   vaddr - mod->main.bias, minread, mod->main.elf);
    222 #endif
    223       return false;
    224     }
    225 
    226   Elf_Data *data = elf_rawdata (scn, NULL);
    227   if (unlikely (data == NULL))
    228     // XXX throw error?
    229     return false;
    230 
    231   if (unlikely (data->d_size < vaddr))
    232     return false;
    233 
    234   /* Provide as much data as we have.  */
    235   void *contents = data->d_buf + vaddr;
    236   size_t avail = data->d_size - vaddr;
    237   if (unlikely (avail < minread))
    238     return false;
    239 
    240   /* If probing for a string, make sure it's terminated.  */
    241   if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
    242     return false;
    243 
    244   /* We have it! */
    245   *buffer = contents;
    246   *buffer_available = avail;
    247   return true;
    248 }
    249 
    250 static size_t
    252 addrsize (uint_fast8_t elfclass)
    253 {
    254   return elfclass * 4;
    255 }
    256 
    257 /* Report a module for each struct link_map in the linked list at r_map
    258    in the struct r_debug at R_DEBUG_VADDR.
    259 
    260    For each link_map entry, if an existing module resides at its address,
    261    this just modifies that module's name and suggested file name.  If
    262    no such module exists, this calls dwfl_report_elf on the l_name string.
    263 
    264    Returns the number of modules found, or -1 for errors.  */
    265 
    266 static int
    267 report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
    268 		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
    269 		Dwfl_Memory_Callback *memory_callback,
    270 		void *memory_callback_arg)
    271 {
    272   /* Skip r_version, to aligned r_map field.  */
    273   GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
    274 
    275   void *buffer = NULL;
    276   size_t buffer_available = 0;
    277   inline int release_buffer (int result)
    278   {
    279     if (buffer != NULL)
    280       (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
    281 				 memory_callback_arg);
    282     return result;
    283   }
    284 
    285   GElf_Addr addrs[4];
    286   inline bool read_addrs (GElf_Addr vaddr, size_t n)
    287   {
    288     size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
    289 
    290     /* Read a new buffer if the old one doesn't cover these words.  */
    291     if (buffer == NULL
    292 	|| vaddr < read_vaddr
    293 	|| vaddr - read_vaddr + nb > buffer_available)
    294       {
    295 	release_buffer (0);
    296 
    297 	read_vaddr = vaddr;
    298 	int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
    299 	if (unlikely (segndx < 0)
    300 	    || unlikely (! (*memory_callback) (dwfl, segndx,
    301 					       &buffer, &buffer_available,
    302 					       vaddr, nb, memory_callback_arg)))
    303 	  return true;
    304       }
    305 
    306     const union
    307     {
    308       Elf32_Addr a32[n];
    309       Elf64_Addr a64[n];
    310     } *in = vaddr - read_vaddr + buffer;
    311 
    312     if (elfclass == ELFCLASS32)
    313       {
    314 	if (elfdata == ELFDATA2MSB)
    315 	  for (size_t i = 0; i < n; ++i)
    316 	    addrs[i] = BE32 (in->a32[i]);
    317 	else
    318 	  for (size_t i = 0; i < n; ++i)
    319 	    addrs[i] = LE32 (in->a32[i]);
    320       }
    321     else
    322       {
    323 	if (elfdata == ELFDATA2MSB)
    324 	  for (size_t i = 0; i < n; ++i)
    325 	    addrs[i] = BE64 (in->a64[i]);
    326 	else
    327 	  for (size_t i = 0; i < n; ++i)
    328 	    addrs[i] = LE64 (in->a64[i]);
    329       }
    330 
    331     return false;
    332   }
    333 
    334   if (unlikely (read_addrs (read_vaddr, 1)))
    335     return release_buffer (-1);
    336 
    337   GElf_Addr next = addrs[0];
    338 
    339   Dwfl_Module **lastmodp = &dwfl->modulelist;
    340   int result = 0;
    341   while (next != 0)
    342     {
    343       if (read_addrs (next, 4))
    344 	return release_buffer (-1);
    345 
    346       GElf_Addr l_addr = addrs[0];
    347       GElf_Addr l_name = addrs[1];
    348       GElf_Addr l_ld = addrs[2];
    349       next = addrs[3];
    350 
    351       /* Fetch the string at the l_name address.  */
    352       const char *name = NULL;
    353       if (buffer != NULL
    354 	  && read_vaddr <= l_name
    355 	  && l_name + 1 - read_vaddr < buffer_available
    356 	  && memchr (l_name - read_vaddr + buffer, '\0',
    357 		     buffer_available - (l_name - read_vaddr)) != NULL)
    358 	name = l_name - read_vaddr + buffer;
    359       else
    360 	{
    361 	  release_buffer (0);
    362 	  read_vaddr = l_name;
    363 	  int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
    364 	  if (likely (segndx >= 0)
    365 	      && (*memory_callback) (dwfl, segndx,
    366 				     &buffer, &buffer_available,
    367 				     l_name, 0, memory_callback_arg))
    368 	    name = buffer;
    369 	}
    370 
    371       if (name != NULL && name[0] == '\0')
    372 	name = NULL;
    373 
    374       /* If content-sniffing already reported a module covering
    375 	 the same area, find that existing module to adjust.
    376 	 The l_ld address is the only one we know for sure
    377 	 to be within the module's own segments (its .dynamic).  */
    378       Dwfl_Module *mod;
    379       int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_ld, &mod);
    380       if (unlikely (segndx < 0))
    381 	return release_buffer (-1);
    382 
    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
    404 	      && mod->main.elf == NULL
    405 	      && mod->main.name == NULL)
    406 	    mod->main.name = strdup (name);
    407 	}
    408       else if (name != NULL)
    409 	{
    410 	  /* We have to find the file's phdrs to compute along with l_addr
    411 	     what its runtime address boundaries are.  */
    412 
    413 	  // XXX hook for sysroot
    414 	  mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
    415 					 name, -1, l_addr);
    416 	}
    417 
    418       if (mod != NULL)
    419 	{
    420 	  ++result;
    421 
    422 	  /* Move this module to the end of the list, so that we end
    423 	     up with a list in the same order as the link_map chain.  */
    424 	  if (mod->next != NULL)
    425 	    {
    426 	      if (*lastmodp != mod)
    427 		{
    428 		  lastmodp = &dwfl->modulelist;
    429 		  while (*lastmodp != mod)
    430 		    lastmodp = &(*lastmodp)->next;
    431 		}
    432 	      *lastmodp = mod->next;
    433 	      mod->next = NULL;
    434 	      while (*lastmodp != NULL)
    435 		lastmodp = &(*lastmodp)->next;
    436 	      *lastmodp = mod;
    437 	    }
    438 
    439 	  lastmodp = &mod->next;
    440 	}
    441     }
    442 
    443   return release_buffer (result);
    444 }
    445 
    446 static GElf_Addr
    448 consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
    449 		     uint_fast8_t *elfclass, uint_fast8_t *elfdata,
    450 		     Dwfl_Memory_Callback *memory_callback,
    451 		     void *memory_callback_arg)
    452 {
    453   GElf_Ehdr ehdr;
    454   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
    455     return 0;
    456 
    457   if (at_entry != 0)
    458     {
    459       /* If we have an AT_ENTRY value, reject this executable if
    460 	 its entry point address could not have supplied that.  */
    461 
    462       if (ehdr.e_entry == 0)
    463 	return 0;
    464 
    465       if (mod->e_type == ET_EXEC)
    466 	{
    467 	  if (ehdr.e_entry != at_entry)
    468 	    return 0;
    469 	}
    470       else
    471 	{
    472 	  /* It could be a PIE.  */
    473 	}
    474     }
    475 
    476   // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
    477   /* Find the vaddr of the DT_DEBUG's d_ptr.  This is the memory
    478      address where &r_debug was written at runtime.  */
    479   GElf_Xword align = mod->dwfl->segment_align;
    480   GElf_Addr d_val_vaddr = 0;
    481   for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
    482     {
    483       GElf_Phdr phdr_mem;
    484       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
    485       if (phdr == NULL)
    486 	break;
    487 
    488       if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
    489 	align = phdr->p_align;
    490 
    491       if (at_phdr != 0
    492 	  && phdr->p_type == PT_LOAD
    493 	  && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
    494 	{
    495 	  /* This is the segment that would map the phdrs.
    496 	     If we have an AT_PHDR value, reject this executable
    497 	     if its phdr mapping could not have supplied that.  */
    498 	  if (mod->e_type == ET_EXEC)
    499 	    {
    500 	      if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
    501 		return 0;
    502 	    }
    503 	  else
    504 	    {
    505 	      /* It could be a PIE.  If the AT_PHDR value and our
    506 		 phdr address don't match modulo ALIGN, then this
    507 		 could not have been the right PIE.  */
    508 	      if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
    509 		  != (at_phdr & -align))
    510 		return 0;
    511 
    512 	      /* Calculate the bias applied to the PIE's p_vaddr values.  */
    513 	      GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
    514 					   + phdr->p_vaddr));
    515 
    516 	      /* Final sanity check: if we have an AT_ENTRY value,
    517 		 reject this PIE unless its biased e_entry matches.  */
    518 	      if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
    519 		return 0;
    520 
    521 	      /* If we're changing the module's address range,
    522 		 we've just invalidated the module lookup table.  */
    523 	      if (bias != mod->main.bias)
    524 		{
    525 		  mod->low_addr -= mod->main.bias;
    526 		  mod->high_addr -= mod->main.bias;
    527 		  mod->main.bias = bias;
    528 		  mod->low_addr += bias;
    529 		  mod->high_addr += bias;
    530 
    531 		  free (mod->dwfl->lookup_module);
    532 		  mod->dwfl->lookup_module = NULL;
    533 		}
    534 	    }
    535 	}
    536 
    537       if (phdr->p_type == PT_DYNAMIC)
    538 	{
    539 	  Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
    540 						 phdr->p_filesz, ELF_T_DYN);
    541 	  if (data == NULL)
    542 	    continue;
    543 	  const size_t entsize = gelf_fsize (mod->main.elf,
    544 					     ELF_T_DYN, 1, EV_CURRENT);
    545 	  const size_t n = data->d_size / entsize;
    546 	  for (size_t j = 0; j < n; ++j)
    547 	    {
    548 	      GElf_Dyn dyn_mem;
    549 	      GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
    550 	      if (dyn != NULL && dyn->d_tag == DT_DEBUG)
    551 		{
    552 		  d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
    553 		  break;
    554 		}
    555 	    }
    556 	}
    557     }
    558 
    559   if (d_val_vaddr != 0)
    560     {
    561       /* Now we have the final address from which to read &r_debug.  */
    562       d_val_vaddr += mod->main.bias;
    563 
    564       void *buffer = NULL;
    565       size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
    566 
    567       Dwfl_Module *m;
    568       int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, &m);
    569       assert (m == mod);
    570 
    571       if ((*memory_callback) (mod->dwfl, segndx,
    572 			      &buffer, &buffer_available,
    573 			      d_val_vaddr, buffer_available,
    574 			      memory_callback_arg))
    575 	{
    576 	  const union
    577 	  {
    578 	    Elf32_Addr a32;
    579 	    Elf64_Addr a64;
    580 	  } *u = buffer;
    581 
    582 	  GElf_Addr vaddr;
    583 	  if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
    584 	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
    585 		     ? BE32 (u->a32) : LE32 (u->a32));
    586 	  else
    587 	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
    588 		     ? BE64 (u->a64) : LE64 (u->a64));
    589 
    590 	  (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
    591 			      memory_callback_arg);
    592 
    593 
    594 	  if (*elfclass == ELFCLASSNONE)
    595 	    *elfclass = ehdr.e_ident[EI_CLASS];
    596 	  else if (*elfclass != ehdr.e_ident[EI_CLASS])
    597 	    return 0;
    598 
    599 	  if (*elfdata == ELFDATANONE)
    600 	    *elfdata = ehdr.e_ident[EI_DATA];
    601 	  else if (*elfdata != ehdr.e_ident[EI_DATA])
    602 	    return 0;
    603 
    604 	  return vaddr;
    605 	}
    606     }
    607 
    608   return 0;
    609 }
    610 
    611 /* Try to find an existing executable module with a DT_DEBUG.  */
    612 static GElf_Addr
    613 find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
    614 		 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
    615 		 Dwfl_Memory_Callback *memory_callback,
    616 		 void *memory_callback_arg)
    617 {
    618   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
    619     if (mod->main.elf != NULL)
    620       {
    621 	GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
    622 						       elfclass, elfdata,
    623 						       memory_callback,
    624 						       memory_callback_arg);
    625 	if (r_debug_vaddr != 0)
    626 	  return r_debug_vaddr;
    627       }
    628 
    629   return 0;
    630 }
    631 
    632 
    634 int
    635 dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
    636 		      Dwfl_Memory_Callback *memory_callback,
    637 		      void *memory_callback_arg)
    638 {
    639   GElf_Addr r_debug_vaddr = 0;
    640 
    641   uint_fast8_t elfclass = ELFCLASSNONE;
    642   uint_fast8_t elfdata = ELFDATANONE;
    643   if (likely (auxv != NULL)
    644       && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
    645     {
    646       GElf_Addr entry = 0;
    647       GElf_Addr phdr = 0;
    648       GElf_Xword phent = 0;
    649       GElf_Xword phnum = 0;
    650 
    651 #define AUXV_SCAN(NN, BL) do					\
    652 	{							\
    653 	  const Elf##NN##_auxv_t *av = auxv;			\
    654 	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)	\
    655 	    {							\
    656 	      Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val);	\
    657 	      if (av[i].a_type == BL##NN (AT_ENTRY))		\
    658 		entry = val;					\
    659 	      else if (av[i].a_type == BL##NN (AT_PHDR))	\
    660 		phdr = val;					\
    661 	      else if (av[i].a_type == BL##NN (AT_PHNUM))	\
    662 		phnum = val;					\
    663 	      else if (av[i].a_type == BL##NN (AT_PHENT))	\
    664 		phent = val;					\
    665 	      else if (av[i].a_type == BL##NN (AT_PAGESZ))	\
    666 		{						\
    667 		  if (val > 1					\
    668 		      && (dwfl->segment_align == 0		\
    669 			  || val < dwfl->segment_align))	\
    670 		    dwfl->segment_align = val;			\
    671 		}						\
    672 	    }							\
    673 	}							\
    674       while (0)
    675 
    676       if (elfclass == ELFCLASS32)
    677 	{
    678 	  if (elfdata == ELFDATA2MSB)
    679 	    AUXV_SCAN (32, BE);
    680 	  else
    681 	    AUXV_SCAN (32, LE);
    682 	}
    683       else
    684 	{
    685 	  if (elfdata == ELFDATA2MSB)
    686 	    AUXV_SCAN (64, BE);
    687 	  else
    688 	    AUXV_SCAN (64, LE);
    689 	}
    690 
    691       /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC.  */
    692       GElf_Addr dyn_vaddr = 0;
    693       GElf_Xword dyn_filesz = 0;
    694       if (phdr != 0 && phnum != 0)
    695 	{
    696 	  Dwfl_Module *phdr_mod;
    697 	  int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
    698 	  Elf_Data in =
    699 	    {
    700 	      .d_type = ELF_T_PHDR,
    701 	      .d_version = EV_CURRENT,
    702 	      .d_size = phnum * phent,
    703 	      .d_buf = NULL
    704 	    };
    705 	  if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
    706 				  phdr, phnum * phent, memory_callback_arg))
    707 	    {
    708 	      union
    709 	      {
    710 		Elf32_Phdr p32;
    711 		Elf64_Phdr p64;
    712 		char data[phnum * phent];
    713 	      } buf;
    714 	      Elf_Data out =
    715 		{
    716 		  .d_type = ELF_T_PHDR,
    717 		  .d_version = EV_CURRENT,
    718 		  .d_size = phnum * phent,
    719 		  .d_buf = &buf
    720 		};
    721 	      in.d_size = out.d_size;
    722 	      if (likely ((elfclass == ELFCLASS32
    723 			   ? elf32_xlatetom : elf64_xlatetom)
    724 			  (&out, &in, elfdata) != NULL))
    725 		{
    726 		  /* We are looking for PT_DYNAMIC.  */
    727 		  const union
    728 		  {
    729 		    Elf32_Phdr p32[phnum];
    730 		    Elf64_Phdr p64[phnum];
    731 		  } *u = (void *) &buf;
    732 		  if (elfclass == ELFCLASS32)
    733 		    {
    734 		      for (size_t i = 0; i < phnum; ++i)
    735 			if (u->p32[i].p_type == PT_DYNAMIC)
    736 			  {
    737 			    dyn_vaddr = u->p32[i].p_vaddr;
    738 			    dyn_filesz = u->p32[i].p_filesz;
    739 			    break;
    740 			  }
    741 		    }
    742 		  else
    743 		    {
    744 		      for (size_t i = 0; i < phnum; ++i)
    745 			if (u->p64[i].p_type == PT_DYNAMIC)
    746 			  {
    747 			    dyn_vaddr = u->p64[i].p_vaddr;
    748 			    dyn_filesz = u->p64[i].p_filesz;
    749 			    break;
    750 			  }
    751 		    }
    752 		}
    753 
    754 	      (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    755 				  memory_callback_arg);
    756 	    }
    757 	  else
    758 	    /* We could not read the executable's phdrs from the
    759 	       memory image.  If we have a presupplied executable,
    760 	       we can still use the AT_PHDR and AT_ENTRY values to
    761 	       verify it, and to adjust its bias if it's a PIE.
    762 
    763 	       If there was an ET_EXEC module presupplied that contains
    764 	       the AT_PHDR address, then we only consider that one.
    765 	       We'll either accept it if its phdr location and e_entry
    766 	       make sense or reject it if they don't.  If there is no
    767 	       presupplied ET_EXEC, then look for a presupplied module,
    768 	       which might be a PIE (ET_DYN) that needs its bias adjusted.  */
    769 	    r_debug_vaddr = ((phdr_mod == NULL
    770 			      || phdr_mod->main.elf == NULL
    771 			      || phdr_mod->e_type != ET_EXEC)
    772 			     ? find_executable (dwfl, phdr, entry,
    773 						&elfclass, &elfdata,
    774 						memory_callback,
    775 						memory_callback_arg)
    776 			     : consider_executable (phdr_mod, phdr, entry,
    777 						    &elfclass, &elfdata,
    778 						    memory_callback,
    779 						    memory_callback_arg));
    780 	}
    781 
    782       /* If we found PT_DYNAMIC, search it for DT_DEBUG.  */
    783       if (dyn_filesz != 0)
    784 	{
    785 	  Elf_Data in =
    786 	    {
    787 	      .d_type = ELF_T_DYN,
    788 	      .d_version = EV_CURRENT,
    789 	      .d_size = dyn_filesz,
    790 	      .d_buf = NULL
    791 	    };
    792 	  int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
    793 	  if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
    794 				  dyn_vaddr, dyn_filesz, memory_callback_arg))
    795 	    {
    796 	      union
    797 	      {
    798 		Elf32_Dyn d32;
    799 		Elf64_Dyn d64;
    800 		char data[dyn_filesz];
    801 	      } buf;
    802 	      Elf_Data out =
    803 		{
    804 		  .d_type = ELF_T_DYN,
    805 		  .d_version = EV_CURRENT,
    806 		  .d_size = dyn_filesz,
    807 		  .d_buf = &buf
    808 		};
    809 	      in.d_size = out.d_size;
    810 	      if (likely ((elfclass == ELFCLASS32
    811 			   ? elf32_xlatetom : elf64_xlatetom)
    812 			  (&out, &in, elfdata) != NULL))
    813 		{
    814 		  /* We are looking for PT_DYNAMIC.  */
    815 		  const union
    816 		  {
    817 		    Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
    818 		    Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
    819 		  } *u = (void *) &buf;
    820 		  if (elfclass == ELFCLASS32)
    821 		    {
    822 		      size_t n = dyn_filesz / sizeof (Elf32_Dyn);
    823 		      for (size_t i = 0; i < n; ++i)
    824 			if (u->d32[i].d_tag == DT_DEBUG)
    825 			  {
    826 			    r_debug_vaddr = u->d32[i].d_un.d_val;
    827 			    break;
    828 			  }
    829 		    }
    830 		  else
    831 		    {
    832 		      size_t n = dyn_filesz / sizeof (Elf64_Dyn);
    833 		      for (size_t i = 0; i < n; ++i)
    834 			if (u->d64[i].d_tag == DT_DEBUG)
    835 			  {
    836 			    r_debug_vaddr = u->d64[i].d_un.d_val;
    837 			    break;
    838 			  }
    839 		    }
    840 		}
    841 
    842 	      (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    843 				  memory_callback_arg);
    844 	    }
    845 	}
    846     }
    847   else
    848     /* We have to look for a presupplied executable file to determine
    849        the vaddr of its dynamic section and DT_DEBUG therein.  */
    850     r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
    851 				     memory_callback, memory_callback_arg);
    852 
    853   if (r_debug_vaddr == 0)
    854     return 0;
    855 
    856   /* For following pointers from struct link_map, we will use an
    857      integrated memory access callback that can consult module text
    858      elided from the core file.  This is necessary when the l_name
    859      pointer for the dynamic linker's own entry is a pointer into the
    860      executable's .interp section.  */
    861   struct integrated_memory_callback mcb =
    862     {
    863       .memory_callback = memory_callback,
    864       .memory_callback_arg = memory_callback_arg
    865     };
    866 
    867   /* Now we can follow the dynamic linker's library list.  */
    868   return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
    869 			 &integrated_memory_callback, &mcb);
    870 }
    871 INTDEF (dwfl_link_map_report)
    872