LCOV - code coverage report
Current view: top level - libelf - elf_begin.c (source / functions) Hit Total Coverage
Test: elfutils-0.173 Lines: 285 381 74.8 %
Date: 2018-06-29 23:49:12 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13