LCOV - code coverage report
Current view: top level - libdwfl - link_map.c (source / functions) Hit Total Coverage
Test: elfutils-0.173 Lines: 265 398 66.6 %
Date: 2018-06-29 23:49:12 Functions: 7 9 77.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13