LCOV - code coverage report
Current view: top level - libelf - elf32_getshdr.c (source / functions) Hit Total Coverage
Test: elfutils-0.172 Lines: 76 90 84.4 %
Date: 2018-06-11 22:52:14 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Return section header.
       2             :    Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014, 2015 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 <errno.h>
      36             : #include <stdbool.h>
      37             : #include <unistd.h>
      38             : 
      39             : #include <system.h>
      40             : #include "libelfP.h"
      41             : #include "common.h"
      42             : 
      43             : #ifndef LIBELFBITS
      44             : # define LIBELFBITS 32
      45             : #endif
      46             : 
      47             : 
      48             : static ElfW2(LIBELFBITS,Shdr) *
      49        1038 : load_shdr_wrlock (Elf_Scn *scn)
      50             : {
      51             :   ElfW2(LIBELFBITS,Shdr) *result;
      52             : 
      53             :   /* Read the section header table.  */
      54        1038 :   Elf *elf = scn->elf;
      55        1038 :   ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
      56             : 
      57             :   /* Try again, maybe the data is there now.  */
      58        1038 :   result = scn->shdr.ELFW(e,LIBELFBITS);
      59        1038 :   if (result != NULL)
      60             :     goto out;
      61             : 
      62             :   size_t shnum;
      63        1038 :   if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
      64        1038 :       || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
      65             :     goto out;
      66        1038 :   size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
      67             : 
      68             :   /* Allocate memory for the section headers.  We know the number
      69             :      of entries from the ELF header.  */
      70        1038 :   ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
      71        1038 :     (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
      72        1038 :   if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
      73             :     {
      74           0 :       __libelf_seterrno (ELF_E_NOMEM);
      75             :       goto out;
      76             :     }
      77        1038 :   elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
      78             : 
      79        1038 :   if (elf->map_address != NULL)
      80             :     {
      81             :       /* First see whether the information in the ELF header is
      82             :          valid and it does not ask for too much.  */
      83         688 :       if (unlikely (ehdr->e_shoff >= elf->maximum_size)
      84         688 :           || unlikely (elf->maximum_size - ehdr->e_shoff < size))
      85             :         {
      86             :           /* Something is wrong.  */
      87           0 :           __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
      88             :           goto free_and_out;
      89             :         }
      90             : 
      91             :       ElfW2(LIBELFBITS,Shdr) *notcvt;
      92             : 
      93             :       /* All the data is already mapped.  If we could use it
      94             :          directly this would already have happened.  Unless
      95             :          we allocated the memory ourselves and the ELF_F_MALLOCED
      96             :          flag is set.  */
      97         688 :       void *file_shdr = ((char *) elf->map_address
      98         688 :                          + elf->start_offset + ehdr->e_shoff);
      99             : 
     100         688 :       assert ((elf->flags & ELF_F_MALLOCED)
     101             :               || ehdr->e_ident[EI_DATA] != MY_ELFDATA
     102             :               || elf->cmd == ELF_C_READ_MMAP
     103             :               || (! ALLOW_UNALIGNED
     104             :                   && ((uintptr_t) file_shdr
     105             :                       & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
     106             : 
     107             :       /* Now copy the data and at the same time convert the byte order.  */
     108         688 :       if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
     109             :         {
     110         538 :           assert ((elf->flags & ELF_F_MALLOCED)
     111             :                   || elf->cmd == ELF_C_READ_MMAP
     112             :                   || ! ALLOW_UNALIGNED);
     113             :           memcpy (shdr, file_shdr, size);
     114             :         }
     115             :       else
     116             :         {
     117             :           bool copy = ! (ALLOW_UNALIGNED
     118             :                          || ((uintptr_t) file_shdr
     119             :                              & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1))
     120             :                              == 0);
     121             :           if (! copy)
     122             :             notcvt = (ElfW2(LIBELFBITS,Shdr) *)
     123             :               ((char *) elf->map_address
     124             :                + elf->start_offset + ehdr->e_shoff);
     125             :           else
     126             :             {
     127             :               notcvt = (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
     128             :               if (unlikely (notcvt == NULL))
     129             :                 {
     130             :                   __libelf_seterrno (ELF_E_NOMEM);
     131             :                   goto out;
     132             :                 }
     133             :               memcpy (notcvt, ((char *) elf->map_address
     134             :                                + elf->start_offset + ehdr->e_shoff),
     135             :                       size);
     136             :             }
     137             : 
     138        3490 :           for (size_t cnt = 0; cnt < shnum; ++cnt)
     139             :             {
     140        6980 :               CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
     141        6980 :               CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
     142        6980 :               CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
     143        6980 :               CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
     144        6980 :               CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
     145        6980 :               CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
     146        6980 :               CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
     147        6980 :               CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
     148        6980 :               CONVERT_TO (shdr[cnt].sh_addralign,
     149             :                           notcvt[cnt].sh_addralign);
     150        6980 :               CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
     151             : 
     152             :               /* If this is a section with an extended index add a
     153             :                  reference in the section which uses the extended
     154             :                  index.  */
     155        3490 :               if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
     156           0 :                   && shdr[cnt].sh_link < shnum)
     157             :                 elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
     158           0 :                   = cnt;
     159             : 
     160             :               /* Set the own shndx_index field in case it has not yet
     161             :                  been set.  */
     162        3490 :               if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
     163             :                 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
     164        3490 :                   = -1;
     165             :             }
     166             : 
     167             :           if (copy)
     168             :             free (notcvt);
     169             :         }
     170             :     }
     171         350 :   else if (likely (elf->fildes != -1))
     172             :     {
     173             :       /* Read the header.  */
     174         350 :       ssize_t n = pread_retry (elf->fildes,
     175             :                                elf->state.ELFW(elf,LIBELFBITS).shdr, size,
     176         350 :                                elf->start_offset + ehdr->e_shoff);
     177         350 :       if (unlikely ((size_t) n != size))
     178             :         {
     179             :           /* Severe problems.  We cannot read the data.  */
     180           0 :           __libelf_seterrno (ELF_E_READ_ERROR);
     181             :           goto free_and_out;
     182             :         }
     183             : 
     184             :       /* If the byte order of the file is not the same as the one
     185             :          of the host convert the data now.  */
     186         350 :       if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
     187        2236 :         for (size_t cnt = 0; cnt < shnum; ++cnt)
     188             :           {
     189        4472 :             CONVERT (shdr[cnt].sh_name);
     190        4472 :             CONVERT (shdr[cnt].sh_type);
     191        4472 :             CONVERT (shdr[cnt].sh_flags);
     192        4472 :             CONVERT (shdr[cnt].sh_addr);
     193        4472 :             CONVERT (shdr[cnt].sh_offset);
     194        4472 :             CONVERT (shdr[cnt].sh_size);
     195        4472 :             CONVERT (shdr[cnt].sh_link);
     196        4472 :             CONVERT (shdr[cnt].sh_info);
     197        4472 :             CONVERT (shdr[cnt].sh_addralign);
     198        4472 :             CONVERT (shdr[cnt].sh_entsize);
     199             :           }
     200             :     }
     201             :   else
     202             :     {
     203             :       /* The file descriptor was already enabled and not all data was
     204             :          read.  Undo the allocation.  */
     205           0 :       __libelf_seterrno (ELF_E_FD_DISABLED);
     206             : 
     207           0 :     free_and_out:
     208           0 :       free (shdr);
     209           0 :       elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
     210           0 :       elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
     211             : 
     212             :       goto out;
     213             :     }
     214             : 
     215             :   /* Set the pointers in the `scn's.  */
     216      225299 :   for (size_t cnt = 0; cnt < shnum; ++cnt)
     217             :     elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
     218      225299 :       = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
     219             : 
     220        1038 :   result = scn->shdr.ELFW(e,LIBELFBITS);
     221        1038 :   assert (result != NULL);
     222             : 
     223        1038 : out:
     224        1038 :   return result;
     225             : }
     226             : 
     227             : static bool
     228      410959 : scn_valid (Elf_Scn *scn)
     229             : {
     230      410959 :   if (scn == NULL)
     231             :     return false;
     232             : 
     233      410958 :   if (unlikely (scn->elf->state.elf.ehdr == NULL))
     234             :     {
     235           0 :       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
     236           0 :       return false;
     237             :     }
     238             : 
     239      410958 :   if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
     240             :     {
     241           0 :       __libelf_seterrno (ELF_E_INVALID_CLASS);
     242           0 :       return false;
     243             :     }
     244             : 
     245             :   return true;
     246             : }
     247             : 
     248             : ElfW2(LIBELFBITS,Shdr) *
     249             : internal_function
     250      205926 : __elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
     251             : {
     252             :   ElfW2(LIBELFBITS,Shdr) *result;
     253             : 
     254      205926 :   if (!scn_valid (scn))
     255             :     return NULL;
     256             : 
     257      205926 :   result = scn->shdr.ELFW(e,LIBELFBITS);
     258      205926 :   if (result == NULL)
     259             :     {
     260        1032 :       rwlock_unlock (scn->elf->lock);
     261             :       rwlock_wrlock (scn->elf->lock);
     262        1032 :       result = scn->shdr.ELFW(e,LIBELFBITS);
     263             :       if (result == NULL)
     264        1032 :         result = load_shdr_wrlock (scn);
     265             :     }
     266             : 
     267             :   return result;
     268             : }
     269             : 
     270             : ElfW2(LIBELFBITS,Shdr) *
     271             : internal_function
     272           6 : __elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
     273             : {
     274             :   ElfW2(LIBELFBITS,Shdr) *result;
     275             : 
     276           6 :   if (!scn_valid (scn))
     277             :     return NULL;
     278             : 
     279           6 :   result = scn->shdr.ELFW(e,LIBELFBITS);
     280           6 :   if (result == NULL)
     281           6 :     result = load_shdr_wrlock (scn);
     282             : 
     283             :   return result;
     284             : }
     285             : 
     286             : ElfW2(LIBELFBITS,Shdr) *
     287      205027 : elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
     288             : {
     289             :   ElfW2(LIBELFBITS,Shdr) *result;
     290             : 
     291      205027 :   if (!scn_valid (scn))
     292             :     return NULL;
     293             : 
     294             :   rwlock_rdlock (scn->elf->lock);
     295      205026 :   result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
     296             :   rwlock_unlock (scn->elf->lock);
     297             : 
     298      205026 :   return result;
     299             : }

Generated by: LCOV version 1.13