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

Generated by: LCOV version 1.13