LCOV - code coverage report
Current view: top level - elfutils/libelf - elf_begin.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 264 335 78.8 %
Date: 2013-03-08 Functions: 12 12 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 176 316 55.7 %

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

Generated by: LCOV version 1.9