LCOV - code coverage report
Current view: top level - libdwfl - link_map.c (source / functions) Hit Total Coverage
Test: elfutils-0.190 Lines: 305 470 64.9 %
Date: 2024-02-02 22:44:22 Functions: 8 10 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 245 428 57.2 %

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

Generated by: LCOV version 1.16