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

Generated by: LCOV version 1.12