LCOV - code coverage report
Current view: top level - libdwfl - link_map.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 258 389 66.3 %
Date: 2017-01-05 09:15:16 Functions: 6 8 75.0 %
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 (size_t i, const Elf64_auxv_t (*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             : 
      51         180 :   uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type);
      52         180 :   uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val);
      53             : 
      54         180 :   if (type == BE64 (PROBE_TYPE)
      55           4 :       && val == BE64 (PROBE_VAL64))
      56             :     {
      57           4 :       *elfdata = ELFDATA2MSB;
      58             :       return true;
      59             :     }
      60             : 
      61         352 :   if (type == LE64 (PROBE_TYPE)
      62         176 :       && val == LE64 (PROBE_VAL64))
      63             :     {
      64          20 :       *elfdata = ELFDATA2LSB;
      65             :       return true;
      66             :     }
      67             : 
      68             :   return false;
      69             : }
      70             : 
      71             : #define check64(n) do_check64 (n, a64, elfdata)
      72             : 
      73             : static inline bool
      74             : do_check32 (size_t i, const Elf32_auxv_t (*a32)[], uint_fast8_t *elfdata)
      75             : {
      76             :   /* The AUXV pointer might not even be naturally aligned for 32-bit
      77             :      data, because note payloads in a core file are not aligned.  */
      78             : 
      79         308 :   uint32_t type = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_type);
      80         308 :   uint32_t val = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_un.a_val);
      81             : 
      82         308 :   if (type == BE32 (PROBE_TYPE)
      83           3 :       && val == BE32 (PROBE_VAL32))
      84             :     {
      85           3 :       *elfdata = ELFDATA2MSB;
      86             :       return true;
      87             :     }
      88             : 
      89         610 :   if (type == LE32 (PROBE_TYPE)
      90         305 :       && val == LE32 (PROBE_VAL32))
      91             :     {
      92           3 :       *elfdata = ELFDATA2LSB;
      93             :       return true;
      94             :     }
      95             : 
      96             :   return false;
      97             : }
      98             : 
      99             : #define check32(n) do_check32 (n, a32, elfdata)
     100             : 
     101             : /* Examine an auxv data block and determine its format.
     102             :    Return true iff we figured it out.  */
     103             : static bool
     104          30 : auxv_format_probe (const void *auxv, size_t size,
     105             :                    uint_fast8_t *elfclass, uint_fast8_t *elfdata)
     106             : {
     107          30 :   const Elf32_auxv_t (*a32)[size / sizeof (Elf32_auxv_t)] = (void *) auxv;
     108          30 :   const Elf64_auxv_t (*a64)[size / sizeof (Elf64_auxv_t)] = (void *) auxv;
     109             : 
     110         180 :   for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
     111             :     {
     112         180 :       if (check64 (i))
     113             :         {
     114          24 :           *elfclass = ELFCLASS64;
     115          24 :           return true;
     116             :         }
     117             : 
     118         464 :       if (check32 (i * 2) || check32 (i * 2 + 1))
     119             :         {
     120           6 :           *elfclass = ELFCLASS32;
     121           6 :           return true;
     122             :         }
     123             :     }
     124             : 
     125             :   return false;
     126             : }
     127             : 
     128             : /* This is a Dwfl_Memory_Callback that wraps another memory callback.
     129             :    If the underlying callback cannot fill the data, then this will
     130             :    fall back to fetching data from module files.  */
     131             : 
     132             : struct integrated_memory_callback
     133             : {
     134             :   Dwfl_Memory_Callback *memory_callback;
     135             :   void *memory_callback_arg;
     136             :   void *buffer;
     137             : };
     138             : 
     139             : static bool
     140         494 : integrated_memory_callback (Dwfl *dwfl, int ndx,
     141             :                                void **buffer, size_t *buffer_available,
     142             :                                GElf_Addr vaddr,
     143             :                                size_t minread,
     144             :                                void *arg)
     145             : {
     146         494 :   struct integrated_memory_callback *info = arg;
     147             : 
     148         494 :   if (ndx == -1)
     149             :     {
     150             :       /* Called for cleanup.  */
     151         256 :       if (info->buffer != NULL)
     152             :         {
     153             :           /* The last probe buffer came from the underlying callback.
     154             :              Let it do its cleanup.  */
     155         197 :           assert (*buffer == info->buffer); /* XXX */
     156         197 :           *buffer = info->buffer;
     157         197 :           info->buffer = NULL;
     158         197 :           return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
     159             :                                            vaddr, minread,
     160             :                                            info->memory_callback_arg);
     161             :         }
     162          59 :       *buffer = NULL;
     163          59 :       *buffer_available = 0;
     164          59 :       return false;
     165             :     }
     166             : 
     167         238 :   if (*buffer != NULL)
     168             :     /* For a final-read request, we only use the underlying callback.  */
     169           0 :     return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
     170             :                                      vaddr, minread, info->memory_callback_arg);
     171             : 
     172             :   /* Let the underlying callback try to fill this request.  */
     173         238 :   if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
     174             :                                 vaddr, minread, info->memory_callback_arg))
     175             :     {
     176         197 :       *buffer = info->buffer;
     177         197 :       return true;
     178             :     }
     179             : 
     180             :   /* Now look for module text covering this address.  */
     181             : 
     182             :   Dwfl_Module *mod;
     183          41 :   (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
     184          41 :   if (mod == NULL)
     185             :     return false;
     186             : 
     187             :   Dwarf_Addr bias;
     188           0 :   Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
     189           0 :   if (unlikely (scn == NULL))
     190             :     {
     191             : #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
     192             :       /* If we have no sections we can try to fill it from the module file
     193             :          based on its phdr mappings.  */
     194             :       if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
     195             :         return INTUSE(dwfl_elf_phdr_memory_callback)
     196             :           (dwfl, 0, buffer, buffer_available,
     197             :            vaddr - mod->main.bias, minread, mod->main.elf);
     198             : #endif
     199             :       return false;
     200             :     }
     201             : 
     202           0 :   Elf_Data *data = elf_rawdata (scn, NULL);
     203           0 :   if (unlikely (data == NULL))
     204             :     // XXX throw error?
     205             :     return false;
     206             : 
     207           0 :   if (unlikely (data->d_size < vaddr))
     208             :     return false;
     209             : 
     210             :   /* Provide as much data as we have.  */
     211           0 :   void *contents = data->d_buf + vaddr;
     212           0 :   size_t avail = data->d_size - vaddr;
     213           0 :   if (unlikely (avail < minread))
     214             :     return false;
     215             : 
     216             :   /* If probing for a string, make sure it's terminated.  */
     217           0 :   if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
     218             :     return false;
     219             : 
     220             :   /* We have it! */
     221           0 :   *buffer = contents;
     222           0 :   *buffer_available = avail;
     223           0 :   return true;
     224             : }
     225             : 
     226             : static size_t
     227             : addrsize (uint_fast8_t elfclass)
     228             : {
     229         151 :   return elfclass * 4;
     230             : }
     231             : 
     232             : /* Report a module for each struct link_map in the linked list at r_map
     233             :    in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
     234             :    see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
     235             :    modules get added to DWFL, caller has to add them from filled in
     236             :    R_DEBUG_INFO.
     237             : 
     238             :    For each link_map entry, if an existing module resides at its address,
     239             :    this just modifies that module's name and suggested file name.  If
     240             :    no such module exists, this calls dwfl_report_elf on the l_name string.
     241             : 
     242             :    Returns the number of modules found, or -1 for errors.  */
     243             : 
     244             : static int
     245          21 : report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
     246             :                 Dwfl *dwfl, GElf_Addr r_debug_vaddr,
     247             :                 Dwfl_Memory_Callback *memory_callback,
     248             :                 void *memory_callback_arg,
     249             :                 struct r_debug_info *r_debug_info)
     250             : {
     251             :   /* Skip r_version, to aligned r_map field.  */
     252          42 :   GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
     253             : 
     254          21 :   void *buffer = NULL;
     255          21 :   size_t buffer_available = 0;
     256             :   inline int release_buffer (int result)
     257             :   {
     258         337 :     if (buffer != NULL)
     259         197 :       (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
     260             :                                  memory_callback_arg);
     261             :     return result;
     262             :   }
     263             : 
     264             :   GElf_Addr addrs[4];
     265         130 :   inline bool read_addrs (GElf_Addr vaddr, size_t n)
     266             :   {
     267         260 :     size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
     268             : 
     269             :     /* Read a new buffer if the old one doesn't cover these words.  */
     270         130 :     if (buffer == NULL
     271          21 :         || vaddr < read_vaddr
     272          19 :         || vaddr - read_vaddr + nb > buffer_available)
     273             :       {
     274         111 :         release_buffer (0);
     275             : 
     276         111 :         read_vaddr = vaddr;
     277         111 :         int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
     278         111 :         if (unlikely (segndx < 0)
     279         111 :             || unlikely (! (*memory_callback) (dwfl, segndx,
     280             :                                                &buffer, &buffer_available,
     281             :                                                vaddr, nb, memory_callback_arg)))
     282             :           return true;
     283             :       }
     284             : 
     285         130 :     Elf32_Addr (*a32)[n] = vaddr - read_vaddr + buffer;
     286         130 :     Elf64_Addr (*a64)[n] = (void *) a32;
     287             : 
     288         130 :     if (elfclass == ELFCLASS32)
     289             :       {
     290          14 :         if (elfdata == ELFDATA2MSB)
     291          25 :           for (size_t i = 0; i < n; ++i)
     292          50 :             addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
     293             :         else
     294          25 :           for (size_t i = 0; i < n; ++i)
     295          25 :             addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
     296             :       }
     297             :     else
     298             :       {
     299         116 :         if (elfdata == ELFDATA2MSB)
     300          18 :           for (size_t i = 0; i < n; ++i)
     301          36 :             addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
     302             :         else
     303         389 :           for (size_t i = 0; i < n; ++i)
     304         389 :             addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
     305             :       }
     306             : 
     307             :     return false;
     308             :   }
     309             : 
     310          21 :   if (unlikely (read_addrs (read_vaddr, 1)))
     311             :     return release_buffer (-1);
     312             : 
     313          21 :   GElf_Addr next = addrs[0];
     314             : 
     315          21 :   Dwfl_Module **lastmodp = &dwfl->modulelist;
     316          21 :   int result = 0;
     317             : 
     318             :   /* There can't be more elements in the link_map list than there are
     319             :      segments.  DWFL->lookup_elts is probably twice that number, so it
     320             :      is certainly above the upper bound.  If we iterate too many times,
     321             :      there must be a loop in the pointers due to link_map clobberation.  */
     322          21 :   size_t iterations = 0;
     323         151 :   while (next != 0 && ++iterations < dwfl->lookup_elts)
     324             :     {
     325         109 :       if (read_addrs (next, 4))
     326             :         return release_buffer (-1);
     327             : 
     328             :       /* Unused: l_addr is the difference between the address in memory
     329             :          and the ELF file when the core was created. We need to
     330             :          recalculate the difference below because the ELF file we use
     331             :          might be differently pre-linked.  */
     332             :       // GElf_Addr l_addr = addrs[0];
     333         109 :       GElf_Addr l_name = addrs[1];
     334         109 :       GElf_Addr l_ld = addrs[2];
     335         109 :       next = addrs[3];
     336             : 
     337             :       /* If a clobbered or truncated memory image has no useful pointer,
     338             :          just skip this element.  */
     339         109 :       if (l_ld == 0)
     340           1 :         continue;
     341             : 
     342             :       /* Fetch the string at the l_name address.  */
     343         108 :       const char *name = NULL;
     344         108 :       if (buffer != NULL
     345         108 :           && read_vaddr <= l_name
     346          14 :           && l_name + 1 - read_vaddr < buffer_available
     347           1 :           && memchr (l_name - read_vaddr + buffer, '\0',
     348           1 :                      buffer_available - (l_name - read_vaddr)) != NULL)
     349             :         name = l_name - read_vaddr + buffer;
     350             :       else
     351             :         {
     352         107 :           release_buffer (0);
     353         107 :           read_vaddr = l_name;
     354         107 :           int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
     355         107 :           if (likely (segndx >= 0)
     356         107 :               && (*memory_callback) (dwfl, segndx,
     357             :                                      &buffer, &buffer_available,
     358             :                                      l_name, 0, memory_callback_arg))
     359          67 :             name = buffer;
     360             :         }
     361             : 
     362         108 :       if (name != NULL && name[0] == '\0')
     363           0 :         name = NULL;
     364             : 
     365         108 :       if (iterations == 1
     366          19 :           && dwfl->user_core != NULL
     367          16 :           && dwfl->user_core->executable_for_core != NULL)
     368          16 :         name = dwfl->user_core->executable_for_core;
     369             : 
     370         108 :       struct r_debug_info_module *r_debug_info_module = NULL;
     371         108 :       if (r_debug_info != NULL)
     372             :         {
     373             :           /* Save link map information about valid shared library (or
     374             :              executable) which has not been found on disk.  */
     375         108 :           const char *name1 = name == NULL ? "" : name;
     376         108 :           r_debug_info_module = malloc (sizeof (*r_debug_info_module)
     377         108 :                                         + strlen (name1) + 1);
     378         108 :           if (unlikely (r_debug_info_module == NULL))
     379             :             return release_buffer (result);
     380         108 :           r_debug_info_module->fd = -1;
     381         108 :           r_debug_info_module->elf = NULL;
     382         108 :           r_debug_info_module->l_ld = l_ld;
     383         108 :           r_debug_info_module->start = 0;
     384         108 :           r_debug_info_module->end = 0;
     385         108 :           r_debug_info_module->disk_file_has_build_id = false;
     386         108 :           strcpy (r_debug_info_module->name, name1);
     387         108 :           r_debug_info_module->next = r_debug_info->module;
     388         108 :           r_debug_info->module = r_debug_info_module;
     389             :         }
     390             : 
     391         108 :       Dwfl_Module *mod = NULL;
     392         108 :       if (name != NULL)
     393             :         {
     394             :           /* This code is mostly inlined dwfl_report_elf.  */
     395             :           // XXX hook for sysroot
     396          84 :           int fd = open (name, O_RDONLY);
     397          84 :           if (fd >= 0)
     398             :             {
     399             :               Elf *elf;
     400          82 :               Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
     401             :               GElf_Addr elf_dynamic_vaddr;
     402          82 :               if (error == DWFL_E_NOERROR
     403          82 :                   && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
     404             :                 {
     405             :                   const void *build_id_bits;
     406             :                   GElf_Addr build_id_elfaddr;
     407             :                   int build_id_len;
     408          82 :                   bool valid = true;
     409             : 
     410          82 :                   if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
     411             :                                                    &build_id_elfaddr,
     412             :                                                    &build_id_len) > 0
     413          79 :                       && build_id_elfaddr != 0)
     414             :                     {
     415          79 :                       if (r_debug_info_module != NULL)
     416          79 :                         r_debug_info_module->disk_file_has_build_id = true;
     417          79 :                       GElf_Addr build_id_vaddr = (build_id_elfaddr
     418          79 :                                                   - elf_dynamic_vaddr + l_ld);
     419             : 
     420          79 :                       release_buffer (0);
     421          79 :                       int segndx = INTUSE(dwfl_addrsegment) (dwfl,
     422             :                                                              build_id_vaddr,
     423             :                                                              NULL);
     424          79 :                       if (! (*memory_callback) (dwfl, segndx,
     425             :                                                 &buffer, &buffer_available,
     426             :                                                 build_id_vaddr, build_id_len,
     427             :                                                 memory_callback_arg))
     428             :                         {
     429             :                           /* File has valid build-id which cannot be read from
     430             :                              memory.  This happens for core files without bit 4
     431             :                              (0x10) set in Linux /proc/PID/coredump_filter.  */
     432             :                         }
     433             :                       else
     434             :                         {
     435          19 :                           if (memcmp (build_id_bits, buffer, build_id_len) != 0)
     436             :                             /* File has valid build-id which does not match
     437             :                                the one in memory.  */
     438           4 :                             valid = false;
     439             :                           release_buffer (0);
     440             :                         }
     441             :                     }
     442             : 
     443          82 :                   if (valid)
     444             :                     {
     445             :                       // It is like l_addr but it handles differently prelinked
     446             :                       // files at core dumping vs. core loading time.
     447          78 :                       GElf_Addr base = l_ld - elf_dynamic_vaddr;
     448          78 :                       if (r_debug_info_module == NULL)
     449             :                         {
     450             :                           // XXX hook for sysroot
     451           0 :                           mod = __libdwfl_report_elf (dwfl, basename (name),
     452             :                                                       name, fd, elf, base,
     453             :                                                       true, true);
     454           0 :                           if (mod != NULL)
     455             :                             {
     456           0 :                               elf = NULL;
     457           0 :                               fd = -1;
     458             :                             }
     459             :                         }
     460          78 :                       else if (__libdwfl_elf_address_range (elf, base, true,
     461             :                                                             true, NULL, NULL,
     462             :                                                     &r_debug_info_module->start,
     463             :                                                     &r_debug_info_module->end,
     464             :                                                             NULL, NULL))
     465             :                         {
     466          78 :                           r_debug_info_module->elf = elf;
     467          78 :                           r_debug_info_module->fd = fd;
     468          78 :                           elf = NULL;
     469          78 :                           fd = -1;
     470             :                         }
     471             :                     }
     472          82 :                   if (elf != NULL)
     473           4 :                     elf_end (elf);
     474          82 :                   if (fd != -1)
     475           4 :                     close (fd);
     476             :                 }
     477             :             }
     478             :         }
     479             : 
     480         108 :       if (mod != NULL)
     481             :         {
     482           0 :           ++result;
     483             : 
     484             :           /* Move this module to the end of the list, so that we end
     485             :              up with a list in the same order as the link_map chain.  */
     486           0 :           if (mod->next != NULL)
     487             :             {
     488           0 :               if (*lastmodp != mod)
     489             :                 {
     490           0 :                   lastmodp = &dwfl->modulelist;
     491           0 :                   while (*lastmodp != mod)
     492           0 :                     lastmodp = &(*lastmodp)->next;
     493             :                 }
     494           0 :               *lastmodp = mod->next;
     495           0 :               mod->next = NULL;
     496           0 :               while (*lastmodp != NULL)
     497           0 :                 lastmodp = &(*lastmodp)->next;
     498           0 :               *lastmodp = mod;
     499             :             }
     500             : 
     501           0 :           lastmodp = &mod->next;
     502             :         }
     503             :     }
     504             : 
     505             :   return release_buffer (result);
     506             : }
     507             : 
     508             : static GElf_Addr
     509           0 : consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
     510             :                      uint_fast8_t *elfclass, uint_fast8_t *elfdata,
     511             :                      Dwfl_Memory_Callback *memory_callback,
     512             :                      void *memory_callback_arg)
     513             : {
     514             :   GElf_Ehdr ehdr;
     515           0 :   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
     516             :     return 0;
     517             : 
     518           0 :   if (at_entry != 0)
     519             :     {
     520             :       /* If we have an AT_ENTRY value, reject this executable if
     521             :          its entry point address could not have supplied that.  */
     522             : 
     523           0 :       if (ehdr.e_entry == 0)
     524             :         return 0;
     525             : 
     526           0 :       if (mod->e_type == ET_EXEC)
     527             :         {
     528           0 :           if (ehdr.e_entry != at_entry)
     529             :             return 0;
     530             :         }
     531             :       else
     532             :         {
     533             :           /* It could be a PIE.  */
     534             :         }
     535             :     }
     536             : 
     537             :   // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
     538             :   /* Find the vaddr of the DT_DEBUG's d_ptr.  This is the memory
     539             :      address where &r_debug was written at runtime.  */
     540           0 :   GElf_Xword align = mod->dwfl->segment_align;
     541           0 :   GElf_Addr d_val_vaddr = 0;
     542             :   size_t phnum;
     543           0 :   if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
     544             :     return 0;
     545             : 
     546           0 :   for (size_t i = 0; i < phnum; ++i)
     547             :     {
     548             :       GElf_Phdr phdr_mem;
     549           0 :       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
     550           0 :       if (phdr == NULL)
     551             :         break;
     552             : 
     553           0 :       if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
     554           0 :         align = phdr->p_align;
     555             : 
     556           0 :       if (at_phdr != 0
     557           0 :           && phdr->p_type == PT_LOAD
     558           0 :           && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
     559             :         {
     560             :           /* This is the segment that would map the phdrs.
     561             :              If we have an AT_PHDR value, reject this executable
     562             :              if its phdr mapping could not have supplied that.  */
     563           0 :           if (mod->e_type == ET_EXEC)
     564             :             {
     565           0 :               if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
     566           0 :                 return 0;
     567             :             }
     568             :           else
     569             :             {
     570             :               /* It could be a PIE.  If the AT_PHDR value and our
     571             :                  phdr address don't match modulo ALIGN, then this
     572             :                  could not have been the right PIE.  */
     573           0 :               if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
     574           0 :                   != (at_phdr & -align))
     575             :                 return 0;
     576             : 
     577             :               /* Calculate the bias applied to the PIE's p_vaddr values.  */
     578           0 :               GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
     579           0 :                                            + phdr->p_vaddr));
     580             : 
     581             :               /* Final sanity check: if we have an AT_ENTRY value,
     582             :                  reject this PIE unless its biased e_entry matches.  */
     583           0 :               if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
     584             :                 return 0;
     585             : 
     586             :               /* If we're changing the module's address range,
     587             :                  we've just invalidated the module lookup table.  */
     588           0 :               GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
     589           0 :               if (bias != mod_bias)
     590             :                 {
     591           0 :                   mod->low_addr -= mod_bias;
     592           0 :                   mod->high_addr -= mod_bias;
     593           0 :                   mod->low_addr += bias;
     594           0 :                   mod->high_addr += bias;
     595             : 
     596           0 :                   free (mod->dwfl->lookup_module);
     597           0 :                   mod->dwfl->lookup_module = NULL;
     598             :                 }
     599             :             }
     600             :         }
     601             : 
     602           0 :       if (phdr->p_type == PT_DYNAMIC)
     603             :         {
     604           0 :           Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
     605             :                                                  phdr->p_filesz, ELF_T_DYN);
     606           0 :           if (data == NULL)
     607           0 :             continue;
     608           0 :           const size_t entsize = gelf_fsize (mod->main.elf,
     609             :                                              ELF_T_DYN, 1, EV_CURRENT);
     610           0 :           const size_t n = data->d_size / entsize;
     611           0 :           for (size_t j = 0; j < n; ++j)
     612             :             {
     613             :               GElf_Dyn dyn_mem;
     614           0 :               GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
     615           0 :               if (dyn != NULL && dyn->d_tag == DT_DEBUG)
     616             :                 {
     617           0 :                   d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
     618           0 :                   break;
     619             :                 }
     620             :             }
     621             :         }
     622             :     }
     623             : 
     624           0 :   if (d_val_vaddr != 0)
     625             :     {
     626             :       /* Now we have the final address from which to read &r_debug.  */
     627           0 :       d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
     628             : 
     629           0 :       void *buffer = NULL;
     630           0 :       size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
     631             : 
     632           0 :       int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
     633             : 
     634           0 :       if ((*memory_callback) (mod->dwfl, segndx,
     635             :                               &buffer, &buffer_available,
     636             :                               d_val_vaddr, buffer_available,
     637             :                               memory_callback_arg))
     638             :         {
     639             :           const union
     640             :           {
     641             :             Elf32_Addr a32;
     642             :             Elf64_Addr a64;
     643           0 :           } *u = buffer;
     644             : 
     645             :           GElf_Addr vaddr;
     646           0 :           if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
     647           0 :             vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
     648           0 :                      ? BE32 (u->a32) : LE32 (u->a32));
     649             :           else
     650           0 :             vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
     651           0 :                      ? BE64 (u->a64) : LE64 (u->a64));
     652             : 
     653           0 :           (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
     654             :                               memory_callback_arg);
     655             : 
     656           0 :           if (*elfclass == ELFCLASSNONE)
     657           0 :             *elfclass = ehdr.e_ident[EI_CLASS];
     658           0 :           else if (*elfclass != ehdr.e_ident[EI_CLASS])
     659           0 :             return 0;
     660             : 
     661           0 :           if (*elfdata == ELFDATANONE)
     662           0 :             *elfdata = ehdr.e_ident[EI_DATA];
     663           0 :           else if (*elfdata != ehdr.e_ident[EI_DATA])
     664             :             return 0;
     665             : 
     666             :           return vaddr;
     667             :         }
     668             :     }
     669             : 
     670             :   return 0;
     671             : }
     672             : 
     673             : /* Try to find an existing executable module with a DT_DEBUG.  */
     674             : static GElf_Addr
     675           0 : find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
     676             :                  uint_fast8_t *elfclass, uint_fast8_t *elfdata,
     677             :                  Dwfl_Memory_Callback *memory_callback,
     678             :                  void *memory_callback_arg)
     679             : {
     680           0 :   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
     681           0 :     if (mod->main.elf != NULL)
     682             :       {
     683           0 :         GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
     684             :                                                        elfclass, elfdata,
     685             :                                                        memory_callback,
     686             :                                                        memory_callback_arg);
     687           0 :         if (r_debug_vaddr != 0)
     688             :           return r_debug_vaddr;
     689             :       }
     690             : 
     691             :   return 0;
     692             : }
     693             : 
     694             : 
     695             : int
     696          30 : dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
     697             :                       Dwfl_Memory_Callback *memory_callback,
     698             :                       void *memory_callback_arg,
     699             :                       struct r_debug_info *r_debug_info)
     700             : {
     701          30 :   GElf_Addr r_debug_vaddr = 0;
     702             : 
     703          30 :   uint_fast8_t elfclass = ELFCLASSNONE;
     704          30 :   uint_fast8_t elfdata = ELFDATANONE;
     705          30 :   if (likely (auxv != NULL)
     706          30 :       && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
     707             :     {
     708          30 :       GElf_Addr entry = 0;
     709          30 :       GElf_Addr phdr = 0;
     710          30 :       GElf_Xword phent = 0;
     711          30 :       GElf_Xword phnum = 0;
     712             : 
     713             : #define READ_AUXV32(ptr)        read_4ubyte_unaligned_noncvt (ptr)
     714             : #define READ_AUXV64(ptr)        read_8ubyte_unaligned_noncvt (ptr)
     715             : #define AUXV_SCAN(NN, BL) do                                            \
     716             :         {                                                               \
     717             :           const Elf##NN##_auxv_t *av = auxv;                            \
     718             :           for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)         \
     719             :             {                                                           \
     720             :               uint##NN##_t type = READ_AUXV##NN (&av[i].a_type);        \
     721             :               uint##NN##_t val = BL##NN (READ_AUXV##NN (&av[i].a_un.a_val)); \
     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          30 :       if (elfclass == ELFCLASS32)
     742             :         {
     743           6 :           if (elfdata == ELFDATA2MSB)
     744         138 :             AUXV_SCAN (32, BE);
     745             :           else
     746          59 :             AUXV_SCAN (32, LE);
     747             :         }
     748             :       else
     749             :         {
     750          24 :           if (elfdata == ELFDATA2MSB)
     751         174 :             AUXV_SCAN (64, BE);
     752             :           else
     753         380 :             AUXV_SCAN (64, LE);
     754             :         }
     755             : 
     756             :       /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC.  */
     757          30 :       GElf_Addr dyn_vaddr = 0;
     758          30 :       GElf_Xword dyn_filesz = 0;
     759          30 :       GElf_Addr dyn_bias = (GElf_Addr) -1;
     760             : 
     761         148 :       inline bool consider_phdr (GElf_Word type,
     762             :                                  GElf_Addr vaddr, GElf_Xword filesz)
     763             :       {
     764         148 :         switch (type)
     765             :           {
     766             :           case PT_PHDR:
     767          21 :             if (dyn_bias == (GElf_Addr) -1
     768             :                 /* Do a sanity check on the putative address.  */
     769          42 :                 && ((vaddr & (dwfl->segment_align - 1))
     770          42 :                     == (phdr & (dwfl->segment_align - 1))))
     771             :               {
     772          21 :                 dyn_bias = phdr - vaddr;
     773          21 :                 return dyn_vaddr != 0;
     774             :               }
     775             :             break;
     776             : 
     777             :           case PT_DYNAMIC:
     778          21 :             dyn_vaddr = vaddr;
     779          21 :             dyn_filesz = filesz;
     780          21 :             return dyn_bias != (GElf_Addr) -1;
     781             :           }
     782             : 
     783             :         return false;
     784             :       }
     785             : 
     786          30 :       if (phdr != 0 && phnum != 0)
     787             :         {
     788             :           Dwfl_Module *phdr_mod;
     789          30 :           int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
     790          60 :           Elf_Data in =
     791             :             {
     792             :               .d_type = ELF_T_PHDR,
     793             :               .d_version = EV_CURRENT,
     794          30 :               .d_size = phnum * phent,
     795             :               .d_buf = NULL
     796             :             };
     797          30 :           bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
     798             :                                            &in.d_size, phdr, phnum * phent,
     799             :                                            memory_callback_arg);
     800          30 :           bool in_from_exec = false;
     801          30 :           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           2 :               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          30 :           if (in_ok)
     871             :             {
     872          30 :               if (unlikely (phnum > SIZE_MAX / phent))
     873             :                 {
     874           0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     875           0 :                   return false;
     876             :                 }
     877          30 :               size_t nbytes = phnum * phent;
     878          30 :               void *buf = malloc (nbytes);
     879          30 :               Elf32_Phdr (*p32)[phnum] = buf;
     880          30 :               Elf64_Phdr (*p64)[phnum] = buf;
     881          30 :               if (unlikely (buf == NULL))
     882             :                 {
     883           0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     884           0 :                   return false;
     885             :                 }
     886          30 :               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          30 :               in.d_size = out.d_size;
     894          30 :               if (likely ((elfclass == ELFCLASS32
     895             :                            ? elf32_xlatetom : elf64_xlatetom)
     896             :                           (&out, &in, elfdata) != NULL))
     897             :                 {
     898             :                   /* We are looking for PT_DYNAMIC.  */
     899          30 :                   if (elfclass == ELFCLASS32)
     900             :                     {
     901          29 :                       for (size_t i = 0; i < phnum; ++i)
     902          62 :                         if (consider_phdr ((*p32)[i].p_type,
     903          31 :                                            (*p32)[i].p_vaddr,
     904          31 :                                            (*p32)[i].p_filesz))
     905             :                           break;
     906             :                     }
     907             :                   else
     908             :                     {
     909          98 :                       for (size_t i = 0; i < phnum; ++i)
     910         117 :                         if (consider_phdr ((*p64)[i].p_type,
     911             :                                            (*p64)[i].p_vaddr,
     912             :                                            (*p64)[i].p_filesz))
     913             :                           break;
     914             :                     }
     915             :                 }
     916             : 
     917          30 :               if (in_from_exec)
     918           2 :                 free (in.d_buf);
     919             :               else
     920          28 :                 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
     921             :                                     memory_callback_arg);
     922          30 :               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          30 :       if (dyn_filesz != 0)
     951             :         {
     952          21 :           if (dyn_bias != (GElf_Addr) -1)
     953          21 :             dyn_vaddr += dyn_bias;
     954             : 
     955          21 :           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          21 :           int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
     963          21 :           if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
     964             :                                   dyn_vaddr, dyn_filesz, memory_callback_arg))
     965             :             {
     966          21 :               void *buf = malloc (dyn_filesz);
     967          21 :               Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = buf;
     968          21 :               Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = buf;
     969          21 :               if (unlikely (buf == NULL))
     970             :                 {
     971           0 :                   __libdwfl_seterrno (DWFL_E_NOMEM);
     972           0 :                   return false;
     973             :                 }
     974          21 :               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          21 :               in.d_size = out.d_size;
     982          21 :               if (likely ((elfclass == ELFCLASS32
     983             :                            ? elf32_xlatetom : elf64_xlatetom)
     984             :                           (&out, &in, elfdata) != NULL))
     985             :                 {
     986             :                   /* We are looking for DT_DEBUG.  */
     987          21 :                   if (elfclass == ELFCLASS32)
     988             :                     {
     989           2 :                       size_t n = dyn_filesz / sizeof (Elf32_Dyn);
     990          28 :                       for (size_t i = 0; i < n; ++i)
     991          28 :                         if ((*d32)[i].d_tag == DT_DEBUG)
     992             :                           {
     993           2 :                             r_debug_vaddr = (*d32)[i].d_un.d_val;
     994           2 :                             break;
     995             :                           }
     996             :                     }
     997             :                   else
     998             :                     {
     999          19 :                       size_t n = dyn_filesz / sizeof (Elf64_Dyn);
    1000         258 :                       for (size_t i = 0; i < n; ++i)
    1001         258 :                         if ((*d64)[i].d_tag == DT_DEBUG)
    1002             :                           {
    1003          19 :                             r_debug_vaddr = (*d64)[i].d_un.d_val;
    1004          19 :                             break;
    1005             :                           }
    1006             :                     }
    1007             :                 }
    1008             : 
    1009          21 :               (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
    1010             :                                   memory_callback_arg);
    1011          21 :               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          30 :   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          21 :   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          21 :   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.12