LCOV - code coverage report
Current view: top level - libelf - elf_begin.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 82.1 % 458 376
Test Date: 2025-08-30 14:31:09 Functions: 100.0 % 12 12
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 68.3 % 322 220

             Branch data     Line data    Source code
       1                 :             : /* Create descriptor for processing file.
       2                 :             :    Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
       3                 :             :    Copyright (C) 2021, 2022 Mark J. Wielaard <mark@klomp.org>
       4                 :             :    This file is part of elfutils.
       5                 :             :    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
       6                 :             : 
       7                 :             :    This file is free software; you can redistribute it and/or modify
       8                 :             :    it under the terms of either
       9                 :             : 
      10                 :             :      * the GNU Lesser General Public License as published by the Free
      11                 :             :        Software Foundation; either version 3 of the License, or (at
      12                 :             :        your option) any later version
      13                 :             : 
      14                 :             :    or
      15                 :             : 
      16                 :             :      * the GNU General Public License as published by the Free
      17                 :             :        Software Foundation; either version 2 of the License, or (at
      18                 :             :        your option) any later version
      19                 :             : 
      20                 :             :    or both in parallel, as here.
      21                 :             : 
      22                 :             :    elfutils is distributed in the hope that it will be useful, but
      23                 :             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      24                 :             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      25                 :             :    General Public License for more details.
      26                 :             : 
      27                 :             :    You should have received copies of the GNU General Public License and
      28                 :             :    the GNU Lesser General Public License along with this program.  If
      29                 :             :    not, see <http://www.gnu.org/licenses/>.  */
      30                 :             : 
      31                 :             : #ifdef HAVE_CONFIG_H
      32                 :             : # include <config.h>
      33                 :             : #endif
      34                 :             : 
      35                 :             : #include <assert.h>
      36                 :             : #include <ctype.h>
      37                 :             : #include <errno.h>
      38                 :             : #include <fcntl.h>
      39                 :             : #include <stdbool.h>
      40                 :             : #include <stddef.h>
      41                 :             : #include <stdint.h>
      42                 :             : #include <string.h>
      43                 :             : #include <sys/stat.h>
      44                 :             : 
      45                 :             : #include "libelfP.h"
      46                 :             : #include "common.h"
      47                 :             : 
      48                 :             : 
      49                 :             : /* Create descriptor for archive in memory.  */
      50                 :             : static inline Elf *
      51                 :         342 : file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
      52                 :             :               Elf_Cmd cmd, Elf *parent)
      53                 :             : {
      54                 :         342 :   Elf *elf;
      55                 :             : 
      56                 :             :   /* Create a descriptor.  */
      57                 :         342 :   elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
      58                 :             :                       ELF_K_AR, 0);
      59         [ +  - ]:         342 :   if (elf != NULL)
      60                 :             :     {
      61                 :             :       /* We don't read all the symbol tables in advance.  All this will
      62                 :             :          happen on demand.  */
      63                 :         342 :       elf->state.ar.offset = offset + SARMAG;
      64                 :             : 
      65                 :         342 :       elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
      66                 :             :     }
      67                 :             : 
      68                 :         342 :   return elf;
      69                 :             : }
      70                 :             : 
      71                 :             : 
      72                 :             : static size_t
      73                 :       32234 : get_shnum (void *map_address, unsigned char *e_ident, int fildes,
      74                 :             :            int64_t offset, size_t maxsize)
      75                 :             : {
      76                 :       32234 :   size_t result;
      77                 :       32234 :   union
      78                 :             :   {
      79                 :             :     Elf32_Ehdr *e32;
      80                 :             :     Elf64_Ehdr *e64;
      81                 :             :     void *p;
      82                 :             :   } ehdr;
      83                 :       32234 :   union
      84                 :             :   {
      85                 :             :     Elf32_Ehdr e32;
      86                 :             :     Elf64_Ehdr e64;
      87                 :             :   } ehdr_mem;
      88                 :       32234 :   bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
      89                 :             : 
      90         [ +  - ]:       32234 :   if ((is32 && maxsize < sizeof (Elf32_Ehdr))
      91         [ -  + ]:       32234 :       || (!is32 && maxsize < sizeof (Elf64_Ehdr)))
      92                 :             :     {
      93                 :           0 :        __libelf_seterrno (ELF_E_INVALID_ELF);
      94                 :           0 :       return (size_t) -1l;
      95                 :             :     }
      96                 :             : 
      97                 :             :   /* Make the ELF header available.  */
      98         [ +  + ]:       32234 :   if (e_ident[EI_DATA] == MY_ELFDATA
      99                 :             :       && (ALLOW_UNALIGNED
     100                 :             :           || (((size_t) e_ident
     101                 :             :                & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
     102                 :             :                   - 1)) == 0)))
     103                 :             :     ehdr.p = e_ident;
     104                 :             :   else
     105                 :             :     {
     106                 :             :       /* We already read the ELF header.  We have to copy the header
     107                 :             :          since we possibly modify the data here and the caller
     108                 :             :          expects the memory it passes in to be preserved.  */
     109                 :        1750 :       ehdr.p = &ehdr_mem;
     110                 :             : 
     111         [ +  + ]:        1750 :       if (is32)
     112                 :             :         {
     113                 :         804 :           if (ALLOW_UNALIGNED)
     114                 :             :             {
     115                 :         804 :               ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
     116                 :         804 :               ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
     117                 :             :             }
     118                 :             :           else
     119                 :             :             memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
     120                 :             : 
     121                 :         804 :           if (e_ident[EI_DATA] != MY_ELFDATA)
     122                 :             :             {
     123                 :         804 :               CONVERT (ehdr_mem.e32.e_shnum);
     124                 :         804 :               CONVERT (ehdr_mem.e32.e_shoff);
     125                 :             :             }
     126                 :             :         }
     127                 :             :       else
     128                 :             :         {
     129                 :         946 :           if (ALLOW_UNALIGNED)
     130                 :             :             {
     131                 :         946 :               ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
     132                 :         946 :               ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
     133                 :             :             }
     134                 :             :           else
     135                 :             :             memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
     136                 :             : 
     137                 :         946 :           if (e_ident[EI_DATA] != MY_ELFDATA)
     138                 :             :             {
     139                 :         946 :               CONVERT (ehdr_mem.e64.e_shnum);
     140                 :         946 :               CONVERT (ehdr_mem.e64.e_shoff);
     141                 :             :             }
     142                 :             :         }
     143                 :             :     }
     144                 :             : 
     145         [ +  + ]:       32234 :   if (is32)
     146                 :             :     {
     147                 :             :       /* Get the number of sections from the ELF header.  */
     148                 :        2244 :       result = ehdr.e32->e_shnum;
     149                 :             : 
     150   [ +  +  +  + ]:        2244 :       if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
     151                 :             :         {
     152         [ +  - ]:          36 :           if (unlikely (ehdr.e32->e_shoff >= maxsize)
     153         [ -  + ]:          36 :               || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
     154                 :             :             /* Cannot read the first section header.  */
     155                 :             :             return 0;
     156                 :             : 
     157         [ +  + ]:          36 :           if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
     158         [ +  + ]:          28 :               && (ALLOW_UNALIGNED
     159                 :             :                   || (((size_t) ((char *) (map_address + ehdr.e32->e_shoff
     160                 :             :                                            + offset)))
     161                 :             :                       & (__alignof__ (Elf32_Shdr) - 1)) == 0))
     162                 :             :             /* We can directly access the memory.  */
     163                 :          22 :             result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
     164                 :          22 :                                       + offset))->sh_size;
     165                 :             :           else
     166                 :             :             {
     167                 :          14 :               Elf32_Word size;
     168                 :          14 :               ssize_t r;
     169                 :             : 
     170                 :          14 :               if (likely (map_address != NULL))
     171                 :             :                 /* gcc will optimize the memcpy to a simple memory
     172                 :             :                    access while taking care of alignment issues.  */
     173                 :           6 :                 memcpy (&size, ((char *) map_address
     174                 :             :                                          + ehdr.e32->e_shoff
     175                 :           6 :                                          + offset
     176                 :           6 :                                          + offsetof (Elf32_Shdr, sh_size)),
     177                 :             :                         sizeof (Elf32_Word));
     178                 :             :               else
     179         [ -  + ]:           8 :                 if (unlikely ((r = pread_retry (fildes, &size,
     180                 :             :                                                 sizeof (Elf32_Word),
     181                 :             :                                                 offset + ehdr.e32->e_shoff
     182                 :             :                                                 + offsetof (Elf32_Shdr,
     183                 :             :                                                             sh_size)))
     184                 :             :                               != sizeof (Elf32_Word)))
     185                 :             :                   {
     186         [ #  # ]:           0 :                     if (r < 0)
     187                 :           0 :                       __libelf_seterrno (ELF_E_INVALID_FILE);
     188                 :             :                     else
     189                 :           0 :                       __libelf_seterrno (ELF_E_INVALID_ELF);
     190                 :           0 :                     return (size_t) -1l;
     191                 :             :                   }
     192                 :             : 
     193         [ +  + ]:          14 :               if (e_ident[EI_DATA] != MY_ELFDATA)
     194                 :           6 :                 CONVERT (size);
     195                 :             : 
     196                 :          14 :               result = size;
     197                 :             :             }
     198                 :             :         }
     199                 :             : 
     200                 :             :       /* If the section headers were truncated, pretend none were there.  */
     201         [ -  + ]:        2244 :       if (ehdr.e32->e_shoff > maxsize
     202         [ -  + ]:        2244 :           || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
     203                 :           8 :         result = 0;
     204                 :             :     }
     205                 :             :   else
     206                 :             :     {
     207                 :             :       /* Get the number of sections from the ELF header.  */
     208                 :       29990 :       result = ehdr.e64->e_shnum;
     209                 :             : 
     210   [ +  +  +  + ]:       29990 :       if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
     211                 :             :         {
     212         [ +  - ]:          34 :           if (unlikely (ehdr.e64->e_shoff >= maxsize)
     213         [ +  - ]:          34 :               || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
     214                 :             :             /* Cannot read the first section header.  */
     215                 :           0 :             return 0;
     216                 :             : 
     217                 :          34 :           Elf64_Xword size;
     218         [ +  + ]:          34 :           if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
     219         [ +  + ]:          32 :               && (ALLOW_UNALIGNED
     220                 :             :                   || (((size_t) ((char *) (map_address + ehdr.e64->e_shoff
     221                 :             :                                            + offset)))
     222                 :             :                       & (__alignof__ (Elf64_Shdr) - 1)) == 0))
     223                 :             :             /* We can directly access the memory.  */
     224                 :          26 :             size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
     225                 :          26 :                                     + offset))->sh_size;
     226                 :             :           else
     227                 :             :             {
     228                 :           8 :               ssize_t r;
     229                 :           8 :               if (likely (map_address != NULL))
     230                 :             :                 /* gcc will optimize the memcpy to a simple memory
     231                 :             :                    access while taking care of alignment issues.  */
     232                 :           6 :                 memcpy (&size, ((char *) map_address
     233                 :             :                                          + ehdr.e64->e_shoff
     234                 :           6 :                                          + offset
     235                 :           6 :                                          + offsetof (Elf64_Shdr, sh_size)),
     236                 :             :                         sizeof (Elf64_Xword));
     237                 :             :               else
     238         [ -  + ]:           2 :                 if (unlikely ((r = pread_retry (fildes, &size,
     239                 :             :                                                 sizeof (Elf64_Xword),
     240                 :             :                                                 offset + ehdr.e64->e_shoff
     241                 :             :                                                 + offsetof (Elf64_Shdr,
     242                 :             :                                                             sh_size)))
     243                 :             :                               != sizeof (Elf64_Xword)))
     244                 :             :                   {
     245         [ #  # ]:           0 :                     if (r < 0)
     246                 :           0 :                       __libelf_seterrno (ELF_E_INVALID_FILE);
     247                 :             :                     else
     248                 :           0 :                       __libelf_seterrno (ELF_E_INVALID_ELF);
     249                 :           0 :                     return (size_t) -1l;
     250                 :             :                   }
     251                 :             : 
     252         [ +  + ]:           8 :               if (e_ident[EI_DATA] != MY_ELFDATA)
     253                 :           6 :                 CONVERT (size);
     254                 :             :             }
     255                 :             : 
     256                 :             :           /* Although sh_size is an Elf64_Xword and can contain a 64bit
     257                 :             :              value, we only expect an 32bit value max.  GElf_Word is
     258                 :             :              32bit unsigned.  */
     259         [ -  + ]:          34 :           if (size > ~((GElf_Word) 0))
     260                 :             :             {
     261                 :             :               /* Invalid value, it is too large.  */
     262                 :           0 :               __libelf_seterrno (ELF_E_INVALID_ELF);
     263                 :           0 :               return (size_t) -1l;
     264                 :             :             }
     265                 :             : 
     266                 :          34 :           result = size;
     267                 :             :         }
     268                 :             : 
     269                 :             :       /* If the section headers were truncated, pretend none were there.  */
     270         [ +  + ]:       29990 :       if (ehdr.e64->e_shoff > maxsize
     271         [ -  + ]:       29982 :           || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
     272                 :           8 :         result = 0;
     273                 :             :     }
     274                 :             : 
     275                 :             :   return result;
     276                 :             : }
     277                 :             : 
     278                 :             : 
     279                 :             : /* Create descriptor for ELF file in memory.  */
     280                 :             : static Elf *
     281                 :       32234 : file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
     282                 :             :                int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
     283                 :             : {
     284                 :             :   /* Verify the binary is of the class we can handle.  */
     285   [ +  -  -  + ]:       32234 :   if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
     286                 :             :                  && e_ident[EI_CLASS] != ELFCLASS64)
     287                 :             :                 /* We also can only handle two encodings.  */
     288                 :             :                 || (e_ident[EI_DATA] != ELFDATA2LSB
     289                 :             :                     && e_ident[EI_DATA] != ELFDATA2MSB)))
     290                 :             :     {
     291                 :             :       /* Cannot handle this.  */
     292                 :           0 :       __libelf_seterrno (ELF_E_INVALID_ELF);
     293                 :           0 :       return NULL;
     294                 :             :     }
     295                 :             : 
     296                 :             :   /* Determine the number of sections.  Returns -1 and sets libelf errno
     297                 :             :      if the file handle or elf file is invalid.  Returns zero if there
     298                 :             :      are no section headers (or they cannot be read).  */
     299                 :       32234 :   size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
     300         [ -  + ]:       32234 :   if (scncnt == (size_t) -1l)
     301                 :             :     /* Could not determine the number of sections.  */
     302                 :             :     return NULL;
     303                 :             : 
     304                 :             :   /* Check for too many sections.  */
     305                 :       32234 :   if (e_ident[EI_CLASS] == ELFCLASS32)
     306                 :             :     {
     307                 :             :       if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
     308                 :             :         {
     309                 :             :           __libelf_seterrno (ELF_E_INVALID_ELF);
     310                 :             :           return NULL;
     311                 :             :         }
     312                 :             :     }
     313                 :       32234 :   else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
     314                 :             :     {
     315                 :             :       __libelf_seterrno (ELF_E_INVALID_ELF);
     316                 :             :       return NULL;
     317                 :             :     }
     318                 :             : 
     319                 :             :   /* We can now allocate the memory.  Even if there are no section headers,
     320                 :             :      we allocate space for a zeroth section in case we need it later.  */
     321         [ +  + ]:       32234 :   const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
     322                 :         386 :                          ? 1 : 0);
     323                 :       32234 :   Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
     324                 :             :                            ELF_K_ELF, scnmax * sizeof (Elf_Scn));
     325         [ -  + ]:       32234 :   if (elf == NULL)
     326                 :             :     /* Not enough memory.  allocate_elf will have set libelf errno.  */
     327                 :             :     return NULL;
     328                 :             : 
     329                 :       32234 :   assert ((unsigned int) scncnt == scncnt);
     330                 :       32234 :   assert (offsetof (struct Elf, state.elf32.scns)
     331                 :             :           == offsetof (struct Elf, state.elf64.scns));
     332                 :       32234 :   elf->state.elf32.scns.cnt = scncnt;
     333                 :       32234 :   elf->state.elf32.scns.max = scnmax;
     334                 :             : 
     335                 :             :   /* Some more or less arbitrary value.  */
     336                 :       32234 :   elf->state.elf.scnincr = 10;
     337                 :             : 
     338                 :             :   /* Make the class easily available.  */
     339                 :       32234 :   elf->class = e_ident[EI_CLASS];
     340                 :             : 
     341         [ +  + ]:       32234 :   if (e_ident[EI_CLASS] == ELFCLASS32)
     342                 :             :     {
     343                 :             :       /* This pointer might not be directly usable if the alignment is
     344                 :             :          not sufficient for the architecture.  */
     345                 :        2244 :       uintptr_t ehdr = (uintptr_t) map_address + offset;
     346                 :             : 
     347                 :             :       /* This is a 32-bit binary.  */
     348         [ +  + ]:        2244 :       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
     349         [ +  + ]:        1306 :           && (ALLOW_UNALIGNED
     350                 :             :               || (ehdr & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
     351                 :             :         {
     352                 :             :           /* We can use the mmapped memory.  */
     353                 :         844 :           elf->state.elf32.ehdr = (Elf32_Ehdr *) ehdr;
     354                 :             :         }
     355                 :             :       else
     356                 :             :         {
     357                 :             :           /* Copy the ELF header.  */
     358         [ +  + ]:        1400 :           elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
     359                 :             :                                           sizeof (Elf32_Ehdr));
     360                 :             : 
     361         [ +  + ]:        1400 :           if (e_ident[EI_DATA] != MY_ELFDATA)
     362                 :             :             {
     363                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_type);
     364                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_machine);
     365                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_version);
     366                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_entry);
     367                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
     368                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
     369                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_flags);
     370                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
     371                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
     372                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
     373                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
     374                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
     375                 :         804 :               CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
     376                 :             :             }
     377                 :             :         }
     378                 :             : 
     379                 :             :       /* Don't precache the phdr pointer here.
     380                 :             :          elf32_getphdr will validate it against the size when asked.  */
     381                 :             : 
     382                 :        2244 :       Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
     383   [ +  +  +  + ]:        2244 :       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
     384                 :             :           && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
     385         [ +  + ]:         844 :           && (ALLOW_UNALIGNED
     386                 :             :               || (((ehdr + e_shoff) & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
     387                 :             :         {
     388   [ +  +  -  + ]:         464 :           if (unlikely (scncnt > 0 && e_shoff >= maxsize)
     389         [ -  + ]:         464 :               || unlikely (maxsize - e_shoff
     390                 :             :                            < scncnt * sizeof (Elf32_Shdr)))
     391                 :             :             {
     392                 :           0 :             free_and_out:
     393                 :           0 :               free (elf);
     394                 :           0 :               __libelf_seterrno (ELF_E_INVALID_ELF);
     395                 :           0 :               return NULL;
     396                 :             :             }
     397                 :             : 
     398         [ +  + ]:         464 :           if (scncnt > 0)
     399                 :         442 :             elf->state.elf32.shdr = (Elf32_Shdr *) (ehdr + e_shoff);
     400                 :             : 
     401         [ +  + ]:      602154 :           for (size_t cnt = 0; cnt < scncnt; ++cnt)
     402                 :             :             {
     403                 :      601690 :               elf->state.elf32.scns.data[cnt].index = cnt;
     404                 :      601690 :               elf->state.elf32.scns.data[cnt].elf = elf;
     405                 :      601690 :               elf->state.elf32.scns.data[cnt].shdr.e32 =
     406                 :      601690 :                 &elf->state.elf32.shdr[cnt];
     407         [ +  + ]:      601690 :               if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
     408         [ +  + ]:      601686 :                   && likely (elf->state.elf32.shdr[cnt].sh_size
     409                 :             :                              <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
     410                 :      601674 :                 elf->state.elf32.scns.data[cnt].rawdata_base =
     411                 :      601674 :                   elf->state.elf32.scns.data[cnt].data_base =
     412                 :             :                   ((char *) map_address + offset
     413                 :      601674 :                    + elf->state.elf32.shdr[cnt].sh_offset);
     414                 :      601690 :               elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
     415                 :             :             }
     416                 :             :         }
     417                 :             :       else
     418                 :             :         {
     419         [ +  + ]:     4040110 :           for (size_t cnt = 0; cnt < scncnt; ++cnt)
     420                 :             :             {
     421                 :     4038330 :               elf->state.elf32.scns.data[cnt].index = cnt;
     422                 :     4038330 :               elf->state.elf32.scns.data[cnt].elf = elf;
     423                 :     4038330 :               elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
     424                 :             :             }
     425                 :             :         }
     426                 :             : 
     427                 :             :       /* So far only one block with sections.  */
     428                 :        2244 :       elf->state.elf32.scns_last = &elf->state.elf32.scns;
     429                 :        2244 :       eu_search_tree_init (&elf->state.elf32.rawchunk_tree);
     430                 :             :     }
     431                 :             :   else
     432                 :             :     {
     433                 :             :       /* This pointer might not be directly usable if the alignment is
     434                 :             :          not sufficient for the architecture.  */
     435                 :       29990 :       uintptr_t ehdr = (uintptr_t) map_address + offset;
     436                 :             : 
     437                 :             :       /* This is a 64-bit binary.  */
     438         [ +  + ]:       29990 :       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
     439         [ +  + ]:       14382 :           && (ALLOW_UNALIGNED
     440                 :             :               || (ehdr & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
     441                 :             :         {
     442                 :             :           /* We can use the mmapped memory.  */
     443                 :       13850 :           elf->state.elf64.ehdr = (Elf64_Ehdr *) ehdr;
     444                 :             :         }
     445                 :             :       else
     446                 :             :         {
     447                 :             :           /* Copy the ELF header.  */
     448         [ +  + ]:       16140 :           elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
     449                 :             :                                           sizeof (Elf64_Ehdr));
     450                 :             : 
     451         [ +  + ]:       16140 :           if (e_ident[EI_DATA] != MY_ELFDATA)
     452                 :             :             {
     453                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_type);
     454                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_machine);
     455                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_version);
     456                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_entry);
     457                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
     458                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
     459                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_flags);
     460                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
     461                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
     462                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
     463                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
     464                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
     465                 :         946 :               CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
     466                 :             :             }
     467                 :             :         }
     468                 :             : 
     469                 :             :       /* Don't precache the phdr pointer here.
     470                 :             :          elf64_getphdr will validate it against the size when asked.  */
     471                 :             : 
     472                 :       29990 :       Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
     473   [ +  +  +  + ]:       29990 :       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
     474                 :             :           && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
     475         [ +  + ]:       13850 :           && (ALLOW_UNALIGNED
     476                 :             :               || (((ehdr + e_shoff) & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
     477                 :             :         {
     478         [ +  - ]:       12268 :           if (unlikely (scncnt > 0 && e_shoff >= maxsize)
     479         [ -  + ]:       12268 :               || unlikely (maxsize - e_shoff
     480                 :             :                            < scncnt * sizeof (Elf64_Shdr)))
     481                 :           0 :             goto free_and_out;
     482                 :             : 
     483         [ +  + ]:       12268 :           if (scncnt > 0)
     484                 :       12214 :             elf->state.elf64.shdr = (Elf64_Shdr *) (ehdr + (ptrdiff_t) e_shoff);
     485                 :             : 
     486         [ +  + ]:     2138440 :           for (size_t cnt = 0; cnt < scncnt; ++cnt)
     487                 :             :             {
     488                 :     2126172 :               elf->state.elf64.scns.data[cnt].index = cnt;
     489                 :     2126172 :               elf->state.elf64.scns.data[cnt].elf = elf;
     490                 :     2126172 :               elf->state.elf64.scns.data[cnt].shdr.e64 =
     491                 :     2126172 :                 &elf->state.elf64.shdr[cnt];
     492         [ +  + ]:     2126172 :               if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
     493         [ +  + ]:     2125944 :                   && likely (elf->state.elf64.shdr[cnt].sh_size
     494                 :             :                              <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
     495                 :     2125782 :                 elf->state.elf64.scns.data[cnt].rawdata_base =
     496                 :     2125782 :                   elf->state.elf64.scns.data[cnt].data_base =
     497                 :             :                   ((char *) map_address + offset
     498                 :     2125782 :                    + elf->state.elf64.shdr[cnt].sh_offset);
     499                 :     2126172 :               elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
     500                 :             :             }
     501                 :             :         }
     502                 :             :       else
     503                 :             :         {
     504         [ +  + ]:     3447970 :           for (size_t cnt = 0; cnt < scncnt; ++cnt)
     505                 :             :             {
     506                 :     3430248 :               elf->state.elf64.scns.data[cnt].index = cnt;
     507                 :     3430248 :               elf->state.elf64.scns.data[cnt].elf = elf;
     508                 :     3430248 :               elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
     509                 :             :             }
     510                 :             :         }
     511                 :             : 
     512                 :             :       /* So far only one block with sections.  */
     513                 :       29990 :       elf->state.elf64.scns_last = &elf->state.elf64.scns;
     514                 :       29990 :       eu_search_tree_init (&elf->state.elf64.rawchunk_tree);
     515                 :             :     }
     516                 :             : 
     517                 :             :   return elf;
     518                 :             : }
     519                 :             : 
     520                 :             : 
     521                 :             : Elf *
     522                 :             : internal_function
     523                 :       16728 : __libelf_read_mmaped_file (int fildes, void *map_address,  int64_t offset,
     524                 :             :                            size_t maxsize, Elf_Cmd cmd, Elf *parent)
     525                 :             : {
     526                 :             :   /* We have to find out what kind of file this is.  We handle ELF
     527                 :             :      files and archives.  To find out what we have we must look at the
     528                 :             :      header.  The header for an ELF file is EI_NIDENT bytes in size,
     529                 :             :      the header for an archive file SARMAG bytes long.  */
     530                 :       16728 :   unsigned char *e_ident = (unsigned char *) map_address + offset;
     531                 :             : 
     532                 :             :   /* See what kind of object we have here.  */
     533                 :       16728 :   Elf_Kind kind = determine_kind (e_ident, maxsize);
     534                 :             : 
     535      [ +  +  + ]:       16728 :   switch (kind)
     536                 :             :     {
     537                 :       15688 :     case ELF_K_ELF:
     538                 :       15688 :       return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
     539                 :             :                             cmd, parent);
     540                 :             : 
     541                 :          64 :     case ELF_K_AR:
     542                 :          64 :       return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
     543                 :             : 
     544                 :             :     default:
     545                 :         976 :       break;
     546                 :             :     }
     547                 :             : 
     548                 :             :   /* This case is easy.  Since we cannot do anything with this file
     549                 :             :      create a dummy descriptor.  */
     550                 :         976 :   return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
     551                 :             :                        ELF_K_NONE, 0);
     552                 :             : }
     553                 :             : 
     554                 :             : 
     555                 :             : static Elf *
     556                 :       17328 : read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
     557                 :             :                     Elf *parent)
     558                 :             : {
     559                 :             :   /* We have to find out what kind of file this is.  We handle ELF
     560                 :             :      files and archives.  To find out what we have we must read the
     561                 :             :      header.  The identification header for an ELF file is EI_NIDENT
     562                 :             :      bytes in size, but we read the whole ELF header since we will
     563                 :             :      need it anyway later.  For archives the header in SARMAG bytes
     564                 :             :      long.  Read the maximum of these numbers.
     565                 :             : 
     566                 :             :      XXX We have to change this for the extended `ar' format some day.
     567                 :             : 
     568                 :             :      Use a union to ensure alignment.  We might later access the
     569                 :             :      memory as a ElfXX_Ehdr.  */
     570                 :       17328 :   union
     571                 :             :   {
     572                 :             :     Elf64_Ehdr ehdr;
     573                 :             :     unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
     574                 :             :   } mem;
     575                 :             : 
     576                 :             :   /* Read the head of the file.  */
     577                 :       34656 :   ssize_t nread = pread_retry (fildes, mem.header,
     578                 :       17328 :                                MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
     579                 :             :                                     maxsize),
     580                 :             :                                offset);
     581         [ -  + ]:       17328 :   if (unlikely (nread == -1))
     582                 :             :     {
     583                 :             :       /* We cannot even read the head of the file.  Maybe FILDES is associated
     584                 :             :          with an unseekable device.  This is nothing we can handle.  */
     585                 :           0 :       __libelf_seterrno (ELF_E_INVALID_FILE);
     586                 :           0 :       return NULL;
     587                 :             :     }
     588                 :             : 
     589                 :             :   /* See what kind of object we have here.  */
     590                 :       17328 :   Elf_Kind kind = determine_kind (mem.header, nread);
     591                 :             : 
     592      [ +  +  + ]:       17328 :   switch (kind)
     593                 :             :     {
     594                 :         278 :     case ELF_K_AR:
     595                 :         278 :       return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
     596                 :             : 
     597                 :       16546 :     case ELF_K_ELF:
     598                 :             :       /* Make sure at least the ELF header is contained in the file.  */
     599         [ +  - ]:       16546 :       if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
     600         [ +  + ]:       16546 :                              ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
     601                 :       16546 :         return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
     602                 :             :                               parent);
     603                 :         504 :       FALLTHROUGH;
     604                 :             : 
     605                 :             :     default:
     606                 :         504 :       break;
     607                 :             :     }
     608                 :             : 
     609                 :             :   /* This case is easy.  Since we cannot do anything with this file
     610                 :             :      create a dummy descriptor.  */
     611                 :         504 :   return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
     612                 :             :                        ELF_K_NONE, 0);
     613                 :             : }
     614                 :             : 
     615                 :             : 
     616                 :             : /* Open a file for reading.  If possible we will try to mmap() the file.  */
     617                 :             : static struct Elf *
     618                 :       33834 : read_file (int fildes, int64_t offset, size_t maxsize,
     619                 :             :            Elf_Cmd cmd, Elf *parent)
     620                 :             : {
     621                 :       33834 :   void *map_address = NULL;
     622                 :       33834 :   int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
     623                 :             :                   || cmd == ELF_C_WRITE_MMAP
     624                 :       33834 :                   || cmd == ELF_C_READ_MMAP_PRIVATE);
     625                 :             : 
     626         [ +  + ]:       33834 :   if (parent == NULL)
     627                 :             :     {
     628         [ +  - ]:       19122 :       if (maxsize == ~((size_t) 0))
     629                 :             :         {
     630                 :             :           /* We don't know in the moment how large the file is.
     631                 :             :              Determine it now.  */
     632                 :       19122 :           struct stat st;
     633                 :             : 
     634         [ +  - ]:       19122 :           if (fstat (fildes, &st) == 0
     635                 :             :               && (sizeof (size_t) >= sizeof (st.st_size)
     636                 :             :                   || st.st_size <= ~((size_t) 0)))
     637                 :       19122 :             maxsize = (size_t) st.st_size;
     638                 :             :         }
     639                 :             :     }
     640                 :             :   else
     641                 :             :     {
     642                 :             :       /* The parent is already loaded.  Use it.  */
     643         [ -  + ]:       14712 :       assert (maxsize != ~((size_t) 0));
     644                 :             :     }
     645                 :             : 
     646         [ +  + ]:       33834 :   if (use_mmap)
     647                 :             :     {
     648         [ +  + ]:       16546 :       if (parent == NULL)
     649                 :             :         {
     650                 :             :           /* We try to map the file ourself.  */
     651         [ +  + ]:       30134 :           map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
     652                 :             :                                               ? PROT_READ
     653                 :             :                                               : PROT_READ|PROT_WRITE),
     654                 :       16342 :                               cmd == ELF_C_READ_MMAP_PRIVATE
     655         [ +  + ]:       16342 :                               || cmd == ELF_C_READ_MMAP
     656                 :             :                               ? MAP_PRIVATE : MAP_SHARED,
     657                 :             :                               fildes, offset);
     658                 :             : 
     659         [ +  + ]:       16342 :           if (map_address == MAP_FAILED)
     660                 :             :             map_address = NULL;
     661                 :             :         }
     662                 :             :       else
     663                 :             :         {
     664                 :         204 :           map_address = parent->map_address;
     665                 :             :         }
     666                 :             :     }
     667                 :             : 
     668                 :             :   /* If we have the file in memory optimize the access.  */
     669         [ +  - ]:       16506 :   if (map_address != NULL)
     670                 :             :     {
     671         [ -  + ]:       16506 :       assert (map_address != MAP_FAILED);
     672                 :             : 
     673                 :       16506 :       struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
     674                 :             :                                                       offset, maxsize, cmd,
     675                 :             :                                                       parent);
     676                 :             : 
     677                 :             :       /* If something went wrong during the initialization unmap the
     678                 :             :          memory if we mmaped here.  */
     679         [ -  + ]:       16506 :       if (result == NULL
     680         [ #  # ]:           0 :           && (parent == NULL
     681         [ #  # ]:           0 :               || parent->map_address != map_address))
     682                 :           0 :         munmap (map_address, maxsize);
     683         [ +  + ]:       16506 :       else if (parent == NULL)
     684                 :             :         /* Remember that we mmap()ed the memory.  */
     685                 :       16302 :         result->flags |= ELF_F_MMAPPED;
     686                 :             : 
     687                 :       16506 :       return result;
     688                 :             :     }
     689                 :             : 
     690                 :             :   /* Otherwise we have to do it the hard way.  We read as much as necessary
     691                 :             :      from the file whenever we need information which is not available.  */
     692                 :       17328 :   return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
     693                 :             : }
     694                 :             : 
     695                 :             : 
     696                 :             : /* Find the entry with the long names for the content of this archive.  */
     697                 :             : static const char *
     698                 :         204 : read_long_names (Elf *elf)
     699                 :             : {
     700                 :         204 :   off_t offset = SARMAG;        /* This is the first entry.  */
     701                 :         408 :   struct ar_hdr hdrm;
     702                 :         408 :   struct ar_hdr *hdr;
     703                 :         408 :   char *newp;
     704                 :         408 :   size_t len;
     705                 :             : 
     706                 :         612 :   while (1)
     707                 :         204 :     {
     708         [ -  + ]:         408 :       if (elf->map_address != NULL)
     709                 :             :         {
     710         [ #  # ]:           0 :           if ((size_t) offset > elf->maximum_size
     711         [ #  # ]:           0 :               || elf->maximum_size - offset < sizeof (struct ar_hdr))
     712                 :           0 :             return NULL;
     713                 :             : 
     714                 :             :           /* The data is mapped.  */
     715                 :           0 :           hdr = (struct ar_hdr *) (elf->map_address + offset);
     716                 :             :         }
     717                 :             :       else
     718                 :             :         {
     719                 :             :           /* Read the header from the file.  */
     720         [ +  - ]:         408 :           if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
     721                 :             :                                      elf->start_offset + offset)
     722                 :             :                         != sizeof (hdrm)))
     723                 :             :             return NULL;
     724                 :             : 
     725                 :             :           hdr = &hdrm;
     726                 :             :         }
     727                 :             : 
     728                 :             :       /* The ar_size is given as a fixed size decimal string, right
     729                 :             :          padded with spaces.  Make sure we read it properly even if
     730                 :             :          there is no terminating space.  */
     731                 :         408 :       char buf[sizeof (hdr->ar_size) + 1];
     732                 :         408 :       const char *string = hdr->ar_size;
     733         [ -  + ]:         408 :       if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ')
     734                 :             :         {
     735                 :           0 :           *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
     736                 :           0 :           string = buf;
     737                 :             :         }
     738                 :             : 
     739                 :             :       /* atol expects to see at least one digit.
     740                 :             :          It also cannot be negative (-).  */
     741         [ +  - ]:         408 :       if (!isdigit(string[0]))
     742                 :             :         return NULL;
     743                 :         408 :       len = atol (string);
     744                 :             : 
     745         [ +  + ]:         408 :       if (memcmp (hdr->ar_name, "//              ", 16) == 0)
     746                 :             :         break;
     747                 :             : 
     748                 :         204 :       offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
     749                 :             :     }
     750                 :             : 
     751                 :             :   /* Sanity check len early if we can.  */
     752         [ -  + ]:         204 :   if (elf->map_address != NULL)
     753                 :             :     {
     754         [ #  # ]:           0 :       if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
     755                 :             :         return NULL;
     756                 :             :     }
     757                 :             : 
     758                 :             :   /* Due to the stupid format of the long name table entry (which are not
     759                 :             :      NUL terminted) we have to provide an appropriate representation anyhow.
     760                 :             :      Therefore we always make a copy which has the appropriate form.  */
     761                 :         204 :   newp = malloc (len);
     762         [ +  - ]:         204 :   if (newp != NULL)
     763                 :             :     {
     764                 :         204 :       char *runp;
     765                 :             : 
     766         [ -  + ]:         204 :       if (elf->map_address != NULL)
     767                 :             :         {
     768                 :             :           /* Simply copy it over.  */
     769                 :           0 :           elf->state.ar.long_names = (char *) memcpy (newp,
     770                 :             :                                                       elf->map_address + offset
     771                 :           0 :                                                       + sizeof (struct ar_hdr),
     772                 :             :                                                       len);
     773                 :             :         }
     774                 :             :       else
     775                 :             :         {
     776         [ -  + ]:         204 :           if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
     777                 :             :                                               elf->start_offset + offset
     778                 :             :                                               + sizeof (struct ar_hdr))
     779                 :             :                         != len))
     780                 :             :             {
     781                 :             :               /* We were not able to read all data.  */
     782                 :           0 :               free (newp);
     783                 :           0 :               elf->state.ar.long_names = NULL;
     784                 :           0 :               return NULL;
     785                 :             :             }
     786                 :         204 :           elf->state.ar.long_names = newp;
     787                 :             :         }
     788                 :             : 
     789                 :         204 :       elf->state.ar.long_names_len = len;
     790                 :             : 
     791                 :             :       /* Now NUL-terminate the strings.  */
     792                 :         204 :       runp = newp;
     793                 :        8364 :       while (1)
     794                 :             :         {
     795                 :        8364 :           char *startp = runp;
     796                 :        8364 :           runp = (char *) memchr (runp, '/', newp + len - runp);
     797         [ +  + ]:        8364 :           if (runp == NULL)
     798                 :             :             {
     799                 :             :               /* This was the last entry.  Clear any left overs.  */
     800                 :         204 :               memset (startp, '\0', newp + len - startp);
     801                 :         204 :               break;
     802                 :             :             }
     803                 :             : 
     804                 :             :           /* NUL-terminate the string.  */
     805                 :        8160 :           *runp++ = '\0';
     806                 :             : 
     807                 :             :           /* A sanity check.  Somebody might have generated invalid
     808                 :             :              archive.  */
     809         [ +  - ]:        8160 :           if (runp >= newp + len)
     810                 :             :             break;
     811                 :             :         }
     812                 :             :     }
     813                 :             : 
     814                 :             :   return newp;
     815                 :             : }
     816                 :             : 
     817                 :             : 
     818                 :             : /* Copy archive header from parent archive ref to member descriptor elf.  */
     819                 :             : static int
     820                 :       14712 : copy_arhdr (Elf_Arhdr *dest, Elf *ref)
     821                 :             : {
     822                 :       14712 :   Elf_Arhdr *hdr;
     823                 :             : 
     824         [ +  - ]:       14712 :   if (ref->kind == ELF_K_AR)
     825                 :       14712 :     hdr = &ref->state.ar.elf_ar_hdr;
     826                 :             :   else
     827                 :           0 :     hdr = &ref->state.elf.elf_ar_hdr;
     828                 :             : 
     829                 :       14712 :   char *ar_name = hdr->ar_name;
     830                 :       14712 :   char *ar_rawname = hdr->ar_rawname;
     831         [ -  + ]:       14712 :   if (ar_name == NULL || ar_rawname == NULL)
     832                 :             :     {
     833                 :             :       /* ref doesn't have an Elf_Arhdr or it was marked as unusable.  */
     834                 :             :       return 0;
     835                 :             :     }
     836                 :             : 
     837                 :             :   /* Allocate copies of ar_name and ar_rawname.  */
     838                 :       14712 :   size_t name_len = strlen (ar_name) + 1;
     839                 :       14712 :   char *name_copy = malloc (MAX (name_len, 16));
     840         [ -  + ]:       14712 :   if (name_copy == NULL)
     841                 :             :     {
     842                 :           0 :       __libelf_seterrno (ELF_E_NOMEM);
     843                 :           0 :       return -1;
     844                 :             :     }
     845         [ -  + ]:       14712 :   memcpy (name_copy, ar_name, name_len);
     846                 :             : 
     847                 :       14712 :   size_t rawname_len = strlen (ar_rawname) + 1;
     848                 :       14712 :   char *rawname_copy = malloc (MAX (rawname_len, 17));
     849         [ -  + ]:       14712 :   if (rawname_copy == NULL)
     850                 :             :     {
     851                 :           0 :       free (name_copy);
     852                 :           0 :       __libelf_seterrno (ELF_E_NOMEM);
     853                 :           0 :       return -1;
     854                 :             :     }
     855                 :       14712 :   memcpy (rawname_copy, ar_rawname, rawname_len);
     856                 :             : 
     857                 :       14712 :   *dest = *hdr;
     858                 :       14712 :   dest->ar_name = name_copy;
     859                 :       14712 :   dest->ar_rawname = rawname_copy;
     860                 :             : 
     861                 :       14712 :   return 0;
     862                 :             : }
     863                 :             : 
     864                 :             : 
     865                 :             : /* Read the next archive header.  */
     866                 :             : int
     867                 :             : internal_function
     868                 :       14778 : __libelf_next_arhdr_wrlock (Elf *elf)
     869                 :             : {
     870                 :       14778 :   struct ar_hdr *ar_hdr;
     871                 :       14778 :   Elf_Arhdr *elf_ar_hdr;
     872                 :             : 
     873         [ +  + ]:       14778 :   if (elf->map_address != NULL)
     874                 :             :     {
     875                 :             :       /* See whether this entry is in the file.  */
     876   [ +  -  +  + ]:         246 :       if (unlikely ((size_t) elf->state.ar.offset
     877                 :             :                     > elf->start_offset + elf->maximum_size
     878                 :             :                     || (elf->start_offset + elf->maximum_size
     879                 :             :                         - elf->state.ar.offset) < sizeof (struct ar_hdr)))
     880                 :             :         {
     881                 :             :           /* This record is not anymore in the file.  */
     882                 :          42 :           __libelf_seterrno (ELF_E_RANGE);
     883                 :          42 :           return -1;
     884                 :             :         }
     885                 :         204 :       ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
     886                 :             :     }
     887                 :             :   else
     888                 :             :     {
     889                 :       14532 :       ar_hdr = &elf->state.ar.ar_hdr;
     890                 :             : 
     891         [ +  + ]:       14532 :       if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
     892                 :             :                                  elf->state.ar.offset)
     893                 :             :                     != sizeof (struct ar_hdr)))
     894                 :             :         {
     895                 :             :           /* Something went wrong while reading the file.  */
     896                 :          24 :           __libelf_seterrno (ELF_E_RANGE);
     897                 :          24 :           return -1;
     898                 :             :         }
     899                 :             :     }
     900                 :             : 
     901                 :             :   /* One little consistency check.  */
     902         [ -  + ]:       14712 :   if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
     903                 :             :     {
     904                 :             :       /* This is no valid archive.  */
     905                 :           0 :       __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
     906                 :           0 :       return -1;
     907                 :             :     }
     908                 :             : 
     909                 :             :   /* Copy the raw name over to a NUL terminated buffer.  */
     910         [ +  + ]:       14712 :   *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
     911                 :             : 
     912                 :       14712 :   elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
     913                 :             : 
     914                 :             :   /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
     915                 :             :      Determine whether this is a special entry.  */
     916         [ +  + ]:       14712 :   if (ar_hdr->ar_name[0] == '/')
     917                 :             :     {
     918         [ +  + ]:        4182 :       if (ar_hdr->ar_name[1] == ' '
     919         [ +  - ]:         254 :           && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
     920                 :             :         /* This is the index.  */
     921                 :         254 :         elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
     922         [ +  + ]:        3928 :       else if (ar_hdr->ar_name[1] == 'S'
     923         [ +  - ]:          16 :                && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
     924                 :             :         /* 64-bit index.  */
     925                 :          16 :         elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
     926         [ +  + ]:        3912 :       else if (ar_hdr->ar_name[1] == '/'
     927         [ +  - ]:         232 :                && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
     928                 :             :         /* This is the array with the long names.  */
     929                 :         232 :         elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
     930         [ +  - ]:        3680 :       else if (likely  (isdigit (ar_hdr->ar_name[1])))
     931                 :             :         {
     932                 :        3680 :           size_t offset;
     933                 :             : 
     934                 :             :           /* This is a long name.  First we have to read the long name
     935                 :             :              table, if this hasn't happened already.  */
     936   [ +  +  -  + ]:        3680 :           if (unlikely (elf->state.ar.long_names == NULL
     937                 :             :                         && read_long_names (elf) == NULL))
     938                 :             :             {
     939                 :             :               /* No long name table although it is reference.  The archive is
     940                 :             :                  broken.  */
     941                 :           0 :               __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
     942                 :           0 :               return -1;
     943                 :             :             }
     944                 :             : 
     945                 :        3680 :           offset = atol (ar_hdr->ar_name + 1);
     946         [ -  + ]:        3680 :           if (unlikely (offset >= elf->state.ar.long_names_len))
     947                 :             :             {
     948                 :             :               /* The index in the long name table is larger than the table.  */
     949                 :           0 :               __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
     950                 :           0 :               return -1;
     951                 :             :             }
     952                 :        3680 :           elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
     953                 :             :         }
     954                 :             :       else
     955                 :             :         {
     956                 :             :           /* This is none of the known special entries.  */
     957                 :           0 :           __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
     958                 :           0 :           return -1;
     959                 :             :         }
     960                 :             :     }
     961                 :             :   else
     962                 :             :     {
     963                 :       10530 :       char *endp;
     964                 :             : 
     965                 :             :       /* It is a normal entry.  Copy over the name.  */
     966                 :       10530 :       endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
     967                 :             :                                '/', 16);
     968         [ +  - ]:       10530 :       if (endp != NULL)
     969                 :       10530 :         endp[-1] = '\0';
     970                 :             :       else
     971                 :             :         {
     972                 :             :           /* In the old BSD style of archive, there is no / terminator.
     973                 :             :              Instead, there is space padding at the end of the name.  */
     974                 :             :           size_t i = 15;
     975                 :           0 :           do
     976                 :           0 :             elf->state.ar.ar_name[i] = '\0';
     977   [ #  #  #  # ]:           0 :           while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
     978                 :             :         }
     979                 :             : 
     980                 :       10530 :       elf_ar_hdr->ar_name = elf->state.ar.ar_name;
     981                 :             :     }
     982                 :             : 
     983         [ -  + ]:       14712 :   if (unlikely (ar_hdr->ar_size[0] == ' '))
     984                 :             :     /* Something is really wrong.  We cannot live without a size for
     985                 :             :        the member since it will not be possible to find the next
     986                 :             :        archive member.  */
     987                 :             :     {
     988                 :           0 :       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
     989                 :           0 :       return -1;
     990                 :             :     }
     991                 :             : 
     992                 :             :   /* Since there are no specialized functions to convert ASCII to
     993                 :             :      time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
     994                 :             :      atoll depending on the size of the types.  We are also prepared
     995                 :             :      for the case where the whole field in the `struct ar_hdr' is
     996                 :             :      filled in which case we cannot simply use atol/l but instead have
     997                 :             :      to create a temporary copy.  Note that all fields use decimal
     998                 :             :      encoding, except ar_mode which uses octal.  */
     999                 :             : 
    1000                 :             : #define INT_FIELD(FIELD)                                                      \
    1001                 :             :   do                                                                          \
    1002                 :             :     {                                                                         \
    1003                 :             :       char buf[sizeof (ar_hdr->FIELD) + 1];                                \
    1004                 :             :       const char *string = ar_hdr->FIELD;                                  \
    1005                 :             :       if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')                     \
    1006                 :             :         {                                                                     \
    1007                 :             :           *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
    1008                 :             :             = '\0';                                                           \
    1009                 :             :           string = buf;                                                       \
    1010                 :             :         }                                                                     \
    1011                 :             :       if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))                      \
    1012                 :             :         elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
    1013                 :             :       else                                                                    \
    1014                 :             :         elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
    1015                 :             :     }                                                                         \
    1016                 :             :   while (0)
    1017                 :             : 
    1018                 :             : #define OCT_FIELD(FIELD)                                                      \
    1019                 :             :   do                                                                          \
    1020                 :             :     {                                                                         \
    1021                 :             :       char buf[sizeof (ar_hdr->FIELD) + 1];                                \
    1022                 :             :       const char *string = ar_hdr->FIELD;                                  \
    1023                 :             :       if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')                     \
    1024                 :             :         {                                                                     \
    1025                 :             :           *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
    1026                 :             :             = '\0';                                                           \
    1027                 :             :           string = buf;                                                       \
    1028                 :             :         }                                                                     \
    1029                 :             :       if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))                      \
    1030                 :             :         elf_ar_hdr->FIELD                                                  \
    1031                 :             :           = (__typeof (elf_ar_hdr->FIELD)) strtol (string, NULL, 8);       \
    1032                 :             :       else                                                                    \
    1033                 :             :         elf_ar_hdr->FIELD                                                  \
    1034                 :             :           = (__typeof (elf_ar_hdr->FIELD)) strtoll (string, NULL, 8);              \
    1035                 :             :     }                                                                         \
    1036                 :             :   while (0)
    1037                 :             : 
    1038         [ -  + ]:       14712 :   INT_FIELD (ar_date);
    1039         [ -  + ]:       14712 :   INT_FIELD (ar_uid);
    1040         [ -  + ]:       14712 :   INT_FIELD (ar_gid);
    1041         [ -  + ]:       14712 :   OCT_FIELD (ar_mode);
    1042         [ -  + ]:       14712 :   INT_FIELD (ar_size);
    1043                 :             : 
    1044         [ -  + ]:       14712 :   if (elf_ar_hdr->ar_size < 0)
    1045                 :             :     {
    1046                 :           0 :       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
    1047                 :           0 :       return -1;
    1048                 :             :     }
    1049                 :             : 
    1050                 :             :   /* Truncated file?  */
    1051                 :       14712 :   size_t maxsize;
    1052                 :       14712 :   maxsize = (elf->start_offset + elf->maximum_size
    1053                 :       14712 :              - elf->state.ar.offset - sizeof (struct ar_hdr));
    1054         [ -  + ]:       14712 :   if ((size_t) elf_ar_hdr->ar_size > maxsize)
    1055                 :           0 :     elf_ar_hdr->ar_size = maxsize;
    1056                 :             : 
    1057                 :             :   return 0;
    1058                 :             : }
    1059                 :             : 
    1060                 :             : 
    1061                 :             : /* We were asked to return a clone of an existing descriptor.  This
    1062                 :             :    function must be called with the lock on the parent descriptor
    1063                 :             :    being held. */
    1064                 :             : static Elf *
    1065                 :       14714 : dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
    1066                 :             : {
    1067                 :       14714 :   struct Elf *result;
    1068                 :             : 
    1069         [ +  + ]:       14714 :   if (fildes == -1)
    1070                 :             :     /* Allow the user to pass -1 as the file descriptor for the new file.  */
    1071                 :          28 :     fildes = ref->fildes;
    1072                 :             :   /* The file descriptor better should be the same.  If it was disconnected
    1073                 :             :      already (using `elf_cntl') we do not test it.  */
    1074   [ +  -  -  + ]:       14686 :   else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
    1075                 :             :     {
    1076                 :           0 :       __libelf_seterrno (ELF_E_FD_MISMATCH);
    1077                 :           0 :       return NULL;
    1078                 :             :     }
    1079                 :             : 
    1080                 :             :   /* The mode must allow reading.  I.e., a descriptor creating with a
    1081                 :             :      command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
    1082                 :             :      not allowed.  */
    1083   [ +  +  +  -  :       14714 :   if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
          +  -  +  -  +  
                -  -  + ]
    1084                 :             :                 && ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
    1085                 :             :                 && ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
    1086                 :             :                 && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
    1087                 :             :     {
    1088                 :           0 :       __libelf_seterrno (ELF_E_INVALID_OP);
    1089                 :           0 :       return NULL;
    1090                 :             :     }
    1091                 :             : 
    1092                 :             :   /* Now it is time to distinguish between reading normal files and
    1093                 :             :      archives.  Normal files can easily be handled be incrementing the
    1094                 :             :      reference counter and return the same descriptor.  */
    1095         [ -  + ]:       14714 :   if (ref->kind != ELF_K_AR)
    1096                 :             :     {
    1097                 :           0 :       ++ref->ref_count;
    1098                 :           0 :       return ref;
    1099                 :             :     }
    1100                 :             : 
    1101                 :             :   /* This is an archive.  We must create a descriptor for the archive
    1102                 :             :      member the internal pointer of the archive file descriptor is
    1103                 :             :      pointing to.  First read the header of the next member if this
    1104                 :             :      has not happened already.  */
    1105         [ +  + ]:       14714 :   if (ref->state.ar.elf_ar_hdr.ar_name == NULL
    1106         [ +  + ]:         298 :       && __libelf_next_arhdr_wrlock (ref) != 0)
    1107                 :             :     /* Something went wrong.  Maybe there is no member left.  */
    1108                 :             :     return NULL;
    1109                 :             : 
    1110                 :       14712 :   Elf_Arhdr ar_hdr = {0};
    1111         [ -  + ]:       14712 :   if (copy_arhdr (&ar_hdr, ref) != 0)
    1112                 :             :     /* Out of memory.  */
    1113                 :             :     return NULL;
    1114                 :             : 
    1115                 :             :   /* We have all the information we need about the next archive member.
    1116                 :             :      Now create a descriptor for it.  */
    1117                 :       29424 :   result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
    1118                 :       14712 :                       ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
    1119                 :             : 
    1120         [ +  - ]:       14712 :   if (result != NULL)
    1121                 :             :     {
    1122                 :             :       /* Enlist this new descriptor in the list of children.  */
    1123                 :       14712 :       result->next = ref->state.ar.children;
    1124                 :       14712 :       result->state.elf.elf_ar_hdr = ar_hdr;
    1125                 :       14712 :       ref->state.ar.children = result;
    1126                 :             :     }
    1127                 :             :   else
    1128                 :             :     {
    1129                 :           0 :       free (ar_hdr.ar_name);
    1130                 :           0 :       free (ar_hdr.ar_rawname);
    1131                 :             :     }
    1132                 :             : 
    1133                 :             :   return result;
    1134                 :             : }
    1135                 :             : 
    1136                 :             : 
    1137                 :             : /* Return descriptor for empty file ready for writing.  */
    1138                 :             : static struct Elf *
    1139                 :        1060 : write_file (int fd, Elf_Cmd cmd)
    1140                 :             : {
    1141                 :             :   /* We simply create an empty `Elf' structure.  */
    1142                 :             : #define NSCNSALLOC      10
    1143                 :        1060 :   Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
    1144                 :             :                               NSCNSALLOC * sizeof (Elf_Scn));
    1145                 :             : 
    1146         [ +  - ]:        1060 :   if (result != NULL)
    1147                 :             :     {
    1148                 :             :       /* We have to write to the file in any case.  */
    1149                 :        1060 :       result->flags = ELF_F_DIRTY;
    1150                 :             : 
    1151                 :             :       /* Some more or less arbitrary value.  */
    1152                 :        1060 :       result->state.elf.scnincr = NSCNSALLOC;
    1153                 :             : 
    1154                 :             :       /* We have allocated room for some sections.  */
    1155                 :        1060 :       assert (offsetof (struct Elf, state.elf32.scns)
    1156                 :             :               == offsetof (struct Elf, state.elf64.scns));
    1157                 :        1060 :       result->state.elf.scns_last = &result->state.elf32.scns;
    1158                 :        1060 :       result->state.elf32.scns.max = NSCNSALLOC;
    1159                 :             :     }
    1160                 :             : 
    1161                 :        1060 :   return result;
    1162                 :             : }
    1163                 :             : 
    1164                 :             : /* Lock if necessary before dup an archive.  */
    1165                 :             : static inline Elf *
    1166                 :       14714 : lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
    1167                 :             : {
    1168                 :             :   /* We need wrlock to dup an archive.  */
    1169                 :       14714 :   if (ref->kind == ELF_K_AR)
    1170                 :             :     {
    1171                 :       14714 :       rwlock_unlock (ref->lock);
    1172                 :       14714 :       rwlock_wrlock (ref->lock);
    1173                 :             :     }
    1174                 :             :     /* Duplicate the descriptor.  */
    1175                 :       14714 :   return dup_elf (fildes, cmd, ref);
    1176                 :             : }
    1177                 :             : 
    1178                 :             : /* Return a descriptor for the file belonging to FILDES.  */
    1179                 :             : Elf *
    1180                 :       34956 : elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
    1181                 :             : {
    1182                 :       34956 :   Elf *retval;
    1183                 :             : 
    1184         [ -  + ]:       34956 :   if (unlikely (__libelf_version != EV_CURRENT))
    1185                 :             :     {
    1186                 :             :       /* Version wasn't set so far.  */
    1187                 :           0 :       __libelf_seterrno (ELF_E_NO_VERSION);
    1188                 :           0 :       return NULL;
    1189                 :             :     }
    1190                 :             : 
    1191         [ +  + ]:       34956 :   if (ref != NULL)
    1192                 :             :     /* Make sure the descriptor is not suddenly going away.  */
    1193                 :             :     rwlock_rdlock (ref->lock);
    1194   [ -  +  -  - ]:       20182 :   else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
    1195                 :             :     {
    1196                 :             :       /* We cannot do anything productive without a file descriptor.  */
    1197                 :           0 :       __libelf_seterrno (ELF_E_INVALID_FILE);
    1198                 :           0 :       return NULL;
    1199                 :             :     }
    1200                 :             : 
    1201   [ +  +  +  +  :       34956 :   switch (cmd)
                   +  - ]
    1202                 :             :     {
    1203                 :             :     case ELF_C_NULL:
    1204                 :             :       /* We simply return a NULL pointer.  */
    1205                 :             :       retval = NULL;
    1206                 :             :       break;
    1207                 :             : 
    1208                 :       13808 :     case ELF_C_READ_MMAP_PRIVATE:
    1209                 :             :       /* If we have a reference it must also be opened this way.  */
    1210   [ +  +  -  + ]:       13808 :       if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
    1211                 :             :         {
    1212                 :           0 :           __libelf_seterrno (ELF_E_INVALID_CMD);
    1213                 :           0 :           retval = NULL;
    1214                 :           0 :           break;
    1215                 :             :         }
    1216                 :       19756 :       FALLTHROUGH;
    1217                 :             : 
    1218                 :             :     case ELF_C_READ:
    1219                 :             :     case ELF_C_READ_MMAP:
    1220         [ +  + ]:       19756 :       if (ref != NULL)
    1221                 :       14714 :         retval = lock_dup_elf (fildes, cmd, ref);
    1222                 :             :       else
    1223                 :             :         /* Create descriptor for existing file.  */
    1224                 :       18850 :         retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
    1225                 :             :       break;
    1226                 :             : 
    1227                 :         272 :     case ELF_C_RDWR:
    1228                 :             :     case ELF_C_RDWR_MMAP:
    1229                 :             :       /* If we have a REF object it must also be opened using this
    1230                 :             :          command.  */
    1231         [ -  + ]:         272 :       if (ref != NULL)
    1232                 :             :         {
    1233   [ #  #  #  #  :           0 :           if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
                   #  # ]
    1234                 :             :                         && ref->cmd != ELF_C_WRITE
    1235                 :             :                         && ref->cmd != ELF_C_WRITE_MMAP))
    1236                 :             :             {
    1237                 :             :               /* This is not ok.  REF must also be opened for writing.  */
    1238                 :           0 :               __libelf_seterrno (ELF_E_INVALID_CMD);
    1239                 :           0 :               retval = NULL;
    1240                 :             :             }
    1241                 :             :           else
    1242                 :           0 :             retval = lock_dup_elf (fildes, cmd, ref);
    1243                 :             :         }
    1244                 :             :       else
    1245                 :             :         /* Create descriptor for existing file.  */
    1246                 :         272 :         retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
    1247                 :             :       break;
    1248                 :             : 
    1249                 :        1060 :     case ELF_C_WRITE:
    1250                 :             :     case ELF_C_WRITE_MMAP:
    1251                 :             :       /* We ignore REF and prepare a descriptor to write a new file.  */
    1252                 :        1060 :       retval = write_file (fildes, cmd);
    1253                 :        1060 :       break;
    1254                 :             : 
    1255                 :           0 :     default:
    1256                 :           0 :       __libelf_seterrno (ELF_E_INVALID_CMD);
    1257                 :           0 :       retval = NULL;
    1258                 :           0 :       break;
    1259                 :             :     }
    1260                 :             : 
    1261                 :             :   /* Release the lock.  */
    1262                 :             :   if (ref != NULL)
    1263                 :             :     rwlock_unlock (ref->lock);
    1264                 :             : 
    1265                 :             :   return retval;
    1266                 :             : }
    1267                 :             : INTDEF(elf_begin)
        

Generated by: LCOV version 2.0-1