LCOV - code coverage report
Current view: top level - libelf - elf32_getshdr.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 82.5 % 103 85
Test Date: 2025-08-30 14:31:09 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 73.2 % 56 41

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

Generated by: LCOV version 2.0-1