LCOV - code coverage report
Current view: top level - libdwfl - link_map.c (source / functions) Hit Total Coverage
Test: elfutils-0.189 Lines: 304 470 64.7 %
Date: 2023-04-06 22:54:00 Functions: 8 10 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 245 432 56.7 %

           Branch data     Line data    Source code
       1                 :            : /* Report modules by examining dynamic linker data structures.
       2                 :            :    Copyright (C) 2008-2016 Red Hat, Inc.
       3                 :            :    Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
       4                 :            :    This file is part of elfutils.
       5                 :            : 
       6                 :            :    This file is free software; you can redistribute it and/or modify
       7                 :            :    it under the terms of either
       8                 :            : 
       9                 :            :      * the GNU Lesser General Public License as published by the Free
      10                 :            :        Software Foundation; either version 3 of the License, or (at
      11                 :            :        your option) any later version
      12                 :            : 
      13                 :            :    or
      14                 :            : 
      15                 :            :      * the GNU General Public License as published by the Free
      16                 :            :        Software Foundation; either version 2 of the License, or (at
      17                 :            :        your option) any later version
      18                 :            : 
      19                 :            :    or both in parallel, as here.
      20                 :            : 
      21                 :            :    elfutils is distributed in the hope that it will be useful, but
      22                 :            :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24                 :            :    General Public License for more details.
      25                 :            : 
      26                 :            :    You should have received copies of the GNU General Public License and
      27                 :            :    the GNU Lesser General Public License along with this program.  If
      28                 :            :    not, see <http://www.gnu.org/licenses/>.  */
      29                 :            : 
      30                 :            : #include <config.h>
      31                 :            : #include "libdwflP.h"
      32                 :            : #include "memory-access.h"
      33                 :            : #include "system.h"
      34                 :            : 
      35                 :            : #include <fcntl.h>
      36                 :            : 
      37                 :            : /* This element is always provided and always has a constant value.
      38                 :            :    This makes it an easy thing to scan for to discern the format.  */
      39                 :            : #define PROBE_TYPE      AT_PHENT
      40                 :            : #define PROBE_VAL32     sizeof (Elf32_Phdr)
      41                 :            : #define PROBE_VAL64     sizeof (Elf64_Phdr)
      42                 :            : 
      43                 :            : 
      44                 :            : static inline bool
      45                 :        207 : do_check64 (const char *a64, uint_fast8_t *elfdata)
      46                 :            : {
      47                 :            :   /* The AUXV pointer might not even be naturally aligned for 64-bit
      48                 :            :      data, because note payloads in a core file are not aligned.  */
      49                 :        207 :   const char *typep = a64 + offsetof (Elf64_auxv_t, a_type);
      50                 :        207 :   uint64_t type = read_8ubyte_unaligned_noncvt (typep);
      51                 :        207 :   const char *valp = a64 + offsetof (Elf64_auxv_t, a_un.a_val);
      52                 :        207 :   uint64_t val = read_8ubyte_unaligned_noncvt (valp);
      53                 :            : 
      54         [ +  + ]:        207 :   if (type == BE64 (PROBE_TYPE)
      55         [ +  - ]:          4 :       && val == BE64 (PROBE_VAL64))
      56                 :            :     {
      57                 :          4 :       *elfdata = ELFDATA2MSB;
      58                 :          4 :       return true;
      59                 :            :     }
      60                 :            : 
      61                 :        203 :   if (type == LE64 (PROBE_TYPE)
      62         [ +  + ]:        203 :       && val == LE64 (PROBE_VAL64))
      63                 :            :     {
      64                 :         23 :       *elfdata = ELFDATA2LSB;
      65                 :         23 :       return true;
      66                 :            :     }
      67                 :            : 
      68                 :            :   return false;
      69                 :            : }
      70                 :            : 
      71                 :            : static inline bool
      72                 :        355 : do_check32 (const char *a32, uint_fast8_t *elfdata)
      73                 :            : {
      74                 :            :   /* The AUXV pointer might not even be naturally aligned for 32-bit
      75                 :            :      data, because note payloads in a core file are not aligned.  */
      76                 :        355 :   const char *typep = a32 + offsetof (Elf32_auxv_t, a_type);
      77                 :        355 :   uint32_t type = read_4ubyte_unaligned_noncvt (typep);
      78                 :        355 :   const char *valp = a32 + offsetof (Elf32_auxv_t, a_un.a_val);
      79                 :        355 :   uint32_t val = read_4ubyte_unaligned_noncvt (valp);
      80                 :            : 
      81         [ +  + ]:        355 :   if (type == BE32 (PROBE_TYPE)
      82         [ +  - ]:          3 :       && val == BE32 (PROBE_VAL32))
      83                 :            :     {
      84                 :          3 :       *elfdata = ELFDATA2MSB;
      85                 :          3 :       return true;
      86                 :            :     }
      87                 :            : 
      88                 :        352 :   if (type == LE32 (PROBE_TYPE)
      89         [ +  + ]:        352 :       && val == LE32 (PROBE_VAL32))
      90                 :            :     {
      91                 :          4 :       *elfdata = ELFDATA2LSB;
      92                 :          4 :       return true;
      93                 :            :     }
      94                 :            : 
      95                 :            :   return false;
      96                 :            : }
      97                 :            : 
      98                 :            : /* Examine an auxv data block and determine its format.
      99                 :            :    Return true iff we figured it out.  */
     100                 :            : static bool
     101                 :         34 : auxv_format_probe (const void *auxv, size_t size,
     102                 :            :                    uint_fast8_t *elfclass, uint_fast8_t *elfdata)
     103                 :            : {
     104         [ +  - ]:        207 :   for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
     105                 :            :     {
     106         [ +  + ]:        207 :       if (do_check64 (auxv + i * sizeof (Elf64_auxv_t), elfdata))
     107                 :            :         {
     108                 :         27 :           *elfclass = ELFCLASS64;
     109                 :         27 :           return true;
     110                 :            :         }
     111                 :            : 
     112         [ +  + ]:        180 :       if (do_check32 (auxv + (i * 2) * sizeof (Elf32_auxv_t), elfdata)
     113         [ +  + ]:        175 :           || do_check32 (auxv + (i * 2 + 1) * sizeof (Elf32_auxv_t), elfdata))
     114                 :            :         {
     115                 :          7 :           *elfclass = ELFCLASS32;
     116                 :          7 :           return true;
     117                 :            :         }
     118                 :            :     }
     119                 :            : 
     120                 :            :   return false;
     121                 :            : }
     122                 :            : 
     123                 :            : /* This is a Dwfl_Memory_Callback that wraps another memory callback.
     124                 :            :    If the underlying callback cannot fill the data, then this will
     125                 :            :    fall back to fetching data from module files.  */
     126                 :            : 
     127                 :            : struct integrated_memory_callback
     128                 :            : {
     129                 :            :   Dwfl_Memory_Callback *memory_callback;
     130                 :            :   void *memory_callback_arg;
     131                 :            :   void *buffer;
     132                 :            : };
     133                 :            : 
     134                 :            : static bool
     135                 :        438 : integrated_memory_callback (Dwfl *dwfl, int ndx,
     136                 :            :                                void **buffer, size_t *buffer_available,
     137                 :            :                                GElf_Addr vaddr,
     138                 :            :                                size_t minread,
     139                 :            :                                void *arg)
     140                 :            : {
     141                 :        438 :   struct integrated_memory_callback *info = arg;
     142                 :            : 
     143         [ +  + ]:        438 :   if (ndx == -1)
     144                 :            :     {
     145                 :            :       /* Called for cleanup.  */
     146         [ +  + ]:        205 :       if (info->buffer != NULL)
     147                 :            :         {
     148                 :            :           /* The last probe buffer came from the underlying callback.
     149                 :            :              Let it do its cleanup.  */
     150         [ -  + ]:        193 :           assert (*buffer == info->buffer); /* XXX */
     151                 :        193 :           *buffer = info->buffer;
     152                 :        193 :           info->buffer = NULL;
     153                 :        193 :           return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
     154                 :            :                                            vaddr, minread,
     155                 :            :                                            info->memory_callback_arg);
     156                 :            :         }
     157                 :         12 :       *buffer = NULL;
     158                 :         12 :       *buffer_available = 0;
     159                 :         12 :       return false;
     160                 :            :     }
     161                 :            : 
     162         [ -  + ]:        233 :   if (*buffer != NULL)
     163                 :            :     /* For a final-read request, we only use the underlying callback.  */
     164                 :          0 :     return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
     165                 :            :                                      vaddr, minread, info->memory_callback_arg);
     166                 :            : 
     167                 :            :   /* Let the underlying callback try to fill this request.  */
     168         [ +  + ]:        233 :   if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
     169                 :            :                                 vaddr, minread, info->memory_callback_arg))
     170                 :            :     {
     171                 :        193 :       *buffer = info->buffer;
     172                 :        193 :       return true;
     173                 :            :     }
     174                 :            : 
     175                 :            :   /* Now look for module text covering this address.  */
     176                 :            : 
     177                 :         40 :   Dwfl_Module *mod;
     178                 :         40 :   (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
     179         [ -  + ]:         40 :   if (mod == NULL)
     180                 :            :     return false;
     181                 :            : 
     182                 :          0 :   Dwarf_Addr bias;
     183                 :          0 :   Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
     184         [ #  # ]:          0 :   if (unlikely (scn == NULL))
     185                 :            :     {
     186                 :            : #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
     187                 :            :       /* If we have no sections we can try to fill it from the module file
     188                 :            :          based on its phdr mappings.  */
     189                 :            :       if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
     190                 :            :         return INTUSE(dwfl_elf_phdr_memory_callback)
     191                 :            :           (dwfl, 0, buffer, buffer_available,
     192                 :            :            vaddr - mod->main.bias, minread, mod->main.elf);
     193                 :            : #endif
     194                 :            :       return false;
     195                 :            :     }
     196                 :            : 
     197                 :          0 :   Elf_Data *data = elf_rawdata (scn, NULL);
     198         [ #  # ]:          0 :   if (unlikely (data == NULL))
     199                 :            :     // XXX throw error?
     200                 :            :     return false;
     201                 :            : 
     202         [ #  # ]:          0 :   if (unlikely (data->d_size < vaddr))
     203                 :            :     return false;
     204                 :            : 
     205                 :            :   /* Provide as much data as we have.  */
     206                 :          0 :   void *contents = data->d_buf + vaddr;
     207                 :          0 :   size_t avail = data->d_size - vaddr;
     208         [ #  # ]:          0 :   if (unlikely (avail < minread))
     209                 :            :     return false;
     210                 :            : 
     211                 :            :   /* If probing for a string, make sure it's terminated.  */
     212   [ #  #  #  # ]:          0 :   if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
     213                 :            :     return false;
     214                 :            : 
     215                 :            :   /* We have it! */
     216                 :          0 :   *buffer = contents;
     217                 :          0 :   *buffer_available = avail;
     218                 :          0 :   return true;
     219                 :            : }
     220                 :            : 
     221                 :            : static size_t
     222                 :        151 : addrsize (uint_fast8_t elfclass)
     223                 :            : {
     224                 :        151 :   return elfclass * 4;
     225                 :            : }
     226                 :            : 
     227                 :            : struct memory_closure
     228                 :            : {
     229                 :            :   Dwfl *dwfl;
     230                 :            :   Dwfl_Memory_Callback *callback;
     231                 :            :   void *arg;
     232                 :            : };
     233                 :            : 
     234                 :            : static inline int
     235                 :        281 : release_buffer (struct memory_closure *closure,
     236                 :            :                 void **buffer, size_t *buffer_available, int result)
     237                 :            : {
     238         [ +  + ]:        281 :   if (*buffer != NULL)
     239                 :        193 :     (*closure->callback) (closure->dwfl, -1, buffer, buffer_available, 0, 0,
     240                 :            :                           closure->arg);
     241                 :            : 
     242                 :        281 :   return result;
     243                 :            : }
     244                 :            : 
     245                 :            : static inline bool
     246                 :        130 : read_addrs (struct memory_closure *closure,
     247                 :            :             uint_fast8_t elfclass, uint_fast8_t elfdata,
     248                 :            :             void **buffer, size_t *buffer_available,
     249                 :            :             GElf_Addr vaddr, GElf_Addr *read_vaddr,
     250                 :            :             size_t n, GElf_Addr *addrs /* [4] */)
     251                 :            : {
     252                 :        130 :   size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
     253                 :        130 :   Dwfl *dwfl = closure->dwfl;
     254                 :            : 
     255                 :            :   /* Read a new buffer if the old one doesn't cover these words.  */
     256         [ +  + ]:        130 :   if (*buffer == NULL
     257         [ +  + ]:         73 :       || vaddr < *read_vaddr
     258         [ +  + ]:         35 :       || nb > *buffer_available
     259         [ +  + ]:         22 :       || vaddr - (*read_vaddr) > *buffer_available - nb)
     260                 :            :     {
     261                 :        111 :       release_buffer (closure, buffer, buffer_available, 0);
     262                 :            : 
     263                 :        111 :       *read_vaddr = vaddr;
     264                 :        111 :       int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
     265         [ +  - ]:        111 :       if (unlikely (segndx < 0)
     266         [ -  + ]:        111 :           || unlikely (! (*closure->callback) (dwfl, segndx,
     267                 :            :                                                buffer, buffer_available,
     268                 :            :                                                vaddr, nb, closure->arg)))
     269                 :          0 :         return true;
     270                 :            :     }
     271                 :            : 
     272                 :        130 :   unsigned char *addr = vaddr - (*read_vaddr) + (*buffer);
     273                 :            : 
     274         [ +  + ]:        130 :   if (elfclass == ELFCLASS32)
     275                 :            :     {
     276         [ +  + ]:         14 :       if (elfdata == ELFDATA2MSB)
     277         [ +  + ]:         32 :         for (size_t i = 0; i < n; ++i)
     278                 :         25 :           addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
     279                 :            :       else
     280         [ +  + ]:         32 :         for (size_t i = 0; i < n; ++i)
     281                 :         25 :           addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
     282                 :            :     }
     283                 :            :   else
     284                 :            :     {
     285         [ +  + ]:        116 :       if (elfdata == ELFDATA2MSB)
     286         [ +  + ]:         24 :         for (size_t i = 0; i < n; ++i)
     287                 :         18 :           addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
     288                 :            :       else
     289         [ +  + ]:        499 :         for (size_t i = 0; i < n; ++i)
     290                 :        389 :           addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
     291                 :            :     }
     292                 :            : 
     293                 :            :   return false;
     294                 :            : }
     295                 :            : 
     296                 :            : /* Report a module for each struct link_map in the linked list at r_map
     297                 :            :    in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
     298                 :            :    see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
     299                 :            :    modules get added to DWFL, caller has to add them from filled in
     300                 :            :    R_DEBUG_INFO.
     301                 :            : 
     302                 :            :    For each link_map entry, if an existing module resides at its address,
     303                 :            :    this just modifies that module's name and suggested file name.  If
     304                 :            :    no such module exists, this calls dwfl_report_elf on the l_name string.
     305                 :            : 
     306                 :            :    Returns the number of modules found, or -1 for errors.  */
     307                 :            : 
     308                 :            : static int
     309                 :         21 : report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
     310                 :            :                 Dwfl *dwfl, GElf_Addr r_debug_vaddr,
     311                 :            :                 Dwfl_Memory_Callback *memory_callback,
     312                 :            :                 void *memory_callback_arg,
     313                 :            :                 struct r_debug_info *r_debug_info)
     314                 :            : {
     315                 :            :   /* Skip r_version, to aligned r_map field.  */
     316                 :         21 :   GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
     317                 :            : 
     318                 :         21 :   void *buffer = NULL;
     319                 :         21 :   size_t buffer_available = 0;
     320                 :         21 :   GElf_Addr addrs[4];
     321                 :         21 :   struct memory_closure memory_closure = { dwfl, memory_callback,
     322                 :            :                                            memory_callback_arg };
     323         [ -  + ]:         21 :   if (unlikely (read_addrs (&memory_closure, elfclass, elfdata,
     324                 :            :                             &buffer, &buffer_available, read_vaddr, &read_vaddr,
     325                 :            :                             1, addrs)))
     326                 :          0 :     return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
     327                 :            : 
     328                 :         21 :   GElf_Addr next = addrs[0];
     329                 :            : 
     330                 :         21 :   Dwfl_Module **lastmodp = &dwfl->modulelist;
     331                 :         21 :   int result = 0;
     332                 :            : 
     333                 :            :   /* There can't be more elements in the link_map list than there are
     334                 :            :      segments.  DWFL->lookup_elts is probably twice that number, so it
     335                 :            :      is certainly above the upper bound.  If we iterate too many times,
     336                 :            :      there must be a loop in the pointers due to link_map clobberation.  */
     337                 :         21 :   size_t iterations = 0;
     338   [ +  +  +  - ]:        130 :   while (next != 0 && ++iterations < dwfl->lookup_elts)
     339                 :            :     {
     340         [ -  + ]:        109 :       if (read_addrs (&memory_closure, elfclass, elfdata,
     341                 :            :                       &buffer, &buffer_available, next, &read_vaddr,
     342                 :            :                       4, addrs))
     343                 :          0 :         return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
     344                 :            : 
     345                 :            :       /* Unused: l_addr is the difference between the address in memory
     346                 :            :          and the ELF file when the core was created. We need to
     347                 :            :          recalculate the difference below because the ELF file we use
     348                 :            :          might be differently pre-linked.  */
     349                 :            :       // GElf_Addr l_addr = addrs[0];
     350                 :        109 :       GElf_Addr l_name = addrs[1];
     351                 :        109 :       GElf_Addr l_ld = addrs[2];
     352                 :        109 :       next = addrs[3];
     353                 :            : 
     354                 :            :       /* If a clobbered or truncated memory image has no useful pointer,
     355                 :            :          just skip this element.  */
     356         [ +  + ]:        109 :       if (l_ld == 0)
     357                 :          1 :         continue;
     358                 :            : 
     359                 :            :       /* Fetch the string at the l_name address.  */
     360                 :        108 :       const char *name = NULL;
     361         [ +  - ]:        108 :       if (buffer != NULL
     362         [ +  + ]:        108 :           && read_vaddr <= l_name
     363         [ +  + ]:         14 :           && l_name + 1 - read_vaddr < buffer_available
     364                 :          1 :           && memchr (l_name - read_vaddr + buffer, '\0',
     365         [ -  + ]:          1 :                      buffer_available - (l_name - read_vaddr)) != NULL)
     366                 :            :         name = l_name - read_vaddr + buffer;
     367                 :            :       else
     368                 :            :         {
     369                 :        107 :           release_buffer (&memory_closure, &buffer, &buffer_available, 0);
     370                 :        107 :           read_vaddr = l_name;
     371                 :        107 :           int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
     372         [ +  - ]:        107 :           if (likely (segndx >= 0)
     373         [ +  + ]:        107 :               && (*memory_callback) (dwfl, segndx,
     374                 :            :                                      &buffer, &buffer_available,
     375                 :            :                                      l_name, 0, memory_callback_arg))
     376                 :         67 :             name = buffer;
     377                 :            :         }
     378                 :            : 
     379   [ +  -  -  + ]:         68 :       if (name != NULL && name[0] == '\0')
     380                 :          0 :         name = NULL;
     381                 :            : 
     382         [ +  + ]:        108 :       if (iterations == 1
     383         [ +  + ]:         19 :           && dwfl->user_core != NULL
     384         [ +  - ]:         16 :           && dwfl->user_core->executable_for_core != NULL)
     385                 :         16 :         name = dwfl->user_core->executable_for_core;
     386                 :            : 
     387                 :        108 :       struct r_debug_info_module *r_debug_info_module = NULL;
     388         [ +  - ]:        108 :       if (r_debug_info != NULL)
     389                 :            :         {
     390                 :            :           /* Save link map information about valid shared library (or
     391                 :            :              executable) which has not been found on disk.  */
     392         [ +  + ]:        108 :           const char *name1 = name == NULL ? "" : name;
     393                 :        108 :           r_debug_info_module = malloc (sizeof (*r_debug_info_module)
     394                 :        108 :                                         + strlen (name1) + 1);
     395         [ -  + ]:        108 :           if (unlikely (r_debug_info_module == NULL))
     396                 :          0 :             release_buffer (&memory_closure, &buffer,
     397                 :            :                             &buffer_available, result);
     398                 :        108 :           r_debug_info_module->fd = -1;
     399                 :        108 :           r_debug_info_module->elf = NULL;
     400                 :        108 :           r_debug_info_module->l_ld = l_ld;
     401                 :        108 :           r_debug_info_module->start = 0;
     402                 :        108 :           r_debug_info_module->end = 0;
     403                 :        108 :           r_debug_info_module->disk_file_has_build_id = false;
     404                 :        108 :           strcpy (r_debug_info_module->name, name1);
     405                 :        108 :           r_debug_info_module->next = r_debug_info->module;
     406                 :        108 :           r_debug_info->module = r_debug_info_module;
     407                 :            :         }
     408                 :            : 
     409                 :        108 :       Dwfl_Module *mod = NULL;
     410         [ +  + ]:        108 :       if (name != NULL)
     411                 :            :         {
     412                 :            :           /* This code is mostly inlined dwfl_report_elf.  */
     413                 :            :           // XXX hook for sysroot
     414                 :         84 :           int fd = open (name, O_RDONLY);
     415         [ +  + ]:         84 :           if (fd >= 0)
     416                 :            :             {
     417                 :         30 :               Elf *elf;
     418                 :         30 :               Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
     419                 :         30 :               GElf_Addr elf_dynamic_vaddr;
     420         [ -  + ]:         30 :               if (error == DWFL_E_NOERROR
     421         [ -  + ]:         30 :                   && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
     422                 :            :                 {
     423                 :         30 :                   const void *build_id_bits;
     424                 :         30 :                   GElf_Addr build_id_elfaddr;
     425                 :         30 :                   int build_id_len;
     426                 :         30 :                   bool valid = true;
     427                 :            : 
     428         [ +  + ]:         30 :                   if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
     429                 :            :                                                    &build_id_elfaddr,
     430                 :            :                                                    &build_id_len) > 0
     431         [ +  - ]:         27 :                       && build_id_elfaddr != 0)
     432                 :            :                     {
     433         [ +  - ]:         27 :                       if (r_debug_info_module != NULL)
     434                 :         27 :                         r_debug_info_module->disk_file_has_build_id = true;
     435                 :         27 :                       GElf_Addr build_id_vaddr = (build_id_elfaddr
     436                 :         27 :                                                   - elf_dynamic_vaddr + l_ld);
     437                 :            : 
     438                 :         27 :                       release_buffer (&memory_closure, &buffer,
     439                 :            :                                       &buffer_available, 0);
     440                 :         27 :                       int segndx = INTUSE(dwfl_addrsegment) (dwfl,
     441                 :            :                                                              build_id_vaddr,
     442                 :            :                                                              NULL);
     443         [ +  + ]:         27 :                       if (! (*memory_callback) (dwfl, segndx,
     444                 :            :                                                 &buffer, &buffer_available,
     445                 :            :                                                 build_id_vaddr, build_id_len,
     446                 :            :                                                 memory_callback_arg))
     447                 :            :                         {
     448                 :            :                           /* File has valid build-id which cannot be read from
     449                 :            :                              memory.  This happens for core files without bit 4
     450                 :            :                              (0x10) set in Linux /proc/PID/coredump_filter.  */
     451                 :            :                         }
     452                 :            :                       else
     453                 :            :                         {
     454         [ -  + ]:         15 :                           if (memcmp (build_id_bits, buffer, build_id_len) != 0)
     455                 :            :                             /* File has valid build-id which does not match
     456                 :            :                                the one in memory.  */
     457                 :          0 :                             valid = false;
     458                 :         15 :                           release_buffer (&memory_closure, &buffer,
     459                 :            :                                           &buffer_available, 0);
     460                 :            : 
     461                 :            :                         }
     462                 :            :                     }
     463                 :            : 
     464         [ +  - ]:         15 :                   if (valid)
     465                 :            :                     {
     466                 :            :                       // It is like l_addr but it handles differently prelinked
     467                 :            :                       // files at core dumping vs. core loading time.
     468                 :         30 :                       GElf_Addr base = l_ld - elf_dynamic_vaddr;
     469         [ -  + ]:         30 :                       if (r_debug_info_module == NULL)
     470                 :            :                         {
     471                 :            :                           // XXX hook for sysroot
     472                 :          0 :                           mod = __libdwfl_report_elf (dwfl, basename (name),
     473                 :            :                                                       name, fd, elf, base,
     474                 :            :                                                       true, true);
     475         [ #  # ]:          0 :                           if (mod != NULL)
     476                 :            :                             {
     477                 :          0 :                               elf = NULL;
     478                 :          0 :                               fd = -1;
     479                 :            :                             }
     480                 :            :                         }
     481         [ +  - ]:         30 :                       else if (__libdwfl_elf_address_range (elf, base, true,
     482                 :            :                                                             true, NULL, NULL,
     483                 :            :                                                     &r_debug_info_module->start,
     484                 :            :                                                     &r_debug_info_module->end,
     485                 :            :                                                             NULL, NULL))
     486                 :            :                         {
     487                 :         30 :                           r_debug_info_module->elf = elf;
     488                 :         30 :                           r_debug_info_module->fd = fd;
     489                 :         30 :                           elf = NULL;
     490                 :         30 :                           fd = -1;
     491                 :            :                         }
     492                 :            :                     }
     493         [ -  + ]:         30 :                   if (elf != NULL)
     494                 :          0 :                     elf_end (elf);
     495         [ -  + ]:         30 :                   if (fd != -1)
     496                 :          0 :                     close (fd);
     497                 :            :                 }
     498                 :            :             }
     499                 :            :         }
     500                 :            : 
     501         [ -  + ]:         84 :       if (mod != NULL)
     502                 :            :         {
     503                 :          0 :           ++result;
     504                 :            : 
     505                 :            :           /* Move this module to the end of the list, so that we end
     506                 :            :              up with a list in the same order as the link_map chain.  */
     507         [ #  # ]:          0 :           if (mod->next != NULL)
     508                 :            :             {
     509         [ #  # ]:          0 :               if (*lastmodp != mod)
     510                 :            :                 {
     511                 :            :                   lastmodp = &dwfl->modulelist;
     512         [ #  # ]:          0 :                   while (*lastmodp != mod)
     513                 :          0 :                     lastmodp = &(*lastmodp)->next;
     514                 :            :                 }
     515                 :          0 :               *lastmodp = mod->next;
     516                 :          0 :               mod->next = NULL;
     517         [ #  # ]:          0 :               while (*lastmodp != NULL)
     518                 :          0 :                 lastmodp = &(*lastmodp)->next;
     519                 :          0 :               *lastmodp = mod;
     520                 :            :             }
     521                 :            : 
     522                 :          0 :           lastmodp = &mod->next;
     523                 :            :         }
     524                 :            :     }
     525                 :            : 
     526                 :         21 :   return release_buffer (&memory_closure, &buffer, &buffer_available, result);
     527                 :            : }
     528                 :            : 
     529                 :            : static GElf_Addr
     530                 :          0 : consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
     531                 :            :                      uint_fast8_t *elfclass, uint_fast8_t *elfdata,
     532                 :            :                      Dwfl_Memory_Callback *memory_callback,
     533                 :            :                      void *memory_callback_arg)
     534                 :            : {
     535                 :          0 :   GElf_Ehdr ehdr;
     536         [ #  # ]:          0 :   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
     537                 :            :     return 0;
     538                 :            : 
     539         [ #  # ]:          0 :   if (at_entry != 0)
     540                 :            :     {
     541                 :            :       /* If we have an AT_ENTRY value, reject this executable if
     542                 :            :          its entry point address could not have supplied that.  */
     543                 :            : 
     544         [ #  # ]:          0 :       if (ehdr.e_entry == 0)
     545                 :            :         return 0;
     546                 :            : 
     547         [ #  # ]:          0 :       if (mod->e_type == ET_EXEC)
     548                 :            :         {
     549         [ #  # ]:          0 :           if (ehdr.e_entry != at_entry)
     550                 :            :             return 0;
     551                 :            :         }
     552                 :            :       else
     553                 :            :         {
     554                 :            :           /* It could be a PIE.  */
     555                 :          0 :         }
     556                 :            :     }
     557                 :            : 
     558                 :            :   // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
     559                 :            :   /* Find the vaddr of the DT_DEBUG's d_ptr.  This is the memory
     560                 :            :      address where &r_debug was written at runtime.  */
     561                 :          0 :   GElf_Xword align = mod->dwfl->segment_align;
     562                 :          0 :   GElf_Addr d_val_vaddr = 0;
     563                 :          0 :   size_t phnum;
     564         [ #  # ]:          0 :   if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
     565                 :            :     return 0;
     566                 :            : 
     567         [ #  # ]:          0 :   for (size_t i = 0; i < phnum; ++i)
     568                 :            :     {
     569                 :          0 :       GElf_Phdr phdr_mem;
     570                 :          0 :       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
     571         [ #  # ]:          0 :       if (phdr == NULL)
     572                 :            :         break;
     573                 :            : 
     574   [ #  #  #  #  :          0 :       if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
                   #  # ]
     575                 :          0 :         align = phdr->p_align;
     576                 :            : 
     577         [ #  # ]:          0 :       if (at_phdr != 0
     578         [ #  # ]:          0 :           && phdr->p_type == PT_LOAD
     579         [ #  # ]:          0 :           && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
     580                 :            :         {
     581                 :            :           /* This is the segment that would map the phdrs.
     582                 :            :              If we have an AT_PHDR value, reject this executable
     583                 :            :              if its phdr mapping could not have supplied that.  */
     584         [ #  # ]:          0 :           if (mod->e_type == ET_EXEC)
     585                 :            :             {
     586         [ #  # ]:          0 :               if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
     587                 :          0 :                 return 0;
     588                 :            :             }
     589                 :            :           else
     590                 :            :             {
     591                 :            :               /* It could be a PIE.  If the AT_PHDR value and our
     592                 :            :                  phdr address don't match modulo ALIGN, then this
     593                 :            :                  could not have been the right PIE.  */
     594                 :          0 :               if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
     595         [ #  # ]:          0 :                   != (at_phdr & -align))
     596                 :            :                 return 0;
     597                 :            : 
     598                 :            :               /* Calculate the bias applied to the PIE's p_vaddr values.  */
     599                 :          0 :               GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
     600                 :          0 :                                            + phdr->p_vaddr));
     601                 :            : 
     602                 :            :               /* Final sanity check: if we have an AT_ENTRY value,
     603                 :            :                  reject this PIE unless its biased e_entry matches.  */
     604   [ #  #  #  # ]:          0 :               if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
     605                 :            :                 return 0;
     606                 :            : 
     607                 :            :               /* If we're changing the module's address range,
     608                 :            :                  we've just invalidated the module lookup table.  */
     609         [ #  # ]:          0 :               GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
     610         [ #  # ]:          0 :               if (bias != mod_bias)
     611                 :            :                 {
     612                 :          0 :                   mod->low_addr -= mod_bias;
     613                 :          0 :                   mod->high_addr -= mod_bias;
     614                 :          0 :                   mod->low_addr += bias;
     615                 :          0 :                   mod->high_addr += bias;
     616                 :            : 
     617                 :          0 :                   free (mod->dwfl->lookup_module);
     618                 :          0 :                   mod->dwfl->lookup_module = NULL;
     619                 :            :                 }
     620                 :            :             }
     621                 :            :         }
     622                 :            : 
     623         [ #  # ]:          0 :       if (phdr->p_type == PT_DYNAMIC)
     624                 :            :         {
     625                 :          0 :           Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
     626                 :            :                                                  phdr->p_filesz, ELF_T_DYN);
     627         [ #  # ]:          0 :           if (data == NULL)
     628                 :          0 :             continue;
     629                 :          0 :           const size_t entsize = gelf_fsize (mod->main.elf,
     630                 :            :                                              ELF_T_DYN, 1, EV_CURRENT);
     631                 :          0 :           const size_t n = data->d_size / entsize;
     632         [ #  # ]:          0 :           for (size_t j = 0; j < n; ++j)
     633                 :            :             {
     634                 :          0 :               GElf_Dyn dyn_mem;
     635                 :          0 :               GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
     636   [ #  #  #  # ]:          0 :               if (dyn != NULL && dyn->d_tag == DT_DEBUG)
     637                 :            :                 {
     638                 :          0 :                   d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
     639                 :          0 :                   break;
     640                 :            :                 }
     641                 :            :             }
     642                 :            :         }
     643                 :            :     }
     644                 :            : 
     645         [ #  # ]:          0 :   if (d_val_vaddr != 0)
     646                 :            :     {
     647                 :            :       /* Now we have the final address from which to read &r_debug.  */
     648                 :          0 :       d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
     649                 :            : 
     650                 :          0 :       void *buffer = NULL;
     651                 :          0 :       size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
     652                 :            : 
     653                 :          0 :       int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
     654                 :            : 
     655         [ #  # ]:          0 :       if ((*memory_callback) (mod->dwfl, segndx,
     656                 :            :                               &buffer, &buffer_available,
     657                 :            :                               d_val_vaddr, buffer_available,
     658                 :            :                               memory_callback_arg))
     659                 :            :         {
     660                 :          0 :           const union
     661                 :            :           {
     662                 :            :             Elf32_Addr a32;
     663                 :            :             Elf64_Addr a64;
     664                 :          0 :           } *u = buffer;
     665                 :            : 
     666                 :          0 :           GElf_Addr vaddr;
     667         [ #  # ]:          0 :           if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
     668                 :          0 :             vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
     669         [ #  # ]:          0 :                      ? BE32 (u->a32) : LE32 (u->a32));
     670                 :            :           else
     671                 :          0 :             vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
     672         [ #  # ]:          0 :                      ? BE64 (u->a64) : LE64 (u->a64));
     673                 :            : 
     674                 :          0 :           (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
     675                 :            :                               memory_callback_arg);
     676                 :            : 
     677         [ #  # ]:          0 :           if (*elfclass == ELFCLASSNONE)
     678                 :          0 :             *elfclass = ehdr.e_ident[EI_CLASS];
     679         [ #  # ]:          0 :           else if (*elfclass != ehdr.e_ident[EI_CLASS])
     680                 :          0 :             return 0;
     681                 :            : 
     682         [ #  # ]:          0 :           if (*elfdata == ELFDATANONE)
     683                 :          0 :             *elfdata = ehdr.e_ident[EI_DATA];
     684         [ #  # ]:          0 :           else if (*elfdata != ehdr.e_ident[EI_DATA])
     685                 :            :             return 0;
     686                 :            : 
     687                 :          0 :           return vaddr;
     688                 :            :         }
     689                 :            :     }
     690                 :            : 
     691                 :            :   return 0;
     692                 :            : }
     693                 :            : 
     694                 :            : /* Try to find an existing executable module with a DT_DEBUG.  */
     695                 :            : static GElf_Addr
     696                 :          0 : find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
     697                 :            :                  uint_fast8_t *elfclass, uint_fast8_t *elfdata,
     698                 :            :                  Dwfl_Memory_Callback *memory_callback,
     699                 :            :                  void *memory_callback_arg)
     700                 :            : {
     701         [ #  # ]:          0 :   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
     702         [ #  # ]:          0 :     if (mod->main.elf != NULL)
     703                 :            :       {
     704                 :          0 :         GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
     705                 :            :                                                        elfclass, elfdata,
     706                 :            :                                                        memory_callback,
     707                 :            :                                                        memory_callback_arg);
     708         [ #  # ]:          0 :         if (r_debug_vaddr != 0)
     709                 :          0 :           return r_debug_vaddr;
     710                 :            :       }
     711                 :            : 
     712                 :            :   return 0;
     713                 :            : }
     714                 :            : 
     715                 :            : 
     716                 :            : int
     717                 :         34 : dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
     718                 :            :                       Dwfl_Memory_Callback *memory_callback,
     719                 :            :                       void *memory_callback_arg,
     720                 :            :                       struct r_debug_info *r_debug_info)
     721                 :            : {
     722                 :         34 :   GElf_Addr r_debug_vaddr = 0;
     723                 :            : 
     724                 :         34 :   uint_fast8_t elfclass = ELFCLASSNONE;
     725                 :         34 :   uint_fast8_t elfdata = ELFDATANONE;
     726         [ +  - ]:         34 :   if (likely (auxv != NULL)
     727         [ +  - ]:         34 :       && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
     728                 :            :     {
     729                 :         34 :       GElf_Addr entry = 0;
     730                 :         34 :       GElf_Addr phdr = 0;
     731                 :         34 :       GElf_Xword phent = 0;
     732                 :         34 :       GElf_Xword phnum = 0;
     733                 :            : 
     734                 :            : #define READ_AUXV32(ptr)        read_4ubyte_unaligned_noncvt (ptr)
     735                 :            : #define READ_AUXV64(ptr)        read_8ubyte_unaligned_noncvt (ptr)
     736                 :            : #define AUXV_SCAN(NN, BL) do                                            \
     737                 :            :         {                                                               \
     738                 :            :           const Elf##NN##_auxv_t *av = auxv;                            \
     739                 :            :           for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)         \
     740                 :            :             {                                                           \
     741                 :            :               const char *typep = auxv + i * sizeof (Elf##NN##_auxv_t); \
     742                 :            :               typep += offsetof (Elf##NN##_auxv_t, a_type);             \
     743                 :            :               uint##NN##_t type = READ_AUXV##NN (typep);                \
     744                 :            :               const char *valp = auxv + i * sizeof (Elf##NN##_auxv_t);  \
     745                 :            :               valp += offsetof (Elf##NN##_auxv_t, a_un.a_val);          \
     746                 :            :               uint##NN##_t val = BL##NN (READ_AUXV##NN (valp));         \
     747                 :            :               if (type == BL##NN (AT_ENTRY))                            \
     748                 :            :                 entry = val;                                            \
     749                 :            :               else if (type == BL##NN (AT_PHDR))                        \
     750                 :            :                 phdr = val;                                             \
     751                 :            :               else if (type == BL##NN (AT_PHNUM))                       \
     752                 :            :                 phnum = val;                                            \
     753                 :            :               else if (type == BL##NN (AT_PHENT))                       \
     754                 :            :                 phent = val;                                            \
     755                 :            :               else if (type == BL##NN (AT_PAGESZ))                      \
     756                 :            :                 {                                                       \
     757                 :            :                   if (val > 1                                           \
     758                 :            :                       && (dwfl->segment_align == 0                      \
     759                 :            :                           || val < dwfl->segment_align))                \
     760                 :            :                     dwfl->segment_align = val;                          \
     761                 :            :                 }                                                       \
     762                 :            :             }                                                           \
     763                 :            :         }                                                               \
     764                 :            :       while (0)
     765                 :            : 
     766         [ +  + ]:         34 :       if (elfclass == ELFCLASS32)
     767                 :            :         {
     768         [ +  + ]:          7 :           if (elfdata == ELFDATA2MSB)
     769   [ +  +  +  +  :         73 :             AUXV_SCAN (32, BE);
          +  +  +  +  +  
          +  +  -  +  -  
             -  +  +  + ]
     770                 :            :           else
     771   [ +  +  +  +  :         83 :             AUXV_SCAN (32, LE);
          +  +  +  +  +  
          +  +  -  +  -  
             -  +  +  + ]
     772                 :            :         }
     773                 :            :       else
     774                 :            :         {
     775         [ +  + ]:         27 :           if (elfdata == ELFDATA2MSB)
     776   [ +  +  +  +  :         91 :             AUXV_SCAN (64, BE);
          +  +  +  +  +  
          +  +  -  +  -  
             -  +  +  + ]
     777                 :            :           else
     778   [ +  +  +  +  :        467 :             AUXV_SCAN (64, LE);
          +  +  +  +  +  
          +  +  -  +  -  
             -  +  +  + ]
     779                 :            :         }
     780                 :            : 
     781                 :            :       /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC.  */
     782                 :         34 :       GElf_Addr dyn_vaddr = 0;
     783                 :         34 :       GElf_Xword dyn_filesz = 0;
     784                 :         34 :       GElf_Addr dyn_bias = (GElf_Addr) -1;
     785                 :            : 
     786         [ +  - ]:         34 :       if (phdr != 0 && phnum != 0
     787   [ +  +  -  + ]:         34 :           && ((elfclass == ELFCLASS32 && phent == sizeof (Elf32_Phdr))
     788   [ +  -  +  - ]:         27 :               || (elfclass == ELFCLASS64 && phent == sizeof (Elf64_Phdr))))
     789                 :            :         {
     790                 :         34 :           Dwfl_Module *phdr_mod;
     791                 :         34 :           int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
     792                 :         34 :           Elf_Data in =
     793                 :            :             {
     794                 :            :               .d_type = ELF_T_PHDR,
     795                 :            :               .d_version = EV_CURRENT,
     796                 :         34 :               .d_size = phnum * phent,
     797                 :            :               .d_buf = NULL
     798                 :            :             };
     799                 :         34 :           bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
     800                 :            :                                            &in.d_size, phdr, phnum * phent,
     801                 :            :                                            memory_callback_arg);
     802                 :         34 :           bool in_from_exec = false;
     803         [ +  + ]:         34 :           if (! in_ok
     804         [ +  - ]:          2 :               && dwfl->user_core != NULL
     805         [ +  - ]:          2 :               && dwfl->user_core->executable_for_core != NULL)
     806                 :            :             {
     807                 :            :               /* AUXV -> PHDR -> DYNAMIC
     808                 :            :                  Both AUXV and DYNAMIC should be always present in a core file.
     809                 :            :                  PHDR may be missing in core file, try to read it from
     810                 :            :                  EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
     811                 :            :                  core file.  */
     812                 :            : 
     813                 :          2 :               int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
     814                 :          2 :               Elf *elf;
     815                 :          2 :               Dwfl_Error error = DWFL_E_ERRNO;
     816         [ +  - ]:          2 :               if (fd != -1)
     817                 :          2 :                 error = __libdw_open_file (&fd, &elf, true, false);
     818         [ -  + ]:          2 :               if (error != DWFL_E_NOERROR)
     819                 :            :                 {
     820                 :          0 :                   __libdwfl_seterrno (error);
     821                 :          0 :                   return false;
     822                 :            :                 }
     823                 :          2 :               GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
     824         [ -  + ]:          2 :               if (ehdr == NULL)
     825                 :            :                 {
     826                 :          0 :                   elf_end (elf);
     827                 :          0 :                   close (fd);
     828                 :          0 :                   __libdwfl_seterrno (DWFL_E_LIBELF);
     829                 :          0 :                   return false;
     830                 :            :                 }
     831                 :          2 :               size_t e_phnum;
     832         [ -  + ]:          2 :               if (elf_getphdrnum (elf, &e_phnum) != 0)
     833                 :            :                 {
     834                 :          0 :                   elf_end (elf);
     835                 :          0 :                   close (fd);
     836                 :          0 :                   __libdwfl_seterrno (DWFL_E_LIBELF);
     837                 :          0 :                   return false;
     838                 :            :                 }
     839   [ +  -  -  + ]:          2 :               if (e_phnum != phnum || ehdr->e_phentsize != phent)
     840                 :            :                 {
     841                 :          0 :                   elf_end (elf);
     842                 :          0 :                   close (fd);
     843                 :          0 :                   __libdwfl_seterrno (DWFL_E_BADELF);
     844                 :          0 :                   return false;
     845                 :            :                 }
     846                 :          2 :               off_t off = ehdr->e_phoff;
     847         [ -  + ]:          2 :               assert (in.d_buf == NULL);
     848                 :            :               /* Note this in the !in_ok path.  That means memory_callback
     849                 :            :                  failed.  But the callback might still have reset the d_size
     850                 :            :                  value (to zero).  So explicitly set it here again.  */
     851         [ -  + ]:          2 :               if (unlikely (phnum > SIZE_MAX / phent))
     852                 :            :                 {
     853                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     854                 :          0 :                   return false;
     855                 :            :                 }
     856                 :          2 :               in.d_size = phnum * phent;
     857                 :          2 :               in.d_buf = malloc (in.d_size);
     858         [ -  + ]:          2 :               if (unlikely (in.d_buf == NULL))
     859                 :            :                 {
     860                 :          0 :                   elf_end (elf);
     861                 :          0 :                   close (fd);
     862                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     863                 :          0 :                   return false;
     864                 :            :                 }
     865                 :          2 :               ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off);
     866                 :          2 :               elf_end (elf);
     867                 :          2 :               close (fd);
     868         [ -  + ]:          2 :               if (nread != (ssize_t) in.d_size)
     869                 :            :                 {
     870                 :          0 :                   free (in.d_buf);
     871                 :          0 :                   __libdwfl_seterrno (DWFL_E_ERRNO);
     872                 :          0 :                   return false;
     873                 :            :                 }
     874                 :          2 :               in_ok = true;
     875                 :          2 :               in_from_exec = true;
     876                 :            :             }
     877         [ +  - ]:         34 :           if (in_ok)
     878                 :            :             {
     879         [ -  + ]:         34 :               if (unlikely (phnum > SIZE_MAX / phent))
     880                 :            :                 {
     881                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     882                 :          0 :                   return false;
     883                 :            :                 }
     884                 :         34 :               size_t nbytes = phnum * phent;
     885                 :            :               /* We can only process as many bytes/phnum as there are
     886                 :            :                  in in.d_size. The data might have been truncated.  */
     887         [ -  + ]:         34 :               if (nbytes > in.d_size)
     888                 :            :                 {
     889                 :          0 :                   nbytes = in.d_size;
     890                 :          0 :                   phnum = nbytes / phent;
     891         [ #  # ]:          0 :                   if (phnum == 0)
     892                 :            :                     {
     893                 :          0 :                       __libdwfl_seterrno (DWFL_E_BADELF);
     894                 :          0 :                       return false;
     895                 :            :                     }
     896                 :            :                 }
     897                 :         34 :               void *buf = malloc (nbytes);
     898                 :         34 :               Elf32_Phdr (*p32)[phnum] = buf;
     899                 :         34 :               Elf64_Phdr (*p64)[phnum] = buf;
     900         [ -  + ]:         34 :               if (unlikely (buf == NULL))
     901                 :            :                 {
     902                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     903                 :          0 :                   return false;
     904                 :            :                 }
     905                 :         34 :               Elf_Data out =
     906                 :            :                 {
     907                 :            :                   .d_type = ELF_T_PHDR,
     908                 :            :                   .d_version = EV_CURRENT,
     909                 :            :                   .d_size = nbytes,
     910                 :            :                   .d_buf = buf
     911                 :            :                 };
     912         [ +  + ]:         34 :               if (in.d_size > out.d_size)
     913                 :            :                 {
     914                 :         32 :                   in.d_size = out.d_size;
     915                 :         32 :                   phnum = in.d_size / phent;
     916         [ -  + ]:         32 :                   if (phnum == 0)
     917                 :            :                     {
     918                 :          0 :                       free (buf);
     919                 :          0 :                       __libdwfl_seterrno (DWFL_E_BADELF);
     920                 :          0 :                       return false;
     921                 :            :                     }
     922                 :            :                 }
     923                 :         34 :               bool is32 = (elfclass == ELFCLASS32);
     924                 :         68 :               size_t phdr_align = (is32
     925                 :            :                                    ? __alignof__ (Elf32_Phdr)
     926         [ +  + ]:         34 :                                    : __alignof__ (Elf64_Phdr));
     927         [ +  + ]:         34 :               if (!in_from_exec
     928         [ -  + ]:         32 :                   && ((uintptr_t) in.d_buf & (phdr_align - 1)) != 0)
     929                 :            :                 {
     930                 :          0 :                   memcpy (out.d_buf, in.d_buf, in.d_size);
     931                 :          0 :                   in.d_buf = out.d_buf;
     932                 :            :                 }
     933   [ +  +  +  - ]:         61 :               if (likely ((elfclass == ELFCLASS32
     934                 :            :                            ? elf32_xlatetom : elf64_xlatetom)
     935                 :            :                           (&out, &in, elfdata) != NULL))
     936                 :            :                 {
     937         [ +  + ]:        183 :                   for (size_t i = 0; i < phnum; ++i)
     938                 :            :                     {
     939                 :        340 :                       GElf_Word type = (is32
     940                 :            :                                         ? (*p32)[i].p_type
     941         [ +  + ]:        170 :                                         : (*p64)[i].p_type);
     942                 :        340 :                       GElf_Addr vaddr = (is32
     943                 :         37 :                                          ? (*p32)[i].p_vaddr
     944         [ +  + ]:        170 :                                          : (*p64)[i].p_vaddr);
     945                 :        340 :                       GElf_Xword filesz = (is32
     946                 :         37 :                                            ? (*p32)[i].p_filesz
     947         [ +  + ]:        170 :                                            : (*p64)[i].p_filesz);
     948                 :            : 
     949         [ +  + ]:        170 :                       if (type == PT_PHDR)
     950                 :            :                         {
     951         [ +  - ]:         21 :                           if (dyn_bias == (GElf_Addr) -1
     952                 :            :                               /* Do a sanity check on the putative address.  */
     953                 :         21 :                               && ((vaddr & (dwfl->segment_align - 1))
     954         [ +  - ]:         21 :                                   == (phdr & (dwfl->segment_align - 1))))
     955                 :            :                             {
     956                 :         21 :                               dyn_bias = phdr - vaddr;
     957         [ +  - ]:         21 :                               if (dyn_vaddr != 0)
     958                 :            :                                 break;
     959                 :            :                             }
     960                 :            : 
     961                 :            :                         }
     962         [ +  + ]:        149 :                       else if (type == PT_DYNAMIC)
     963                 :            :                         {
     964                 :         21 :                           dyn_vaddr = vaddr;
     965                 :         21 :                           dyn_filesz = filesz;
     966         [ -  + ]:         21 :                           if (dyn_bias != (GElf_Addr) -1)
     967                 :            :                             break;
     968                 :            :                         }
     969                 :            :                     }
     970                 :            :                 }
     971                 :            : 
     972         [ +  + ]:         34 :               if (in_from_exec)
     973                 :          2 :                 free (in.d_buf);
     974                 :            :               else
     975                 :         32 :                 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
     976                 :            :                                     memory_callback_arg);
     977                 :         34 :               free (buf);
     978                 :            :             }
     979                 :            :           else
     980                 :            :             /* We could not read the executable's phdrs from the
     981                 :            :                memory image.  If we have a presupplied executable,
     982                 :            :                we can still use the AT_PHDR and AT_ENTRY values to
     983                 :            :                verify it, and to adjust its bias if it's a PIE.
     984                 :            : 
     985                 :            :                If there was an ET_EXEC module presupplied that contains
     986                 :            :                the AT_PHDR address, then we only consider that one.
     987                 :            :                We'll either accept it if its phdr location and e_entry
     988                 :            :                make sense or reject it if they don't.  If there is no
     989                 :            :                presupplied ET_EXEC, then look for a presupplied module,
     990                 :            :                which might be a PIE (ET_DYN) that needs its bias adjusted.  */
     991                 :          0 :             r_debug_vaddr = ((phdr_mod == NULL
     992         [ #  # ]:          0 :                               || phdr_mod->main.elf == NULL
     993         [ #  # ]:          0 :                               || phdr_mod->e_type != ET_EXEC)
     994                 :          0 :                              ? find_executable (dwfl, phdr, entry,
     995                 :            :                                                 &elfclass, &elfdata,
     996                 :            :                                                 memory_callback,
     997                 :            :                                                 memory_callback_arg)
     998         [ #  # ]:          0 :                              : consider_executable (phdr_mod, phdr, entry,
     999                 :            :                                                     &elfclass, &elfdata,
    1000                 :            :                                                     memory_callback,
    1001                 :            :                                                     memory_callback_arg));
    1002                 :            :         }
    1003                 :            : 
    1004                 :            :       /* If we found PT_DYNAMIC, search it for DT_DEBUG.  */
    1005         [ +  + ]:         34 :       if (dyn_filesz != 0)
    1006                 :            :         {
    1007         [ +  - ]:         21 :           if (dyn_bias != (GElf_Addr) -1)
    1008                 :         21 :             dyn_vaddr += dyn_bias;
    1009                 :            : 
    1010                 :         21 :           Elf_Data in =
    1011                 :            :             {
    1012                 :            :               .d_type = ELF_T_DYN,
    1013                 :            :               .d_version = EV_CURRENT,
    1014                 :            :               .d_size = dyn_filesz,
    1015                 :            :               .d_buf = NULL
    1016                 :            :             };
    1017                 :         21 :           int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
    1018         [ +  - ]:         21 :           if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
    1019                 :            :                                   dyn_vaddr, dyn_filesz, memory_callback_arg))
    1020                 :            :             {
    1021                 :         42 :               size_t entsize = (elfclass == ELFCLASS32
    1022         [ +  + ]:         21 :                                 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
    1023         [ -  + ]:         21 :               if (unlikely (dyn_filesz > SIZE_MAX / entsize))
    1024                 :            :                 {
    1025                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
    1026                 :          0 :                   return false;
    1027                 :            :                 }
    1028                 :            :               /* We can only process as many bytes as there are in
    1029                 :            :                  in.d_size. The data might have been truncated.  */
    1030                 :         21 :               if (dyn_filesz > in.d_size)
    1031                 :            :                 dyn_filesz = in.d_size;
    1032         [ -  + ]:         21 :               if (dyn_filesz / entsize == 0)
    1033                 :            :                 {
    1034                 :          0 :                   __libdwfl_seterrno (DWFL_E_BADELF);
    1035                 :          0 :                   return false;
    1036                 :            :                 }
    1037                 :         21 :               void *buf = malloc (dyn_filesz);
    1038         [ -  + ]:         21 :               if (unlikely (buf == NULL))
    1039                 :            :                 {
    1040                 :          0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
    1041                 :          0 :                   return false;
    1042                 :            :                 }
    1043                 :         21 :               Elf_Data out =
    1044                 :            :                 {
    1045                 :            :                   .d_type = ELF_T_DYN,
    1046                 :            :                   .d_version = EV_CURRENT,
    1047                 :            :                   .d_size = dyn_filesz,
    1048                 :            :                   .d_buf = buf
    1049                 :            :                 };
    1050         [ +  - ]:         21 :               if (in.d_size > out.d_size)
    1051                 :         21 :                 in.d_size = out.d_size;
    1052                 :         42 :               size_t dyn_align = (elfclass == ELFCLASS32
    1053                 :            :                                   ? __alignof__ (Elf32_Dyn)
    1054         [ +  + ]:         21 :                                   : __alignof__ (Elf64_Dyn));
    1055         [ -  + ]:         21 :               if (((uintptr_t) in.d_buf & (dyn_align - 1)) != 0)
    1056                 :            :                 {
    1057                 :          0 :                   memcpy (out.d_buf, in.d_buf, in.d_size);
    1058                 :          0 :                   in.d_buf = out.d_buf;
    1059                 :            :                 }
    1060   [ +  +  +  - ]:         40 :               if (likely ((elfclass == ELFCLASS32
    1061                 :            :                            ? elf32_xlatetom : elf64_xlatetom)
    1062                 :            :                           (&out, &in, elfdata) != NULL))
    1063                 :            :                 {
    1064                 :            :                   /* We are looking for DT_DEBUG.  */
    1065         [ +  + ]:         21 :                   if (elfclass == ELFCLASS32)
    1066                 :            :                     {
    1067                 :          2 :                       Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = buf;
    1068                 :          2 :                       size_t n = dyn_filesz / sizeof (Elf32_Dyn);
    1069         [ +  - ]:         28 :                       for (size_t i = 0; i < n; ++i)
    1070         [ +  + ]:         28 :                         if ((*d32)[i].d_tag == DT_DEBUG)
    1071                 :            :                           {
    1072                 :          2 :                             r_debug_vaddr = (*d32)[i].d_un.d_val;
    1073                 :          2 :                             break;
    1074                 :            :                           }
    1075                 :            :                     }
    1076                 :            :                   else
    1077                 :            :                     {
    1078                 :         19 :                       Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = buf;
    1079                 :         19 :                       size_t n = dyn_filesz / sizeof (Elf64_Dyn);
    1080         [ +  - ]:        258 :                       for (size_t i = 0; i < n; ++i)
    1081         [ +  + ]:        258 :                         if ((*d64)[i].d_tag == DT_DEBUG)
    1082                 :            :                           {
    1083                 :         19 :                             r_debug_vaddr = (*d64)[i].d_un.d_val;
    1084                 :         19 :                             break;
    1085                 :            :                           }
    1086                 :            :                     }
    1087                 :            :                 }
    1088                 :            : 
    1089                 :         21 :               (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    1090                 :            :                                   memory_callback_arg);
    1091                 :         21 :               free (buf);
    1092                 :            :             }
    1093                 :            :         }
    1094                 :            :     }
    1095                 :            :   else
    1096                 :            :     /* We have to look for a presupplied executable file to determine
    1097                 :            :        the vaddr of its dynamic section and DT_DEBUG therein.  */
    1098                 :          0 :     r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
    1099                 :            :                                      memory_callback, memory_callback_arg);
    1100                 :            : 
    1101         [ +  + ]:         34 :   if (r_debug_vaddr == 0)
    1102                 :            :     return 0;
    1103                 :            : 
    1104                 :            :   /* For following pointers from struct link_map, we will use an
    1105                 :            :      integrated memory access callback that can consult module text
    1106                 :            :      elided from the core file.  This is necessary when the l_name
    1107                 :            :      pointer for the dynamic linker's own entry is a pointer into the
    1108                 :            :      executable's .interp section.  */
    1109                 :         21 :   struct integrated_memory_callback mcb =
    1110                 :            :     {
    1111                 :            :       .memory_callback = memory_callback,
    1112                 :            :       .memory_callback_arg = memory_callback_arg
    1113                 :            :     };
    1114                 :            : 
    1115                 :            :   /* Now we can follow the dynamic linker's library list.  */
    1116                 :         21 :   return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
    1117                 :            :                          &integrated_memory_callback, &mcb, r_debug_info);
    1118                 :            : }
    1119                 :            : INTDEF (dwfl_link_map_report)

Generated by: LCOV version 1.14